diff --git a/.circleci/README.md b/.circleci/README.md index 22b20bc8c267..b3e879574689 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -2,7 +2,7 @@ ### Docker images -The docker images are build locally on the developer machine: +The docker images are built locally on the developer machine: ```sh cd .circleci/docker/ @@ -13,7 +13,7 @@ docker push ethereum/solidity-buildpack-deps:ubuntu2404- The current revisions per docker image are stored in [circle ci pipeline parameters](https://github.com/CircleCI-Public/api-preview-docs/blob/master/docs/pipeline-parameters.md#pipeline-parameters) called `-docker-image-rev` (e.g., `ubuntu-2404-docker-image-rev`). Please update the value assigned to the parameter(s) corresponding to the docker image(s) being updated at the time of the update. Please verify that the value assigned to the parameter matches the revision part of the docker image tag (`` in the docker build/push snippet shown above). Otherwise, the docker image used by circle ci and the one actually pushed to docker hub will differ. -Once the docker image has been built and pushed to Dockerhub, you can find it at: +Once the docker image has been built and pushed to Docker Hub, you can find it at: https://hub.docker.com/r/ethereum/solidity-buildpack-deps:ubuntu2404- diff --git a/.circleci/build_win.ps1 b/.circleci/build_win.ps1 index 730bb6319586..e95caa7c1cf6 100644 --- a/.circleci/build_win.ps1 +++ b/.circleci/build_win.ps1 @@ -18,7 +18,7 @@ else { mkdir build cd build $boost_dir=(Resolve-Path $PSScriptRoot\..\deps\boost\lib\cmake\Boost-*) -..\deps\cmake\bin\cmake -G "Visual Studio 16 2019" -DBoost_DIR="$boost_dir\" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_INSTALL_PREFIX="$PSScriptRoot\..\upload" -DUSE_Z3=OFF .. +..\deps\cmake\bin\cmake -G "Visual Studio 16 2019" -DBoost_DIR="$boost_dir\" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_INSTALL_PREFIX="$PSScriptRoot\..\upload" .. if ( -not $? ) { throw "CMake configure failed." } msbuild solidity.sln /p:Configuration=Release /m:10 /v:minimal if ( -not $? ) { throw "Build failed." } diff --git a/.circleci/config.yml b/.circleci/config.yml index 63360e3bffe0..a4adbfbb3bd4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,25 +9,29 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-25 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:b3f321fb2d8e7a41ca9328672061c1840e5cd3fb5be503aa158d1c508deacf0a" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-26 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" + ubuntu-2204-docker-image: + type: string + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-2 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:877fcc2589779f8245770711d10db92eda97d338dae76b6a9f27dde1a41b3aa0" ubuntu-2404-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-1 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:5d6d27551104321a30326d6024bd4e96d9d899a97a78eb9feea364996f1d18b5" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-3 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ef6a91d7f1434c67fb9e05c6136d80f71c0ad9198479e1a88e3437680993cda4" ubuntu-2404-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-2 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:bc99a858ba18e088c1cb889ce631e3e707bb3348f0ae452bfe69116dbb931173" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-4 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:97fb2d1bc002b3624161f539a1d29543c0e6c6f4d9a61f611b9b60e99e18f377" ubuntu-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-6 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:8883fa2845bbc1e0922af60439313666e4ba325f67a117e17d78cca3ea6589b3" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-10 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:bd55d9a3b13c88608709ec442188c414d30f4c49f23dc2ce8b76bf8c90603fc7" emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. - # solbuildpackpusher/solidity-buildpack-deps:emscripten-17 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c57f2bfb8c15d70fe290629358dd1c73dc126e3760f443b54764797556b887d4" + # solbuildpackpusher/solidity-buildpack-deps:emscripten-20 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:98f963ed799a0d206ef8e7b5475f847e0dea53b7fdea9618bbc6106a62730bd2" evm-version: type: string default: cancun @@ -503,15 +507,6 @@ defaults: MAKEFLAGS: -j5 CPUs: 5 - - base_python_small: &base_python_small - docker: - - image: cimg/python:3.6 - resource_class: small - environment: &base_python_small_env - TERM: xterm - MAKEFLAGS: -j 2 - CPUs: 2 - - base_ubuntu_clang: &base_ubuntu_clang docker: - image: << pipeline.parameters.ubuntu-clang-ossfuzz-docker-image >> @@ -560,6 +555,42 @@ defaults: MAKEFLAGS: -j 10 CPUs: 10 + - base_ubuntu2204: &base_ubuntu2204 + docker: + - image: << pipeline.parameters.ubuntu-2204-docker-image >> + environment: &base_ubuntu2204_env + TERM: xterm + CC: gcc + CXX: g++ + MAKEFLAGS: -j 3 + CPUs: 3 + + - base_ubuntu2204_large: &base_ubuntu2204_large + <<: *base_ubuntu2204 + resource_class: large + environment: &base_ubuntu2204_large_env + <<: *base_ubuntu2204_env + MAKEFLAGS: -j 5 + CPUs: 5 + + - base_ubuntu2204_clang: &base_ubuntu2204_clang + docker: + - image: << pipeline.parameters.ubuntu-2204-docker-image >> + environment: &base_ubuntu2204_clang_env + TERM: xterm + CC: clang + CXX: clang++ + MAKEFLAGS: -j 3 + CPUs: 3 + + - base_ubuntu2204_clang_large: &base_ubuntu2204_clang_large + <<: *base_ubuntu2204_clang + resource_class: large + environment: &base_ubuntu2204_clang_large_env + <<: *base_ubuntu2204_clang_env + MAKEFLAGS: -j 5 + CPUs: 5 + - base_ubuntu2404: &base_ubuntu2404 docker: - image: << pipeline.parameters.ubuntu-2404-docker-image >> @@ -769,9 +800,6 @@ defaults: name: t_native_compile_ext_euler project: euler binary_type: native - # NOTE: test suite disabled due to dependence on a specific version of Hardhat - # which does not support shanghai EVM. - compile_only: 1 resource_class: medium - job_native_test_ext_yield_liquidator: &job_native_test_ext_yield_liquidator @@ -815,6 +843,8 @@ defaults: binary_type: native image: cimg/rust:1.74.0-node resource_class: medium + # TODO: Use nightly Foundry builds after https://github.com/PaulRBerg/prb-math/issues/248 is fixed + foundry_version: "v0.3.0" - job_native_test_ext_elementfi: &job_native_test_ext_elementfi <<: *requires_b_ubu_static @@ -865,7 +895,7 @@ defaults: jobs: chk_spelling: - <<: *base_python_small + <<: *base_ubuntu2404_small steps: - checkout - attach_workspace: @@ -876,11 +906,7 @@ jobs: pip install --user codespell - run: name: Check spelling - command: | - ~/.local/bin/codespell \ - --skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt,deps" \ - --ignore-words scripts/codespell_whitelist.txt \ - --exclude-file scripts/codespell_ignored_lines.txt + command: ~/.local/bin/codespell - matrix_notify_failure_unless_pr chk_docs_examples: @@ -918,7 +944,7 @@ jobs: - matrix_notify_failure_unless_pr chk_errorcodes: - <<: *base_python_small + <<: *base_ubuntu2404_small steps: - checkout - run: @@ -1023,6 +1049,8 @@ jobs: # See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105562#c27 CMAKE_OPTIONS: -DSANITIZE=address -DPEDANTIC=OFF CMAKE_BUILD_TYPE: Release + # Set the number of jobs to two instead of the default three, so that we do not run out of memory + MAKEFLAGS: -j 2 steps: - build @@ -1058,10 +1086,10 @@ jobs: # to avoid glibc incompatibilities. # See: https://github.com/ethereum/solidity/issues/13954 # On large runs 2x faster than on medium. 3x on xlarge. - <<: *base_ubuntu2004_xlarge + <<: *base_ubuntu2404_xlarge environment: - <<: *base_ubuntu2004_xlarge_env - CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DSOLC_STATIC_STDLIBS=ON + <<: *base_ubuntu2404_xlarge_env + CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DSOLC_LINK_STATIC=ON steps: - checkout - run_build @@ -1078,16 +1106,18 @@ jobs: - solc/solc-static-linux - matrix_notify_failure_unless_pr - # Builds in C++20 mode and uses debug build in order to speed up. - # Do *NOT* store any artifacts or workspace as we don't run tests on this build. - b_ubu_cxx20: - <<: *base_ubuntu2404_large + b_ubu_2204: + <<: *base_ubuntu2204_large + steps: + - checkout + - run_build + - matrix_notify_failure_unless_pr + + b_ubu_2204_clang: + <<: *base_ubuntu2204_clang_large environment: - <<: *base_ubuntu2404_large_env - CMAKE_BUILD_TYPE: Debug - # gold is more memory-efficient than the default, allows us to stay with the "large" resource class without OOM errors - CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS=-fuse-ld=gold - MAKEFLAGS: -j 6 + <<: *base_ubuntu2204_clang_large_env + MAKEFLAGS: -j 10 steps: - checkout - run_build @@ -1122,8 +1152,6 @@ jobs: <<: *base_archlinux_large environment: <<: *base_archlinux_large_env - # This can be switched off if we run out of sync with Arch. - USE_Z3: ON steps: - run: name: Install build dependencies @@ -1155,6 +1183,7 @@ jobs: environment: <<: *base_osx_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 steps: - checkout @@ -1247,6 +1276,7 @@ jobs: environment: <<: *base_archlinux_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 # For Archlinux we do not have prebuilt docker images and we would need to build evmone from source, # thus we forgo semantics tests to speed things up. @@ -1264,6 +1294,7 @@ jobs: environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 # The high parallelism in this job is causing the SMT tests to run out of memory, # so disabling for now. @@ -1313,6 +1344,7 @@ jobs: environment: <<: *base_ubuntu2404_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 @@ -1328,6 +1360,7 @@ jobs: environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 @@ -1340,6 +1373,7 @@ jobs: environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 SOLTEST_FLAGS: --no-smt steps: - soltest @@ -1372,11 +1406,12 @@ jobs: - matrix_notify_failure_unless_pr t_ems_ext_edr: - <<: *base_node_small + # Runs out of memory on the small instance + <<: *base_ubuntu2404 docker: - image: cimg/rust:1.79.0-node environment: - <<: *base_node_small_env + <<: *base_ubuntu2404_env EDR_TESTS_SOLC_PATH: /tmp/workspace/soljson.js steps: - checkout @@ -1440,6 +1475,9 @@ jobs: python2: type: boolean default: false + foundry_version: + type: string + default: "nightly" docker: - image: << parameters.image >> resource_class: << parameters.resource_class >> @@ -1453,7 +1491,8 @@ jobs: - checkout - attach_workspace: at: /tmp/workspace - - install_foundry + - install_foundry: + version: << parameters.foundry_version >> - run: name: Ensure pnpm is installed if npm is present command: | @@ -1466,6 +1505,7 @@ jobs: - run: name: Install Python 2 and make it the default command: | + sudo apt update # python is used by node-gyp to build native modules (needed for Colony). # In the 14.x image node-gyp still requires Python 2. sudo apt install python2 --assume-yes --no-install-recommends @@ -1836,8 +1876,9 @@ workflows: # build-only - b_docs: *requires_nothing - - b_ubu_cxx20: *requires_nothing - b_ubu_ossfuzz: *requires_nothing + - b_ubu_2204: *requires_nothing + - b_ubu_2204_clang: *requires_nothing # OS/X build and tests - b_osx: *requires_nothing diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index e89c414bc556..e7a0b9ddfda2 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -50,7 +50,7 @@ if [ ! -f /usr/local/lib/libz3.a ] # if this file does not exists (cache was not then brew update brew upgrade -# brew install cmake + brew install cmake brew install wget brew install coreutils brew install diffutils @@ -59,9 +59,8 @@ then brew install openjdk@11 brew install unzip - # install historical cmake - chmod +x .circleci/install_cmake.sh - .circleci/install_cmake.sh 3.29.3 + # writing to /usr/local/lib need administrative privileges. + sudo ./scripts/install_obsolete_jsoncpp_1_7_4.sh # boost boost_version="1.84.0" @@ -86,38 +85,35 @@ then rm -rf /tmp/{eldarica,eld_binaries.zip} #cvc5 - cvc5_version="1.1.2" - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-macOS-arm64-static.zip" -O /tmp/cvc5.zip - validate_checksum /tmp/cvc5.zip 2017d683d924676cb713865c6d4fcf70115c65b7ec2848f242ab938902f115b5 - unzip /tmp/cvc5.zip -x "cvc5-macOS-arm64-static/lib/cmake/*" -d /tmp - sudo mv /tmp/cvc5-macOS-arm64-static/bin/* /usr/local/bin - sudo mv /tmp/cvc5-macOS-arm64-static/include/* /usr/local/include - sudo mv /tmp/cvc5-macOS-arm64-static/lib/* /usr/local/lib - rm -rf /tmp/{cvc5-macOS-arm64-static,cvc5.zip} + cvc5_version="1.2.0" + cvc5_archive_name="cvc5-macOS-arm64-static" + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /tmp/cvc5.zip + validate_checksum /tmp/cvc5.zip 57d2d4855af3f3865110a254e415098b4e150a655f297010e27eb292f48f7da7 + sudo unzip -j /tmp/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/local/bin + rm -f /tmp/cvc5.zip # z3 - z3_version="4.12.1" + z3_version="4.13.3" z3_dir="z3-z3-$z3_version" z3_package="z3-$z3_version.tar.gz" wget "https://github.com/Z3Prover/z3/archive/refs/tags/$z3_package" - validate_checksum "$z3_package" a3735fabf00e1341adcc70394993c05fd3e2ae167a3e9bb46045e33084eb64a3 + validate_checksum "$z3_package" f59c9cf600ea57fb64ffeffbffd0f2d2b896854f339e846f48f069d23bc14ba0 tar xf "$z3_package" rm "$z3_package" cd "$z3_dir" mkdir build cd build - # Force to support for CMake 3.5, should be delete in the future version - cmake -DCMAKE_OSX_ARCHITECTURES:STRING="x86_64;arm64" -DZ3_BUILD_LIBZ3_SHARED=false -DCMAKE_POLICY_VERSION_MINIMUM=3.5 .. - make -j + cmake -DCMAKE_OSX_ARCHITECTURES:STRING="x86_64;arm64" -DZ3_BUILD_LIBZ3_SHARED=false .. + make -j "$(nproc)" sudo make install cd ../.. rm -rf "$z3_dir" # evmone - evmone_version="0.12.0" + evmone_version="0.13.0" evmone_package="evmone-${evmone_version}-darwin-arm64.tar.gz" wget "https://github.com/ethereum/evmone/releases/download/v${evmone_version}/${evmone_package}" - validate_checksum "$evmone_package" e164e0d2b985cc1cca07b501538b2e804bf872d1d8d531f9241d518a886234a6 + validate_checksum "$evmone_package" 49fe6cc35e0e13c48ca2f29a6b85a47f7b25dcd427e14254000d3bc29cddf2a6 sudo tar xzpf "$evmone_package" -C /usr/local rm "$evmone_package" fi diff --git a/.circleci/parallel_cli_tests.py b/.circleci/parallel_cli_tests.py index 45cc83aec318..42dabbf05ed3 100755 --- a/.circleci/parallel_cli_tests.py +++ b/.circleci/parallel_cli_tests.py @@ -37,10 +37,13 @@ else: filters = list(selected_tests) -subprocess.run( - ['test/cmdlineTests.sh'] + filters, - stdin=sys.stdin, - stdout=sys.stdout, - stderr=sys.stderr, - check=True, -) +try: + subprocess.run( + ['test/cmdlineTests.sh'] + filters, + stdin=sys.stdin, + stdout=sys.stdout, + stderr=sys.stderr, + check=True, + ) +except subprocess.CalledProcessError as exception: + sys.exit(exception) diff --git a/.circleci/soltest.sh b/.circleci/soltest.sh index 488201bae3ff..318192de4443 100755 --- a/.circleci/soltest.sh +++ b/.circleci/soltest.sh @@ -36,12 +36,18 @@ set -e OPTIMIZE=${OPTIMIZE:-"0"} EVM=${EVM:-"invalid"} +EOF_VERSION=${EOF_VERSION:-0} CPUs=${CPUs:-3} REPODIR="$(realpath "$(dirname "$0")/..")" IFS=" " read -r -a BOOST_TEST_ARGS <<< "$BOOST_TEST_ARGS" IFS=" " read -r -a SOLTEST_FLAGS <<< "$SOLTEST_FLAGS" +# TODO: [EOF] These won't pass on EOF yet. Reenable them when the implementation is complete. +EOF_EXCLUDES=( + --run_test='!yulStackLayout/literal_loop' +) + # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" # Test result output directory (CircleCI is reading test results from here) @@ -55,6 +61,7 @@ get_logfile_basename() { local filename="${EVM}" test "${OPTIMIZE}" = "1" && filename="${filename}_opt" test "${ABI_ENCODER_V1}" = "1" && filename="${filename}_abiv1" + (( EOF_VERSION != 0 )) && filename="${filename}_eofv${EOF_VERSION}" filename="${filename}_${run}" echo -ne "${filename}" @@ -78,10 +85,12 @@ do "--logger=HRF,error,stdout" "${BOOST_TEST_ARGS[@]}" ) + (( EOF_VERSION != 0 )) && BOOST_TEST_ARGS_RUN+=("${EOF_EXCLUDES[@]}") SOLTEST_ARGS=("--evm-version=$EVM" "${SOLTEST_FLAGS[@]}") test "${OPTIMIZE}" = "1" && SOLTEST_ARGS+=(--optimize) test "${ABI_ENCODER_V1}" = "1" && SOLTEST_ARGS+=(--abiencoderv1) + (( EOF_VERSION != 0 )) && SOLTEST_ARGS+=(--eof-version "$EOF_VERSION") BATCH_ARGS=("--batches" "$((CPUs * CIRCLE_NODE_TOTAL))" "--selected-batch" "$((CPUs * CIRCLE_NODE_INDEX + run))") diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 86c14901b22c..216b1ee3815a 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,13 +31,16 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" -DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun prague) +DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun prague osaka) +EVMS_WITH_EOF=(osaka) + # Deserialize the EVM_VALUES array if it was provided as argument or # set EVM_VALUES to the default values. IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" DEFAULT_EVM=cancun OPTIMIZE_VALUES=(0 1) +EOF_VERSIONS=(0 1) # Run for ABI encoder v1, without SMTChecker tests. EVM="${DEFAULT_EVM}" \ @@ -53,19 +56,27 @@ for OPTIMIZE in "${OPTIMIZE_VALUES[@]}" do for EVM in "${EVM_VALUES[@]}" do - ENFORCE_GAS_ARGS="" - [ "${EVM}" = "${DEFAULT_EVM}" ] && ENFORCE_GAS_ARGS="--enforce-gas-cost" - # Run SMTChecker tests only when OPTIMIZE == 0 - DISABLE_SMTCHECKER="" - [ "${OPTIMIZE}" != "0" ] && DISABLE_SMTCHECKER="-t !smtCheckerTests" + for EOF_VERSION in "${EOF_VERSIONS[@]}" + do + if (( EOF_VERSION > 0 )) && [[ ! " ${EVMS_WITH_EOF[*]} " == *" $EVM "* ]]; then + continue + fi + + ENFORCE_GAS_ARGS="" + [ "${EVM}" = "${DEFAULT_EVM}" ] && ENFORCE_GAS_ARGS="--enforce-gas-cost" + # Run SMTChecker tests only when OPTIMIZE == 0 + DISABLE_SMTCHECKER="" + [ "${OPTIMIZE}" != "0" ] && DISABLE_SMTCHECKER="-t !smtCheckerTests" - EVM="$EVM" \ - OPTIMIZE="$OPTIMIZE" \ - SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS" \ - BOOST_TEST_ARGS="-t !@nooptions $DISABLE_SMTCHECKER" \ - INDEX_SHIFT="$INDEX_SHIFT" \ - "${REPODIR}/.circleci/soltest.sh" + EVM="$EVM" \ + EOF_VERSION="$EOF_VERSION" \ + OPTIMIZE="$OPTIMIZE" \ + SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS" \ + BOOST_TEST_ARGS="-t !@nooptions $DISABLE_SMTCHECKER" \ + INDEX_SHIFT="$INDEX_SHIFT" \ + "${REPODIR}/.circleci/soltest.sh" - INDEX_SHIFT=$((INDEX_SHIFT + 1)) + INDEX_SHIFT=$((INDEX_SHIFT + 1)) + done done done diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 000000000000..df31cd316abd --- /dev/null +++ b/.codespellrc @@ -0,0 +1,4 @@ +[codespell] +skip = .git,deps,LICENSE,*.enc,Dockerfile*,codespell_whitelist.txt,codespell_ignored_lines.txt +ignore-words = scripts/codespell_whitelist.txt +exclude-file = scripts/codespell_ignored_lines.txt diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 30c09039ef79..b4f42fd52381 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -16,8 +16,6 @@ assignees: '' - [Stack Overflow](https://ethereum.stackexchange.com/) - Ensure the issue isn't already reported. - The issue should be reproducible with the latest solidity version; however, this isn't a hard requirement and being reproducible with an older version is sufficient. - -*Delete the above section and the instructions in the sections below before submitting* --> ## Description @@ -27,8 +25,9 @@ assignees: '' ## Environment - Compiler version: +- Compilation pipeline (legacy, IR, EOF): - Target EVM version (as per compiler settings): -- Framework/IDE (e.g. Truffle or Remix): +- Framework/IDE (e.g. Foundry, Hardhat, Remix): - EVM execution environment / backend / blockchain client: - Operating system: diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 7ec729b1c7a3..328ff76e22c0 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -18,8 +18,6 @@ assignees: '' - Ensure the issue isn't already reported (check `feature` and `language design` labels). - If you feel uncertain about your feature request, perhaps it's better to open a language design or feedback forum thread via the issue selector, or by going to the forum directly. - [Solidity forum](https://forum.soliditylang.org/) - -*Delete the above section and the instructions in the sections below before submitting* --> ## Abstract diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d982c43f2b59..0b344728220c 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,4 +1,4 @@ -name: Check stale issues and pull requests +name: Check stale pull requests on: workflow_dispatch: @@ -6,12 +6,12 @@ on: - cron: '0 12 * * *' permissions: - issues: write pull-requests: write env: - BEFORE_ISSUE_STALE: 90 - BEFORE_ISSUE_CLOSE: 7 + # NOTE: We set the parameters below to -1, so issues will never be marked as stale or closed automatically. + BEFORE_ISSUE_STALE: -1 + BEFORE_ISSUE_CLOSE: -1 BEFORE_PR_STALE: 14 BEFORE_PR_CLOSE: 7 @@ -24,17 +24,7 @@ jobs: debug-only: false days-before-issue-stale: ${{ env.BEFORE_ISSUE_STALE }} days-before-issue-close: ${{ env.BEFORE_ISSUE_CLOSE }} - stale-issue-message: | - This issue has been marked as stale due to inactivity for the last ${{ env.BEFORE_ISSUE_STALE }} days. - It will be automatically closed in ${{ env.BEFORE_ISSUE_CLOSE }} days. - close-issue-message: | - Hi everyone! This issue has been automatically closed due to inactivity. - If you think this issue is still relevant in the latest Solidity version and you have something to [contribute](https://docs.soliditylang.org/en/latest/contributing.html), feel free to reopen. - However, unless the issue is a concrete proposal that can be implemented, we recommend starting a language discussion on the [forum](https://forum.soliditylang.org) instead. ascending: true - stale-issue-label: stale - close-issue-label: 'closed due inactivity' - exempt-issue-labels: 'bug :bug:,epic,roadmap,selected for development,must have,must have eventually,smt' stale-pr-message: | This pull request is stale because it has been open for ${{ env.BEFORE_PR_STALE }} days with no activity. It will be closed in ${{ env.BEFORE_PR_CLOSE }} days unless the `stale` label is removed. diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c36ff73b436..d95b7213ebe6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.28") +set(PROJECT_VERSION "0.8.29") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) @@ -61,6 +61,11 @@ if (NOT IGNORE_VENDORED_DEPENDENCIES) include(fmtlib) include(nlohmann-json) include(range-v3) +else () + message(WARNING "-- Ignoring vendored dependencies. Will use installed versions if found. Versions may differ from the ones the compiler was tested with. Make sure to run the test suite and thoroughly test the resulting binaries before using them in production.") + find_package(fmt REQUIRED) + find_package(nlohmann_json REQUIRED) + find_package(range-v3 REQUIRED) endif() find_package(Threads) @@ -90,58 +95,31 @@ configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/license.h.in" include/lice include(EthOptions) configure_project(TESTS) -set(TESTED_Z3_VERSION "4.12.1") -set(MINIMUM_Z3_VERSION "4.8.16") -find_package(Z3) -if (${Z3_FOUND}) - if (${STRICT_Z3_VERSION}) - if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${TESTED_Z3_VERSION})) - message( - FATAL_ERROR - "SMTChecker tests require Z3 ${TESTED_Z3_VERSION} for all tests to pass.\n\ -Build with -DSTRICT_Z3_VERSION=OFF if you want to use a different version. \ -You can also use -DUSE_Z3=OFF to build without Z3. In both cases use --no-smt when running tests." - ) - endif() - else() - if ("${Z3_VERSION_STRING}" VERSION_LESS ${MINIMUM_Z3_VERSION}) - message( - FATAL_ERROR - "Solidity requires Z3 ${MINIMUM_Z3_VERSION} or newer. You can also use -DUSE_Z3=OFF to build without Z3." - ) - endif() - endif() -endif() -if(${USE_Z3_DLOPEN}) - add_definitions(-DHAVE_Z3) - add_definitions(-DHAVE_Z3_DLOPEN) - find_package(Python3 COMPONENTS Interpreter) - if(${Z3_FOUND}) - get_target_property(Z3_HEADER_HINTS z3::libz3 INTERFACE_INCLUDE_DIRECTORIES) - endif() - find_path(Z3_HEADER_PATH z3.h HINTS ${Z3_HEADER_HINTS}) - if(Z3_HEADER_PATH) - set(Z3_FOUND TRUE) - else() - message(SEND_ERROR "Dynamic loading of Z3 requires Z3 headers to be present at build time.") - endif() - if(NOT ${Python3_FOUND}) - message(SEND_ERROR "Dynamic loading of Z3 requires Python 3 to be present at build time.") - endif() - if(${SOLC_LINK_STATIC}) - message(SEND_ERROR "solc cannot be linked statically when dynamically loading Z3.") - endif() -elseif (${Z3_FOUND}) - add_definitions(-DHAVE_Z3) - message("Z3 SMT solver found. This enables optional SMT checking with Z3.") -endif() - -find_program(CVC5_PATH cvc5) - -if (NOT (${Z3_FOUND} OR CVC5_PATH)) - message("No SMT solver found (or it has been forcefully disabled). Optional SMT checking will not be available.\ - \nPlease install Z3 or cvc5 or remove the option disabling them (USE_Z3).") +if(EMSCRIPTEN) + set(TESTED_Z3_VERSION "4.13.3") + set(MINIMUM_Z3_VERSION "4.8.16") + find_package(Z3) + if (${Z3_FOUND}) + add_definitions(-DEMSCRIPTEN_BUILD) + if (${STRICT_Z3_VERSION}) + if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${TESTED_Z3_VERSION})) + message( + FATAL_ERROR + "SMTChecker tests require Z3 ${TESTED_Z3_VERSION} for all tests to pass.\n" + ) + endif() + else() + if ("${Z3_VERSION_STRING}" VERSION_LESS ${MINIMUM_Z3_VERSION}) + message( + FATAL_ERROR + "Solidity requires Z3 ${MINIMUM_Z3_VERSION} or newer." + ) + endif() + endif() + else() + message(FATAL_ERROR "Solidity requires Z3 for emscripten build.") + endif() endif() add_subdirectory(libsolutil) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 4c75649ae8a0..898042b7f8c3 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -3,10 +3,10 @@ ## Our Pledge In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and +contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal +level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards diff --git a/Changelog.md b/Changelog.md index d41d62823a1c..978cff2b587f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,48 @@ +### 0.8.29 (2025-03-12) + +Language Features: + * Allow relocating contract storage to an arbitrary location. + + +Compiler Features: + * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. + * ethdebug: Experimental support for instructions and source locations. + * EVM: Support for the EVM version "Osaka". + * EVM Assembly Import: Allow enabling opcode-based optimizer. + * General: The experimental EOF backend implements a subset of EOF sufficient to compile arbitrary high-level Solidity syntax via IR with optimization enabled. + * SMTChecker: Support ``block.blobbasefee`` and ``blobhash``. + * SMTChecker: The option ``--model-checker-print-query`` no longer requires ``--model-checker-solvers smtlib2``. + * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). + * Yul Parser: Make name clash with a builtin a non-fatal error. + + +Bugfixes: + * Commandline Interface: Report StackTooDeep errors in compiler mode as proper errors instead of printing diagnostic information meant for internal compiler errors. + * Error Reporting: Fix error locations not being shown for source files with empty names. + * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. + * Metadata: Fix custom cleanup sequence missing from metadata when other optimizer settings have default values. + * SMTChecker: Fix internal compiler error when analyzing overflowing expressions or bitwise negation of unsigned types involving constants. + * SMTChecker: Fix reporting on targets that are safe in the context of one contract but unsafe in the context of another contract. + * SMTChecker: Fix SMT logic error when analyzing cross-contract getter call with BMC. + * SMTChecker: Fix SMT logic error when contract deployment involves string literal to fixed bytes conversion. + * SMTChecker: Fix SMT logic error when external call has extra effectless parentheses. + * SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals. + * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. + * SMTChecker: Fix wrong encoding of string literals as arguments of ``ecrecover`` precompile. + * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. + * TypeChecker: Fix spurious compilation errors due to incorrect computation of contract storage size which erroneously included transient storage variables. + * Yul: Fix internal compiler error when a code generation error should be reported instead. + * Yul Optimizer: Fix failing debug assertion due to dereferencing of an empty ``optional`` value. + + +Build system: + * Linux release builds are fully static again and no longer depend on ``glibc``. + * Switch from C++17 to C++20 as the target standard. + + +Solc-Js: + * The wrapper now requires at least nodejs v12. + ### 0.8.28 (2024-10-09) Language Features: @@ -1423,7 +1468,7 @@ Language Features: * Introduce ``virtual`` and ``override`` keywords. * Modify ``push(element)`` for dynamic storage arrays such that it does not return the new length anymore. * Yul: Introduce ``leave`` statement that exits the current function. - * JSON AST: Add the function selector of each externally-visible FunctonDefinition to the AST JSON export. + * JSON AST: Add the function selector of each externally-visible FunctionDefinition to the AST JSON export. Compiler Features: * Allow revert strings to be stripped from the binary using the ``--revert-strings`` option or the ``settings.debug.revertStrings`` setting. diff --git a/README.md b/README.md index 2fea599c14e3..1da397250b13 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ You can talk to us on Gitter and Matrix, tweet at us on X (previously Twitter) or create a new topic in the Solidity forum. Questions, feedback, and suggestions are welcome! -Solidity is a statically typed, contract-oriented, high-level language for implementing smart contracts on the Tron platform. +Solidity is a statically-typed, contract-oriented, high-level language for implementing smart contracts on the Tron platform. For a good overview and starting point, please check out the official [Solidity Language Portal](https://soliditylang.org). diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 8ca2e7f96ed3..f55384230aa4 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -76,7 +76,7 @@ At least a day before the release: - [ ] Create a pull request in solc-bin and merge. ### Homebrew and MacOS - - [ ] Update the version and the hash (``sha256sum solidity_$VERSION.tar.gz``) in the [``solidity`` formula in Homebrew core repository](https://github.com/Homebrew/homebrew-core/blob/master/Formula/solidity.rb). + - [ ] Update the version and the hash (``sha256sum solidity_$VERSION.tar.gz``) in the [``solidity`` formula in Homebrew core repository](https://github.com/Homebrew/homebrew-core/blob/master/Formula/s/solidity.rb). ### Docker - [ ] Run ``./scripts/docker_deploy_manual.sh v$VERSION``. @@ -94,7 +94,8 @@ At least a day before the release: **SERIOUSLY: DO NOT PROCEED EARLIER!!!** - [ ] *After* the package with the static build is *published*, use it to create packages for older Ubuntu versions. Copy the static package to the [``~ethereum/ethereum`` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum) - for the destination series ``Trusty``, ``Xenial`` and ``Bionic`` while selecting ``Copy existing binaries``. + for the destination series ``Trusty``, ``Xenial``, ``Bionic``, and ``Focal`` + while selecting ``Copy existing binaries``. ### Release solc-js - [ ] Wait until solc-bin was properly deployed. You can test this via remix - a test run through remix is advisable anyway. @@ -120,4 +121,5 @@ At least a day before the release: - [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) - [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org) - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes). + - [ ] Bump vendored dependencies. - [ ] Lean back, wait for bug reports and repeat from step 1 :). diff --git a/ReviewChecklist.md b/ReviewChecklist.md index 3f0af6f981d2..35563d890712 100644 --- a/ReviewChecklist.md +++ b/ReviewChecklist.md @@ -123,7 +123,7 @@ The following points are all covered by the coding style but come up so often th - If it is a bugfix: - [ ] **The PR must include tests that reproduce the bug.** - [ ] **Are there gaps in test coverage of the buggy feature?** Fill them by adding more tests. - - [ ] **Try to break it.** Can you of any similar features that could also be buggy? + - [ ] **Try to break it.** Can you think of any similar features that could also be buggy? Play with the repro and include prominent variants as separate test cases, even if they don't trigger a bug. - [ ] **Positive cases (code that compiles) should have a semantic test.** - [ ] **Negative cases (code with compilation errors) should have a syntax test.** diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 4cf3927d1d06..ab90c3f2035a 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -89,9 +89,15 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA # Additional GCC-specific compiler settings. if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") - # Check that we've got GCC 8.0 or newer. - if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)) - message(FATAL_ERROR "${PROJECT_NAME} requires g++ 8.0 or greater.") + # Check that we've got GCC 11.0 or newer. + if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0)) + message(FATAL_ERROR "${PROJECT_NAME} requires g++ 11.0 or greater.") + endif () + + # GCC 12 emits warnings for string concatenations with operator+ under O3 + # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105651 + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0) + add_compile_options(-Wno-error=restrict) endif () # Use fancy colors in the compiler diagnostics @@ -99,11 +105,13 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA # Additional Clang-specific compiler settings. elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - # Check that we've got clang 7.0 or newer. - if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)) - message(FATAL_ERROR "${PROJECT_NAME} requires clang++ 7.0 or greater.") + # Check that we've got clang 14.0 or newer. + if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0)) + message(FATAL_ERROR "${PROJECT_NAME} requires clang++ 14.0 or greater.") endif () + # use std::invoke_result, superseding std::result_of which has been removed in c++20 + add_compile_definitions(BOOST_ASIO_HAS_STD_INVOKE_RESULT) if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") # Set stack size to 32MB - by default Apple's clang defines a stack size of 8MB. # Normally 16MB is enough to run all tests, but it will exceed the stack, if -DSANITIZE=address is used. @@ -162,6 +170,10 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_TABLE_GROWTH=1") # Disable warnings about not being pure asm.js due to memory growth. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-almost-asm") + # Increase stack size from 5MB to 16MB to prevent stack overflow issues. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_STACK=16mb") + # Increase memory size from 16MB to 32MB since the stack size is now 16MB. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s INITIAL_MEMORY=32mb") endif() endif() @@ -260,9 +272,3 @@ if(COVERAGE) endif() add_compile_options(-g --coverage) endif() - -# SMT Solvers integration -option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON) -if(UNIX AND NOT APPLE) - option(USE_Z3_DLOPEN "Dynamically load the Z3 SMT solver instead of linking against it." OFF) -endif() diff --git a/cmake/EthToolchains.cmake b/cmake/EthToolchains.cmake index c2306bd75d11..1d5dc62f3ae5 100644 --- a/cmake/EthToolchains.cmake +++ b/cmake/EthToolchains.cmake @@ -1,6 +1,6 @@ -# Require C++17. +# Require C++20. if (NOT DEFINED CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 17) # This requires at least CMake 3.8 to accept this C++17 flag. + set(CMAKE_CXX_STANDARD 20) # This requires at least CMake 3.12 to accept this C++20 flag. endif () set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/cmake/FindZ3.cmake b/cmake/FindZ3.cmake index 092b8636b8e9..0a00fb1528c4 100644 --- a/cmake/FindZ3.cmake +++ b/cmake/FindZ3.cmake @@ -1,51 +1,47 @@ -if (USE_Z3) - # Save and clear Z3_FIND_VERSION, since the - # Z3 config module cannot handle version requirements. - set(Z3_FIND_VERSION_ORIG ${Z3_FIND_VERSION}) - set(Z3_FIND_VERSION) - # Try to find Z3 using its stock cmake files. - find_package(Z3 QUIET CONFIG) - # Restore Z3_FIND_VERSION for find_package_handle_standard_args. - set(Z3_FIND_VERSION ${Z3_FIND_VERSION_ORIG}) - set(Z3_FIND_VERSION_ORIG) +# Save and clear Z3_FIND_VERSION, since the +# Z3 config module cannot handle version requirements. +set(Z3_FIND_VERSION_ORIG ${Z3_FIND_VERSION}) +set(Z3_FIND_VERSION) +# Try to find Z3 using its stock cmake files. +find_package(Z3 QUIET CONFIG) +# Restore Z3_FIND_VERSION for find_package_handle_standard_args. +set(Z3_FIND_VERSION ${Z3_FIND_VERSION_ORIG}) +set(Z3_FIND_VERSION_ORIG) - include(FindPackageHandleStandardArgs) +include(FindPackageHandleStandardArgs) - if (Z3_FOUND) - set(Z3_VERSION ${Z3_VERSION_STRING}) - find_package_handle_standard_args(Z3 CONFIG_MODE) - else() - find_path(Z3_INCLUDE_DIR NAMES z3++.h PATH_SUFFIXES z3) - find_library(Z3_LIBRARY NAMES z3) - find_program(Z3_EXECUTABLE z3 PATH_SUFFIXES bin) +if (Z3_FOUND) + set(Z3_VERSION ${Z3_VERSION_STRING}) + find_package_handle_standard_args(Z3 CONFIG_MODE) +else() + find_path(Z3_INCLUDE_DIR NAMES z3++.h PATH_SUFFIXES z3) + find_library(Z3_LIBRARY NAMES z3) + find_program(Z3_EXECUTABLE z3 PATH_SUFFIXES bin) - if(Z3_INCLUDE_DIR AND Z3_LIBRARY) - if(Z3_EXECUTABLE) - execute_process (COMMAND ${Z3_EXECUTABLE} -version - OUTPUT_VARIABLE libz3_version_str - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) + if(Z3_INCLUDE_DIR AND Z3_LIBRARY) + if(Z3_EXECUTABLE) + execute_process (COMMAND ${Z3_EXECUTABLE} -version + OUTPUT_VARIABLE libz3_version_str + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REGEX REPLACE "^Z3 version ([0-9.]+).*" "\\1" - Z3_VERSION_STRING "${libz3_version_str}") - unset(libz3_version_str) - else() - message(WARNING "Could not determine the version of z3, since the z3 executable was not found.") - set(Z3_VERSION_STRING "0.0.0") - endif() + string(REGEX REPLACE "^Z3 version ([0-9.]+).*" "\\1" + Z3_VERSION_STRING "${libz3_version_str}") + unset(libz3_version_str) + else() + message(WARNING "Could not determine the version of z3, since the z3 executable was not found.") + set(Z3_VERSION_STRING "0.0.0") endif() - mark_as_advanced(Z3_VERSION_STRING z3_DIR) + endif() + mark_as_advanced(Z3_VERSION_STRING z3_DIR) - find_package_handle_standard_args(Z3 - REQUIRED_VARS Z3_LIBRARY Z3_INCLUDE_DIR - VERSION_VAR Z3_VERSION_STRING) + find_package_handle_standard_args(Z3 + REQUIRED_VARS Z3_LIBRARY Z3_INCLUDE_DIR + VERSION_VAR Z3_VERSION_STRING) - if (NOT TARGET z3::libz3) - add_library(z3::libz3 UNKNOWN IMPORTED) - set_property(TARGET z3::libz3 PROPERTY IMPORTED_LOCATION ${Z3_LIBRARY}) - set_property(TARGET z3::libz3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR}) - endif() + if (NOT TARGET z3::libz3) + add_library(z3::libz3 UNKNOWN IMPORTED) + set_property(TARGET z3::libz3 PROPERTY IMPORTED_LOCATION ${Z3_LIBRARY}) + set_property(TARGET z3::libz3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR}) endif() -else() - set(Z3_FOUND FALSE) endif() diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index 3fb6beb2b787..a4e40e87b6b3 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -61,7 +61,7 @@ if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES) endif() set(SOL_VERSION_COMMIT "commit.${SOL_COMMIT_HASH}") -set(SOl_VERSION_PLATFORM ETH_BUILD_PLATFORM) +set(SOL_VERSION_PLATFORM ETH_BUILD_PLATFORM) set(SOL_VERSION_BUILDINFO "commit.${SOL_COMMIT_HASH}.${ETH_BUILD_PLATFORM}") set(TMPFILE "${ETH_DST_DIR}/BuildInfo.h.tmp") diff --git a/cmake/toolchains/libfuzzer.cmake b/cmake/toolchains/libfuzzer.cmake index f9ea64860ae9..272d0bc4d6e5 100644 --- a/cmake/toolchains/libfuzzer.cmake +++ b/cmake/toolchains/libfuzzer.cmake @@ -1,7 +1,5 @@ # Inherit default options include("${CMAKE_CURRENT_LIST_DIR}/default.cmake") -# Enable Z3 -set(USE_Z3 ON CACHE BOOL "Enable Z3" FORCE) # Build fuzzing binaries set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE) # Use libfuzzer as the fuzzing back-end diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 25ab26544318..d2c9c86e7b2e 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -229,7 +229,7 @@ small * { .wy-side-nav-search { background-color: transparent !important; color: var(--color-a) !important; - box-shadow: 0 4 4 0 var(--color-a); + box-shadow: 0 4px 4px 0 var(--color-a); border-bottom: 1px solid var(--color-d) !important; } @@ -823,4 +823,4 @@ a.skip-to-content:focus { #content { scroll-margin-top: 6rem; scroll-behavior: smooth; -} \ No newline at end of file +} diff --git a/docs/assembly.rst b/docs/assembly.rst index a0a9d06dc76c..c1af2907aed8 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -209,7 +209,7 @@ Local Solidity variables are available for assignments, for example: ``assembly { signextend(, x) }`` -Since Solidity 0.6.0, the name of a inline assembly variable may not +Since Solidity 0.6.0, the name of an inline assembly variable may not shadow any declaration visible in the scope of the inline assembly block (including variable, contract and function declarations). @@ -257,6 +257,8 @@ starting from where this pointer points at and update it. There is no guarantee that the memory has not been used before and thus you cannot assume that its contents are zero bytes. There is no built-in mechanism to release or free allocated memory. +Solidity does not guarantee and does not require that the values in memory +are placed at positions aligned to a multiple of any value. Here is an assembly snippet you can use for allocating memory that follows the process outlined above: .. code-block:: yul diff --git a/docs/bugs.json b/docs/bugs.json index 9101aed8bd52..4b5dd74f8571 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -151,7 +151,7 @@ { "uid": "SOL-2021-1", "name": "KeccakCaching", - "summary": "The bytecode optimizer incorrectly re-used previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.", + "summary": "The bytecode optimizer incorrectly reused previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.", "description": "Solidity's bytecode optimizer has a step that can compute Keccak-256 hashes, if the contents of the memory are known during compilation time. This step also has a mechanism to determine that two Keccak-256 hashes are equal even if the values in memory are not known during compile time. This mechanism had a bug where Keccak-256 of the same memory content, but different sizes were considered equal. More specifically, ``keccak256(mpos1, length1)`` and ``keccak256(mpos2, length2)`` in some cases were considered equal if ``length1`` and ``length2``, when rounded up to nearest multiple of 32 were the same, and when the memory contents at ``mpos1`` and ``mpos2`` can be deduced to be equal. You maybe affected if you compute multiple Keccak-256 hashes of the same content, but with different lengths inside inline assembly. You are unaffected if your code uses ``keccak256`` with a length that is not a compile-time constant or if it is always a multiple of 32.", "link": "https://blog.soliditylang.org/2021/03/23/keccak-optimizer-bug/", "fixed": "0.8.3", @@ -200,7 +200,7 @@ "uid": "SOL-2020-7", "name": "MissingEscapingInFormatting", "summary": "String literals containing double backslash characters passed directly to external or encoding function calls can lead to a different string being used when ABIEncoderV2 is enabled.", - "description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intemediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.", + "description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intermediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.", "introduced": "0.5.14", "fixed": "0.6.8", "severity": "very low", diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 2c3b6487ae50..60fcdd049a0f 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1906,6 +1906,10 @@ "bugs": [], "released": "2024-10-09" }, + "0.8.29": { + "bugs": [], + "released": "2025-03-12" + }, "0.8.3": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", diff --git a/docs/conf.py b/docs/conf.py index f57a3b5b904c..dc52c96bdfcf 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -114,7 +114,7 @@ def get_github_username_repo(url): # General information about the project. project = 'Solidity' -project_copyright = '2016-2024, The Solidity Authors' +project_copyright = '2016-2025, The Solidity Authors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/contracts.rst b/docs/contracts.rst index 588b1da00d0b..b47b4aa4552a 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -23,6 +23,7 @@ There is no "cron" concept in Ethereum to call a function at a particular event .. include:: contracts/transient-storage.rst .. include:: contracts/constant-state-variables.rst +.. include:: contracts/custom-storage-layout.rst .. include:: contracts/functions.rst .. include:: contracts/events.rst diff --git a/docs/contracts/custom-storage-layout.rst b/docs/contracts/custom-storage-layout.rst new file mode 100644 index 000000000000..224e77425084 --- /dev/null +++ b/docs/contracts/custom-storage-layout.rst @@ -0,0 +1,57 @@ +.. index:: ! custom storage layout, ! storage layout specifier, ! layout at, ! base slot + +.. _custom-storage-layout: + +********************* +Custom Storage Layout +********************* + +A contract can define an arbitrary location for its storage using the ``layout`` specifier. +The contract's state variables, including those inherited from base contracts, +start from the specified base slot instead of the default slot zero. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.29; + + contract C layout at 0xAAAA + 0x11 { + uint[3] x; // Occupies slots 0xAABB..0xAABD + } + +As the above example shows, the specifier uses the ``layout at `` syntax +and is located in the header of a contract definition. + +The layout specifier can be placed either before or after the inheritance specifier, and can appear at most once. +The ``base-slot-expression`` must be an :ref:`integer literal` expression +that can be evaluated at compilation time and yields a value in the range of ``uint256``. + +A custom layout cannot make contract's storage "wrap around". +If the selected base slot would push the static variables past the end of storage, +the compiler will issue an error. +Note that the data areas of dynamic arrays and mappings are not affected by this check because +their layout is not linear. +Regardless of the base slot used, their locations are calculated in a way that always puts them +within the range of ``uint256`` and their sizes are not known at compilation time. + +While there are no other limits placed on the base slot, it is recommended to avoid locations that are +too close to the end of the address space. +Leaving too little space may complicate contract upgrades or cause problems for contracts that store +additional values past their allocated space using inline assembly. + +The storage layout can only be specified for the topmost contract of an inheritance tree, and +affects locations of all the storage variables in all the contracts in that tree. +Variables are laid out according to the order of their definitions and the +positions of their contracts in the :ref:`linearized inheritance hierarchy` +and a custom base slot preserves their relative positions, shifting them all by the same amount. + +The storage layout cannot be specified for abstract contracts, interfaces and libraries. +Also, it is important to note that it does *not* affect transient state variables. + +For details about storage layout and the effect of the layout specifier on it see +:ref:`layout of storage variables`. + +.. warning:: + The identifiers ``layout`` and ``at`` are not yet reserved as keywords in the language. + It is strongly recommended to avoid using them since they will become reserved in a future + breaking release. diff --git a/docs/contributing.rst b/docs/contributing.rst index bb88d1201678..3cdadef95300 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -93,7 +93,7 @@ Prerequisites For running all compiler tests you may want to optionally install a few dependencies (`evmone `_, -`libz3 `_, `Eldarica `_, +`z3 `_, `Eldarica `_, `cvc5 `). On macOS systems, some of the testing scripts expect GNU coreutils to be installed. @@ -132,13 +132,12 @@ flag to ``scripts/soltest.sh``. The ``evmone`` library should end with the file name extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS. -For running SMT tests, the ``libz3`` library must be installed and locatable -by ``cmake`` during compiler configure stage. -A few SMT tests use ``Eldarica`` instead of ``Z3``. -``Eldarica`` is a runtime dependency, its executable (``eld``) must be present in ``PATH`` for the tests to pass. +For running SMT tests, the ``z3`` executable must be present in ``PATH``. +A few SMT tests use ``Eldarica`` instead of ``z3``. +These require its executable (``eld``) to be present in ``PATH`` for the tests to pass. However, if ``Eldarica`` is not found, these tests will be automatically skipped. -If the ``libz3`` library is not installed on your system, you should disable the +If ``z3`` is not present on your system, you should disable the SMT tests by exporting ``SMT_FLAGS=--no-smt`` before running ``./scripts/tests.sh`` or running ``./scripts/soltest.sh --no-smt``. These tests are ``libsolidity/smtCheckerTests``. @@ -167,7 +166,7 @@ See especially: .. note:: Those working in a Windows environment wanting to run the above basic sets - without libz3. Using Git Bash, you use: ``./build/test/Release/soltest.exe -- --no-smt``. + without z3. Using Git Bash, you use: ``./build/test/Release/soltest.exe -- --no-smt``. If you are running this in plain Command Prompt, use ``.\build\test\Release\soltest.exe -- --no-smt``. If you want to debug using GDB, make sure you build differently than the "usual". diff --git a/docs/control-structures.rst b/docs/control-structures.rst index d58eaa8c0cb9..544390c686e8 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -239,6 +239,8 @@ to limit the amount of gas. If the creation fails (due to out-of-stack, not enough balance or other problems), an exception is thrown. +.. _salted-contract-creations: + Salted contract creations / create2 ----------------------------------- diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index f994c331d536..ad3b04098132 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -14,6 +14,7 @@ Address: 'address'; Anonymous: 'anonymous'; As: 'as'; Assembly: 'assembly' -> pushMode(AssemblyBlockMode); +At: 'at'; // not a real keyword Bool: 'bool'; Break: 'break'; Bytes: 'bytes'; @@ -54,6 +55,7 @@ Indexed: 'indexed'; Interface: 'interface'; Internal: 'internal'; Is: 'is'; +Layout: 'layout'; // not a real keyword Library: 'library'; Mapping: 'mapping'; Memory: 'memory'; diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index a344fad54470..5ad422913e98 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -52,9 +52,14 @@ symbolAliases: LBrace aliases+=importAliases (Comma aliases+=importAliases)* RBr /** * Top-level definition of a contract. */ -contractDefinition: +contractDefinition +locals [boolean layoutSet=false, boolean inheritanceSet=false] +: Abstract? Contract name=identifier - inheritanceSpecifierList? + ( + {!$layoutSet}? Layout At expression {$layoutSet = true;} + | {!$inheritanceSet}? inheritanceSpecifierList {$inheritanceSet = true;} + )* LBrace contractBodyElement* RBrace; /** * Top-level definition of an interface. @@ -379,7 +384,7 @@ expression: expression LBrack index=expression? RBrack # IndexAccess | expression LBrack startIndex=expression? Colon endIndex=expression? RBrack # IndexRangeAccess | expression Period (identifier | Address) # MemberAccess - | expression LBrace (namedArgument (Comma namedArgument)*)? RBrace # FunctionCallOptions + | expression LBrace (namedArgument (Comma namedArgument)*) RBrace # FunctionCallOptions | expression callArgumentList # FunctionCall | Payable callArgumentList # PayableConversion | Type LParen typeName RParen # MetaType @@ -420,7 +425,7 @@ inlineArrayExpression: LBrack (expression ( Comma expression)* ) RBrack; /** * Besides regular non-keyword Identifiers, some keywords like 'from' and 'error' can also be used as identifiers. */ -identifier: Identifier | From | Error | Revert | Global | Transient; +identifier: Identifier | From | Error | Revert | Global | Transient | Layout | At; literal: stringLiteral | numberLiteral | booleanLiteral | hexStringLiteral | unicodeStringLiteral; diff --git a/docs/index.rst b/docs/index.rst index f1608890d757..11765d3be559 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,7 +29,7 @@ read our :doc:`contributors guide ` for more details. .. Hint:: You can download this documentation as PDF, HTML or Epub - by clicking on the versions flyout menu in the bottom-left corner and selecting the preferred download format. + by clicking on the versions flyout menu in the bottom-right corner and selecting the preferred download format. Getting Started @@ -89,7 +89,7 @@ The English version stands as a reference. You can switch between languages by clicking on the flyout menu in the bottom-left corner and selecting the preferred language. -* `Chinese `_ +* `Chinese `_ * `French `_ * `Indonesian `_ * `Japanese `_ diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 5473dbb5240c..07d82b9c81d1 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -47,20 +47,20 @@ npm / Node.js ============= Use ``npm`` for a convenient and portable way to install ``solcjs``, a Solidity compiler. The -`solcjs` program has fewer features than the ways to access the compiler described +``solcjs`` program has fewer features than the ways to access the compiler described further down this page. The :ref:`commandline-compiler` documentation assumes you are using the full-featured compiler, ``solc``. The usage of ``solcjs`` is documented inside its own `repository `_. Note: The solc-js project is derived from the C++ -`solc` by using Emscripten, which means that both use the same compiler source code. -`solc-js` can be used in JavaScript projects directly (such as Remix). +``solc`` by using Emscripten, which means that both use the same compiler source code. +``solc-js`` can be used in JavaScript projects directly (such as Remix). Please refer to the solc-js repository for instructions. .. code-block:: bash - npm install -g solc + npm install --global solc .. note:: @@ -83,24 +83,24 @@ and runs it in a new container, passing the ``--help`` argument. docker run ethereum/solc:stable --help -You can specify release build versions in the tag. For example: - -.. code-block:: bash - - docker run ethereum/solc:stable --help - -Note +.. note:: -Specific compiler versions are supported as the Docker image tag such as `ethereum/solc:0.8.23`. We will be passing the -`stable` tag here instead of specific version tag to ensure that users get the latest version by default and avoid the issue of -an out-of-date version. + Specific compiler versions are supported as the Docker image tag such as ``ethereum/solc:0.8.23``. + We will be passing the ``stable`` tag here instead of specific version tag to ensure that users get + the latest version by default and avoid the issue of an out-of-date version. To use the Docker image to compile Solidity files on the host machine, mount a local folder for input and output, and specify the contract to compile. For example: .. code-block:: bash - docker run -v /local/path:/sources ethereum/solc:stable -o /sources/output --abi --bin /sources/Contract.sol + docker run \ + --volume "/tmp/some/local/path/:/sources/" \ + ethereum/solc:stable \ + /sources/Contract.sol \ + --abi \ + --bin \ + --output-dir /sources/output/ You can also use the standard JSON interface (which is recommended when using the compiler with tooling). When using this interface, it is not necessary to mount any directories as long as the JSON input is @@ -218,7 +218,7 @@ out-of-the-box but it is also meant to be friendly to third-party tools: - The content is mirrored to https://binaries.soliditylang.org where it can be easily downloaded over HTTPS without any authentication, rate limiting or the need to use git. -- Content is served with correct `Content-Type` headers and lenient CORS configuration so that it +- Content is served with correct ``Content-Type`` headers and lenient CORS configuration so that it can be directly loaded by tools running in the browser. - Binaries do not require installation or unpacking (exception for older Windows builds bundled with necessary DLLs). @@ -372,8 +372,8 @@ Minimum Compiler Versions The following C++ compilers and their minimum versions can build the Solidity codebase: -- `GCC `_, version 8+ -- `Clang `_, version 7+ +- `GCC `_, version 11+ +- `Clang `_, version 14+ - `MSVC `_, version 2019+ Prerequisites - macOS @@ -505,7 +505,7 @@ And for Windows: cmake -G "Visual Studio 16 2019" .. In case you want to use the version of boost installed by ``scripts\install_deps.ps1``, you will -additionally need to pass ``-DBoost_DIR="deps\boost\lib\cmake\Boost-*"`` and ``-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`` +additionally need to pass ``-DBoost_ROOT="deps/boost" -DBoost_INCLUDE_DIR="deps/boost/include"`` and ``-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`` as arguments to the call to ``cmake``. This should result in the creation of **solidity.sln** in that build directory. @@ -527,23 +527,12 @@ If you are interested what CMake options are available run ``cmake .. -LH``. SMT Solvers ----------- -Solidity can be built against Z3 SMT solver and will do so by default if -it is found in the system. Z3 can be disabled by a ``cmake`` option. - -*Note: In some cases, this can also be a potential workaround for build failures.* - - -Inside the build folder you can disable Z3, since it is enabled by default: - -.. code-block:: bash - - # disables Z3 SMT Solver. - cmake .. -DUSE_Z3=OFF +Solidity can optionally use SMT solvers, namely ``z3``, ``cvc5`` and ``Eldarica``, +but their presence is checked only at runtime, they are not needed for the build to succeed. .. note:: - Solidity can optionally use other solvers, namely ``cvc5`` and ``Eldarica``, - but their presence is checked only at runtime, they are not needed for the build to succeed. + The emscripten builds require Z3 and will statically link against it instead. The Version String in Detail ============================ diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index a8043875b9c3..1550a458e35e 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -34,6 +34,110 @@ by the above rules, state variables from different contracts do share the same s The elements of structs and arrays are stored after each other, just as if they were given as individual values. +If a contract specifies a :ref:`custom storage layout`, the slots assigned +to static storage variables are shifted according the value defined as the layout base. +Locations of dynamic arrays and mappings are also indirectly affected by this due to shifting +of the static slots they are based on. +The custom layout is specified in the most derived contract and, following the order explained +above, starting from the most base-ward contract's variables, all storage slots are adjusted. + +In the following example, contract ``C`` inherits from contracts ``A`` and ``B`` and also +specifies a custom storage base slot. +The result is that all storage variable slots of the inheritance tree are adjusted according to +the value specified by ``C``. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.29; + + struct S { + int32 x; + bool y; + } + + contract A { + uint a; + uint128 transient b; + uint constant c = 10; + uint immutable d = 12; + } + + contract B { + uint8[] e; + mapping(uint => S) f; + uint16 g; + uint16 h; + bytes16 transient i; + S s; + int8 k; + } + + contract C is A, B layout at 42 { + bytes21 l; + uint8[10] m; + bytes5[8] n; + bytes5 o; + } + +In the example, the storage layout starts with the inherited +state variable ``a`` stored directly inside the base slot (slot ``42``). +Transient, constant and immutable variables are stored in separate +locations, and thus, ``b``, ``i``, ``c`` and ``d`` have no effect on the storage layout. +Then we get to the dynamic array ``e`` and mapping ``f``. +They both reserve a whole slot whose address will be used to :ref:`calculate` +the location where their data is actually stored. +The slot cannot be shared with any other variable, because the resulting addresses must be unique. +The next two variables, ``g`` and ``h``, need 2 bytes each and can be packed together into +slot ``45``, at offsets ``0`` and ``2`` respectively. +Since ``s`` is a struct, its two members are packed contiguously, each taking up 5 bytes. +Even though they both would still fit in slot ``45``, structs and arrays always start a new slot. +Therefore, ``s`` is placed in slot ``46`` and the next variable, ``k``, in slot ``47``. +Base contracts, on the other hand, can share slots with derived ones, so ``l`` does not require an new one. +Then variable ``m``, which is an array of 10 items, gets into slot ``48`` and takes up 10 bytes. +``n`` is an array as well, but due to the size of its items, cannot fill its first slot perfectly +and spills over to the next one. +Finally, variable ``o`` ends up in slot ``51``, even though it is of the same type as items of ``n``. +As explained before, variables after structs and arrays always start a new slot. + +Putting it all together, the storage and transient storage layouts of contract ``C`` can be illustrated as follows: + +- Storage: + :: + + 42 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + 43 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee] + 44 [ffffffffffffffffffffffffffffffff] + 45 [ hhgg] + 46 [ yxxxx] + 47 [ lllllllllllllllllllllk] + 48 [ mmmmmmmmmm] + 49 [ nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn] + 50 [ nnnnnnnnnn] + 51 [ ooooo] + +- Transient storage: + :: + + 00 [iiiiiiiiiiiiiiiibbbbbbbbbbbbbbbb] + +Note that the storage specifier affects ``A`` and ``B`` only as a part of ``C``'s inheritance hierarchy. +When deployed independently, their storage starts at ``0``: + +- Storage layout of ``A``: + :: + + 00 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + +- Storage layout of ``B``: + :: + + 00 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee] + 01 [ffffffffffffffffffffffffffffffff] + 02 [ hhgg] + 03 [ yxxxx] + 04 [ k] + .. warning:: When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller @@ -464,4 +568,4 @@ Transient Storage Layout "numberOfBytes": "32" } } - } \ No newline at end of file + } diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index 847e30cb6738..fbe27533ed4a 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -982,7 +982,7 @@ no other store in between and the values of ``k`` and ``v`` did not change. This simple step is effective if run after the SSATransform and the CommonSubexpressionEliminator, because SSA will make sure that the variables -will not change and the CommonSubexpressionEliminator re-uses exactly the same +will not change and the CommonSubexpressionEliminator reuses exactly the same variable if the value is known to be the same. Prerequisites: Disambiguator, ForLoopInitRewriter. @@ -1287,7 +1287,7 @@ UnusedPruner. The SSA form we generate is detrimental to code generation because it produces many local variables. It would -be better to just re-use existing variables with assignments instead of +be better to just reuse existing variables with assignments instead of fresh variable declarations. The SSATransform rewrites diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 9ed1bd168b58..9e098b261c94 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -537,6 +537,7 @@ operations, loops should be preferred over recursive calls. Furthermore, only 63/64th of the gas can be forwarded in a message call, which causes a depth limit of a little less than 1000 in practice. +.. _delegatecall: .. index:: delegatecall, library Delegatecall and Libraries diff --git a/docs/ir-breaking-changes.rst b/docs/ir-breaking-changes.rst index db46c59b788a..b3633742b96f 100644 --- a/docs/ir-breaking-changes.rst +++ b/docs/ir-breaking-changes.rst @@ -262,6 +262,8 @@ hiding new and different behavior in existing code. Internals ========= +.. _internal-function-pointers-in-ir: + Internal function pointers -------------------------- @@ -280,6 +282,12 @@ The ID ``0`` is reserved for uninitialized function pointers which then cause a In the old code generator, internal function pointers are initialized with a special function that always causes a panic. This causes a storage write at construction time for internal function pointers in storage. +.. note:: + The compiler is free to omit internal functions that are never explicitly referenced by name. + As a consequence, assigning to a function type variable in inline assembly does not guarantee + that the assigned value will be included in the internal dispatch. + The function must also be explicitly referenced elsewhere in the code. + Cleanup ------- diff --git a/docs/metadata.rst b/docs/metadata.rst index a44d9875388a..063936a9dcde 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -134,6 +134,8 @@ explanatory purposes. }, // Required for Solidity. "evmVersion": "london", + // Optional: Only present if not null. + "eofVersion": 1, // Required for Solidity: Addresses for libraries used. "libraries": { "MyLib": "0x123123..." diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index b187ea84c74f..2f0d1d6b40d9 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -73,8 +73,9 @@ The following example shows a contract and a function using all available tags. /// @dev The Alexandr N. Tetearing algorithm could increase precision /// @param rings The number of rings from dendrochronological sample /// @return Age in years, rounded up for partial years - function age(uint256 rings) external virtual pure returns (uint256) { - return rings + 1; + /// @return Name of the tree + function age(uint256 rings) external virtual pure returns (uint256, string memory) { + return (rings + 1, "tree"); } /// @notice Returns the amount of leaves the tree has. @@ -91,8 +92,8 @@ The following example shows a contract and a function using all available tags. } contract KumquatTree is Tree, Plant { - function age(uint256 rings) external override pure returns (uint256) { - return rings + 2; + function age(uint256 rings) external override pure returns (uint256, string memory) { + return (rings + 2, "Kumquat"); } /// Return the amount of leaves that this specific kind of tree has @@ -196,7 +197,7 @@ User Documentation ------------------ The above documentation will produce the following user documentation -JSON file as output: +JSON file as output for the ``Tree`` contract: .. code-block:: json @@ -208,6 +209,10 @@ JSON file as output: "age(uint256)" : { "notice" : "Calculate tree age in years, rounded up, for live trees" + }, + "leaves()" : + { + "notice" : "Returns the amount of leaves the tree has." } }, "notice" : "You can use this contract for only the most basic simulation" @@ -243,7 +248,14 @@ file should also be produced and should look like this: { "rings" : "The number of rings from dendrochronological sample" }, - "return" : "age in years, rounded up for partial years" + "returns" : { + "_0" : "Age in years, rounded up for partial years", + "_1" : "Name of the tree" + } + }, + "leaves()" : + { + "details" : "Returns only a fixed number." } }, "title" : "A simulator for trees" diff --git a/docs/resources.rst b/docs/resources.rst index 1773859d4eaf..7c8d61afacf1 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -5,37 +5,46 @@ Resources General Resources ================= -* `Ethereum.org Developer Portal `_ +* `Ethereum.org Developers page `_ * `Ethereum StackExchange `_ -* `Solidity Portal `_ -* `Solidity Changelog `_ -* `Solidity Source Code on GitHub `_ -* `Solidity Language Users Chat `_ -* `Solidity Compiler Developers Chat `_ -* `Awesome Solidity `_ +* `Solidity website `_ +* `Solidity changelog `_ +* `Solidity codebase on GitHub `_ +* `Solidity language users chat `_ +* `Solidity compiler developers chat `_ +* `awesome-solidity `_ * `Solidity by Example `_ -* `Solidity Documentation Community Translations `_ +* `Solidity documentation community translations `_ Integrated (Ethereum) Development Environments ============================================== - * `Brownie `_ - Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine. +* `Ape `_ + A Python-based web3 development tool for compiling, testing, and interacting with smart contracts. - * `Dapp `_ +* `Brownie `_ + A Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine. + 💡 Note: As per the official docs, Brownie is no longer actively maintained. + Future releases may come sporadically - or never at all. + Check out Ape Framework (first in list) for all your python Ethereum development needs. + +* `Dapp `_ Tool for building, testing and deploying smart contracts from the command-line. - * `Foundry `_ +* `Foundry `_ Fast, portable and modular toolkit for Ethereum application development written in Rust. - * `Hardhat `_ +* `Hardhat `_ Ethereum development environment with local Ethereum network, debugging features and plugin ecosystem. - * `Remix `_ +* `Remix `_ Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. - * `Truffle `_ +* `Truffle `_ Ethereum development framework. + 💡 Note: Consensys announced the sunset of Truffle on September 21, 2023. + Current users may check out the migration path and available product support `here. + `_ Editor Integrations =================== @@ -70,6 +79,7 @@ Editor Integrations * `Ethereum Remix Visual Studio Code extension `_ Ethereum Remix extension pack for VS Code + 💡 Note: As per the official repository, this extension has been removed from the VSCODE marketplace and will be replaced by a dedicated stand-alone desktop application. * `Solidity Visual Studio Code extension, by Juan Blanco `_ Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler. @@ -82,6 +92,9 @@ Editor Integrations * `Truffle for VS Code `_ Build, debug and deploy smart contracts on Ethereum and EVM-compatible blockchains. + 💡 Note: This extension has built-in support for the Truffle Suite which is being sunset. + For information on ongoing support, migration options and FAQs, visit the `Consensys blog. + `_ Solidity Tools ============== @@ -92,9 +105,15 @@ Solidity Tools * `abi-to-sol `_ Tool to generate Solidity interface source from a given ABI JSON. +* `Aderyn `_ + Rust-based solidity smart contract static analyzer designed to help find vulnerabilities in Solidity code bases. + * `Doxity `_ Documentation Generator for Solidity. +* `ethdebug `_ + A standard debugging data format for smart contracts on Ethereum-compatible networks. + * `Ethlint `_ Linter to identify and fix style and security issues in Solidity. @@ -102,7 +121,7 @@ Solidity Tools EVM Disassembler that performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations. * `EVM Lab `_ - Rich tool package to interact with the EVM. Includes a VM, Etherchain API, and a trace-viewer with gas cost display. + A collection of tools to interact with the EVM. The package includes a VM, Etherchain API, and a trace-viewer with gas cost display. * `hevm `_ EVM debugger and symbolic execution engine. @@ -140,6 +159,9 @@ Solidity Tools * `Universal Mutator `_ A tool for mutation generation, with configurable rules and support for Solidity and Vyper. +* `Wake `_ + A Python-based Solidity development and testing framework with built-in vulnerability detectors. + Third-Party Solidity Parsers and Grammars ========================================= diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index c5b9b093c226..1780e9515f9e 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -371,6 +371,16 @@ If your ``mapping`` information must be deleted, consider using a library simila `iterable mapping `_, allowing you to traverse the keys and delete their values in the appropriate ``mapping``. +Internal Function Pointers in Upgradeable Contracts +=================================================== + +Updating the code of your contract may :ref:`invalidate the values of variables of internal function +types`. +Consider such values ephemeral and avoid storing them in state variables. +If you do, you must ensure that they never persist across code updates and are never used by +other contracts having access to the same storage space as a result of a delegatecall or account +abstraction. + Minor Details ============= diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index 92aaa847c921..5de941bf2706 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -831,11 +831,7 @@ option ``--model-checker-solvers {all,cvc5,eld,smtlib2,z3}`` or the JSON option These can be used together with the compiler's `callback mechanism `_ so that any solver binary from the system can be employed to synchronously return the results of the queries to the compiler. This can be used by both BMC and CHC depending on which solvers are called. -- ``z3`` is available - - - if ``solc`` is compiled with it; - - if a dynamic ``z3`` library of version >=4.8.x is installed in a Linux system (from Solidity 0.7.6); - - statically in ``soljson.js`` (from Solidity 0.6.9), that is, the JavaScript binary of the compiler. +- ``z3`` is available statically in ``soljson.js`` (from Solidity 0.6.9), that is, the JavaScript binary of the compiler. Otherwise it is used via its binary which must be installed in the system. .. note:: z3 version 4.8.16 broke ABI compatibility with previous versions and cannot @@ -935,9 +931,9 @@ the arguments. +-----------------------------------+--------------------------------------+ |``addmod``, ``mulmod`` |Supported precisely. | +-----------------------------------+--------------------------------------+ -|``gasleft``, ``blockhash``, |Abstracted with UF. | -|``keccak256``, ``ecrecover`` | | -|``ripemd160`` | | +|``gasleft``, ``blobhash``, |Abstracted with UF. | +|``blockhash``, ``keccak256``, | | +|``ecrecover``, ``ripemd160`` | | +-----------------------------------+--------------------------------------+ |pure functions without |Abstracted with UF | |implementation (external or | | diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 4a053d51beea..79ba8da6e5be 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -37,12 +37,23 @@ non-persistent area where function arguments are stored, and behaves mostly like data location can also be returned from functions, but it is not possible to allocate such types. +.. note:: + Arrays and structs with ``calldata`` location declared in a function body + or as its return parameters must be assigned before being used or returned. + There are certain cases in which non-trivial control flow is used and the compiler + can't properly detect the initialization. + A common workaround in such cases is to assign the affected variable to itself before + the correct initialization takes place. + .. note:: Prior to version 0.6.9 data location for reference-type arguments was limited to ``calldata`` in external functions, ``memory`` in public functions and either ``memory`` or ``storage`` in internal and private ones. Now ``memory`` and ``calldata`` are allowed in all functions regardless of their visibility. +.. note:: + Constructor parameters cannot use ``calldata`` as their data location. + .. note:: Prior to version 0.5.0 the data location could be omitted, and would default to different locations depending on the kind of variable, function type, etc., but all complex types must now give an explicit diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 27baf5485104..38d22aebdc2d 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -9,7 +9,7 @@ are used as function arguments or in assignments. Unlike :ref:`reference types `, value type declarations do not specify a data location since they are small enough to be stored on the stack. -The only exception are :ref:`state variables `. +The only exception is :ref:`state variables `. Those are by default located in storage, but can also be marked as :ref:`transient `, :ref:`constant or immutable `. @@ -204,7 +204,7 @@ must be explicit via ``payable(
)``. Explicit conversions to and from ``address`` are allowed for ``uint160``, integer literals, ``bytes20`` and contract types. -Only expressions of type ``address`` and contract-type can be converted to the type ``address +Only expressions of type ``address`` and contract type can be converted to the type ``address payable`` via the explicit conversion ``payable(...)``. For contract-type, this conversion is only allowed if the contract can receive Ether, i.e., the contract either has a :ref:`receive ` or a payable fallback function. Note that ``payable(0)`` is valid and is @@ -215,7 +215,7 @@ an exception to this rule. declare its type as ``address payable`` to make this requirement visible. Also, try to make this distinction or conversion as early as possible. - The distinction between ``address`` and ``address payable`` was introduced with version 0.5.0. + The distinction between ``address`` and ``address payable`` was introduced in version 0.5.0. Also starting from that version, contracts are not implicitly convertible to the ``address`` type, but can still be explicitly converted to ``address`` or to ``address payable``, if they have a receive or payable fallback function. @@ -344,6 +344,13 @@ You can query the deployed code for any smart contract. Use ``.code`` to get the ``bytes memory``, which might be empty. Use ``.codehash`` to get the Keccak-256 hash of that code (as a ``bytes32``). Note that ``addr.codehash`` is cheaper than using ``keccak256(addr.code)``. +.. warning:: + The output of ``addr.codehash`` may be ``0`` if the account associated with ``addr`` is empty or non-existent + (i.e., it has no code, zero balance, and zero nonce as defined by `EIP-161 `_). + If the account has no code but a non-zero balance or nonce, then ``addr.codehash`` will output the Keccak-256 hash of empty data + (i.e., ``keccak256("")`` which is equal to ``c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470``), as defined by + `EIP-1052 `_. + .. note:: All contracts can be converted to ``address`` type, so it is possible to query the balance of the current contract using ``address(this).balance``. @@ -721,7 +728,7 @@ that has the same data representation as the input, whereas ``toUFixed256x18`` r Function Types -------------- -Function types are the types of functions. Variables of function type +Function types are the types of functions. Variables of a function type can be assigned from functions and function parameters of function type can be used to pass functions to and return functions from function calls. Function types come in two flavours - *internal* and *external* functions: @@ -736,6 +743,20 @@ contract internally. External functions consist of an address and a function signature and they can be passed via and returned from external function calls. +Note that public functions of the current contract can be used both as an +internal and as an external function. To use ``f`` as an internal function, +just use ``f``, if you want to use its external form, use ``this.f``. + +If a function type variable is not initialised, calling it results +in a :ref:`Panic error`. The same happens if you call a function after using ``delete`` +on it. + +.. note:: + Lambda or inline functions are planned but not yet supported. + +Declaration syntax +^^^^^^^^^^^^^^^^^^ + Function types are notated as follows: .. code-block:: solidity @@ -752,7 +773,8 @@ omitted. Note that this only applies to function types. Visibility has to be specified explicitly for functions defined in contracts, they do not have a default. -Conversions: +Conversions +^^^^^^^^^^^ A function type ``A`` is implicitly convertible to a function type ``B`` if and only if their parameter types are identical, their return types are identical, @@ -781,18 +803,10 @@ Which makes it possible to assign a ``payable`` function pointer to a ``non-paya function pointer ensuring both types behave the same way, i.e, both cannot be used to send ether. -If a function type variable is not initialised, calling it results -in a :ref:`Panic error`. The same happens if you call a function after using ``delete`` -on it. - If external function types are used outside of the context of Solidity, they are treated as the ``function`` type, which encodes the address followed by the function identifier together in a single ``bytes24`` type. -Note that public functions of the current contract can be used both as an -internal and as an external function. To use ``f`` as an internal function, -just use ``f``, if you want to use its external form, use ``this.f``. - A function of an internal type can be assigned to a variable of an internal function type regardless of where it is defined. This includes private, internal and public functions of both contracts and libraries as well as free @@ -821,7 +835,8 @@ Libraries are excluded because they require a ``delegatecall`` and use :ref:`a d convention for their selectors `. Functions declared in interfaces do not have definitions so pointing at them does not make sense either. -Members: +Members +^^^^^^^ External (or public) functions have the following members: @@ -836,6 +851,59 @@ External (or public) functions have the following members: respectively. See :ref:`External Function Calls ` for more information. +.. _function-type-value-stability-across-contract-updates: + +Value stability across contract updates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An important aspect to consider when using values of function types is whether the value will +remain valid if the underlying code changes. + +The state of the blockchain is not completely immutable and there are multiple ways to place +different code under the same address: + +- Directly deploying different code using :ref:`salted contract creation`. +- Delegating to a different contract via :ref:`DELEGATECALL` + (upgradeable code behind a proxy contract is a common example of this). +- Account abstraction as defined by `EIP-7702 `_. + +External function types can be considered as stable as contract's ABI, which makes them very portable. +Their ABI representation always consists of a contract address and a function selector and it is +perfectly safe to store them long-term or pass them between contracts. +While it is possible for the referenced function to change or disappear, a direct external call +would be affected the same way, so there is no additional risk in such use. + +In case of internal functions, however, the value is an identifier that is strongly tied to +contract's bytecode. +The actual representation of the identifier is an implementation detail and may change between +compiler versions or even :ref:`between different backends`. +Values assigned under a given representation are deterministic (i.e. guaranteed to remain the same +as long as the source code is the same) but are easily affected by changes such as adding, removing +or reordering of functions. +The compiler is also free to remove internal functions that are never used, which may affect other identifiers. +Some representations, e.g. one where identifiers are simply jump targets, may be affected by +virtually any change, even one completely unrelated to internal functions. + +To counter this, the language limits the use of internal function types outside of the context in +which they are valid. +This is why internal function types cannot be used as parameters of external functions (or in any +other way that is exposed in contract's ABI). +However, there are still situations where it is up to the user to decide whether their use is safe or not. +For example long-term storage of such values in state variables is discouraged, but may be safe if +the contract code is never going to be updated. +It is also always possible to side-step any safeguards by using inline assembly. +Such use always needs careful consideration. + +.. note:: + The removal of unused internal functions only takes into account explicit references to + such functions by name. + Implicit references, such as assigning a new value to a function type variable in inline assembly + may still lead to the removal of the function if it is not also referenced explicitly elsewhere + in the source. + +Examples +^^^^^^^^ + Example that shows how to use the members: .. code-block:: solidity @@ -959,6 +1027,3 @@ Another example that uses external function types: exchangeRate = response; } } - -.. note:: - Lambda or inline functions are planned but not yet supported. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 644945690e02..5e67533ba43c 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -182,6 +182,8 @@ at each version. Backward compatibility is not guaranteed between each version. - Opcode ``mcopy`` is available in assembly (see `EIP-5656 `_). - Opcodes ``tstore`` and ``tload`` are available in assembly (see `EIP-1153 `_). - ``prague`` (**experimental**) +- ``osaka`` (**experimental**) + - Experimental compilation to EOF is available starting from this version. (`EIP-7692 `_) .. index:: ! standard JSON, ! --standard-json .. _compiler-api: @@ -281,72 +283,84 @@ Input Description "remappings": [ ":g=/dir" ], // Optional: Optimizer settings "optimizer": { - // Disabled by default. - // NOTE: enabled=false still leaves some optimizations on. See comments below. - // WARNING: Before version 0.8.6 omitting the 'enabled' key was not equivalent to setting - // it to false and would actually disable all the optimizations. + // Turn on the optimizer. Optional. Default: false. + // NOTE: The state of the optimizer is fully determined by the 'details' dict and this setting + // only affects its defaults - when enabled, all components default to being enabled. + // The opposite is not true - there are several components that always default to being + // enabled an can only be explicitly disabled via 'details'. + // WARNING: Before version 0.8.6 omitting this setting was not equivalent to setting + // it to false and would result in all components being disabled instead. + // WARNING: Enabling optimizations for EVMAssembly input is allowed but not necessary under normal + // circumstances. It forces the opcode-based optimizer to run again and can produce bytecode that + // is not reproducible from metadata. "enabled": true, - // Optimize for how many times you intend to run the code. + // Optimize for how many times you intend to run the code. Optional. Default: 200. // Lower values will optimize more for initial deployment cost, higher // values will optimize more for high-frequency usage. "runs": 200, - // Switch optimizer components on or off in detail. - // The "enabled" switch above provides two defaults which can be - // tweaked here. If "details" is given, "enabled" can be omitted. + // State of all optimizer components. Optional. + // Default values are determined by whether the optimizer is enabled or not. + // Note that the 'enabled' setting only affects the defaults here and has no effect when + // all values are provided explicitly. "details": { - // The peephole optimizer is always on if no details are given, - // use details to switch it off. + // Peephole optimizer (opcode-based). Optional. Default: true. + // Default for EVMAssembly input: false when optimization is not enabled. + // NOTE: Always runs (even with optimization disabled) except for EVMAssembly input or when explicitly turned off here. "peephole": true, - // The inliner is always off if no details are given, - // use details to switch it on. + // Inliner (opcode-based). Optional. Default: true when optimization is enabled. "inliner": false, - // The unused jumpdest remover is always on if no details are given, - // use details to switch it off. + // Unused JUMPDEST remover (opcode-based). Optional. Default: true. + // Default for EVMAssembly input: false when optimization is not enabled. + // NOTE: Always runs (even with optimization disabled) except for EVMAssembly input or when explicitly turned off here. "jumpdestRemover": true, - // Sometimes re-orders literals in commutative operations. + // Literal reordering (codegen-based). Optional. Default: true when optimization is enabled. + // Moves literals to the right of commutative binary operators during code generation, helping exploit associativity. "orderLiterals": false, - // Removes duplicate code blocks + // Block deduplicator (opcode-based). Optional. Default: true when optimization is enabled. + // Unifies assembly code blocks that share content. "deduplicate": false, - // Common subexpression elimination, this is the most complicated step but - // can also provide the largest gain. + // Common subexpression elimination (opcode-based). Optional. Default: true when optimization is enabled. + // This is the most complicated step but can also provide the largest gain. "cse": false, - // Optimize representation of literal numbers and strings in code. + // Constant optimizer (opcode-based). Optional. Default: true when optimization is enabled. + // Tries to find better representations of literal numbers and strings, that satisfy the + // size/cost trade-off determined by the 'runs' setting. "constantOptimizer": false, - // Use unchecked arithmetic when incrementing the counter of for loops - // under certain circumstances. It is always on if no details are given. + // Unchecked loop increment (codegen-based). Optional. Default: true. + // Use unchecked arithmetic when incrementing the counter of 'for' loops under certain circumstances. + // NOTE: Always runs (even with optimization disabled) unless explicitly turned off here. "simpleCounterForLoopUncheckedIncrement": true, - // The new Yul optimizer. Mostly operates on the code of ABI coder v2 - // and inline assembly. - // It is activated together with the global optimizer setting - // and can be deactivated here. - // Before Solidity 0.6.0 it had to be activated through this switch. + // Yul optimizer. Optional. Default: true when optimization is enabled. + // Used to optimize the IR produced by the Yul IR-based pipeline as well as inline assembly + // and utility Yul code generated by the compiler. + // NOTE: Before Solidity 0.6.0 the default was false. "yul": false, - // Tuning options for the Yul optimizer. + // Tuning options for the Yul optimizer. Optional. "yulDetails": { // Improve allocation of stack slots for variables, can free up stack slots early. - // Activated by default if the Yul optimizer is activated. + // Optional. Default: true if Yul optimizer is enabled. "stackAllocation": true, - // Select optimization steps to be applied. It is also possible to modify both the - // optimization sequence and the clean-up sequence. Instructions for each sequence - // are separated with the ":" delimiter and the values are provided in the form of - // optimization-sequence:clean-up-sequence. For more information see - // "The Optimizer > Selecting Optimizations". - // This field is optional, and if not provided, the default sequences for both - // optimization and clean-up are used. If only one of the sequences is provided - // the other will not be run. - // If only the delimiter ":" is provided then neither the optimization nor the clean-up - // sequence will be run. - // If set to an empty value, only the default clean-up sequence is used and - // no optimization steps are applied. + // Optimization step sequence. + // The general form of the value is "
:". + // The setting is optional and when omitted, default values are used for both sequences. + // If the value does not contain the ':' delimiter, it is interpreted as the main + // sequence and the default is used for the cleanup sequence. + // To make one of the sequences empty, the delimiter must be present at the first or last position. + // In particular if the whole value consists only of the delimiter, both sequences are empty. + // Note that there are several hard-coded steps that always run, even when both sequences are empty. + // For more information see "The Optimizer > Selecting Optimizations". "optimizerSteps": "dhfoDgvulfnTUtnIf..." } } }, - // Version of the EVM to compile for. + // Version of the EVM to compile for (optional). // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default) or prague. + // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default), prague (experimental) or osaka (experimental). "evmVersion": "cancun", + // EVM Object Format version to compile for (optional, experimental). + // Currently the only valid value is 1. If not specified, legacy non-EOF bytecode will be generated. + "eofVersion": null, // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is a highly EXPERIMENTAL feature, not to be used for production. This is false by default. "viaIR": true, diff --git a/docs/yul.rst b/docs/yul.rst index d39fa9198e74..57c5e035516e 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -1069,7 +1069,7 @@ by two, without the optimizer touching the constant two, you can use let double := verbatim_1i_1o(hex"600202", x) This code will result in a ``dup1`` opcode to retrieve ``x`` -(the optimizer might directly re-use result of the +(the optimizer might directly reuse result of the ``calldataload`` opcode, though) directly followed by ``600202``. The code is assumed to consume the copied value of ``x`` and produce the result @@ -1094,7 +1094,8 @@ the compiler. Violations of these restrictions can result in undefined behavior. - Control-flow should not jump into or out of verbatim blocks, - but it can jump within the same verbatim block. + but it can jump within the same verbatim block. In particular, + reverting or returning from the block is *not* allowed. - Stack contents apart from the input and output parameters should not be accessed. - The stack height difference should be exactly ``m - n`` diff --git a/libevmasm/AbstractAssemblyStack.h b/libevmasm/AbstractAssemblyStack.h index 278edf5c273b..c4eb804eea41 100644 --- a/libevmasm/AbstractAssemblyStack.h +++ b/libevmasm/AbstractAssemblyStack.h @@ -40,6 +40,10 @@ class AbstractAssemblyStack virtual std::string const* sourceMapping(std::string const& _contractName) const = 0; virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const = 0; + virtual Json ethdebug(std::string const& _contractName) const = 0; + virtual Json ethdebugRuntime(std::string const& _contractName) const = 0; + virtual Json ethdebug() const = 0; + virtual Json assemblyJSON(std::string const& _contractName) const = 0; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const = 0; diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ab26526e14c2..a0711cd41756 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -46,6 +46,7 @@ #include #include #include +#include using namespace solidity; using namespace solidity::evmasm; @@ -89,7 +90,7 @@ void Assembly::importAssemblyItemsFromJSON(Json const& _code, std::vector 1) - solUnimplemented("Add support for more code sections"); + for (size_t i = 1; i < m_codeSections.size(); ++i) + { + _out << std::endl << _prefix << "code_section_" << i << ": assembly {\n"; + Functionalizer codeSectionF(_out, _prefix + " ", _sourceCodes, *this); + for (auto const& item: m_codeSections[i].items) + codeSectionF.feed(item, _debugInfoSelection); + codeSectionF.flush(); + _out << _prefix << "}" << std::endl; + } if (!m_data.empty() || !m_subs.empty()) { @@ -437,7 +444,7 @@ std::string Assembly::assemblyString( { std::ostringstream tmp; assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes); - return tmp.str(); + return (_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "") + tmp.str(); } Json Assembly::assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList) const @@ -445,7 +452,7 @@ Json Assembly::assemblyJSON(std::map const& _sourceIndice Json root; root[".code"] = Json::array(); Json& code = root[".code"]; - // TODO: support EOF + // TODO: support EOF solUnimplementedAssert(!m_eofVersion.has_value(), "Assembly output for EOF is not yet implemented."); solAssert(m_codeSections.size() == 1); for (AssemblyItem const& item: m_codeSections.front().items) @@ -696,6 +703,49 @@ AssemblyItem Assembly::namedTag(std::string const& _name, size_t _params, size_t return AssemblyItem{Tag, m_namedTags.at(_name).id}; } +AssemblyItem Assembly::newFunctionCall(uint16_t _functionID) const +{ + solAssert(_functionID < m_codeSections.size(), "Call to undeclared function."); + solAssert(_functionID > 0, "Cannot call section 0"); + auto const& section = m_codeSections.at(_functionID); + if (section.nonReturning) + return AssemblyItem::jumpToFunction(_functionID, section.inputs, section.outputs); + else + return AssemblyItem::functionCall(_functionID, section.inputs, section.outputs); +} + +AssemblyItem Assembly::newFunctionReturn() const +{ + solAssert(m_currentCodeSection != 0, "Appending function return without begin function."); + return AssemblyItem::functionReturn(); +} + +uint16_t Assembly::createFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) +{ + size_t functionID = m_codeSections.size(); + solRequire(functionID < 1024, AssemblyException, "Too many functions for EOF"); + solAssert(m_currentCodeSection == 0, "Functions need to be declared from the main block."); + solRequire(_rets <= 127, AssemblyException, "Too many function returns."); + solRequire(_args <= 127, AssemblyException, "Too many function inputs."); + m_codeSections.emplace_back(CodeSection{_args, _rets, _nonReturning, {}}); + return static_cast(functionID); +} + +void Assembly::beginFunction(uint16_t _functionID) +{ + solAssert(m_currentCodeSection == 0, "Attempted to begin a function before ending the last one."); + solAssert(_functionID != 0, "Attempt to begin a function with id 0"); + solAssert(_functionID < m_codeSections.size(), "Attempt to begin an undeclared function."); + auto& section = m_codeSections.at(_functionID); + solAssert(section.items.empty(), "Function already defined."); + m_currentCodeSection = _functionID; +} +void Assembly::endFunction() +{ + solAssert(m_currentCodeSection != 0, "End function without begin function."); + m_currentCodeSection = 0; +} + AssemblyItem Assembly::newPushLibraryAddress(std::string const& _identifier) { h256 h(util::keccak256(_identifier)); @@ -717,6 +767,21 @@ AssemblyItem Assembly::newImmutableAssignment(std::string const& _identifier) return AssemblyItem{AssignImmutable, h}; } +AssemblyItem Assembly::newAuxDataLoadN(size_t _offset) const +{ + return AssemblyItem{AuxDataLoadN, _offset}; +} + +AssemblyItem Assembly::newSwapN(size_t _depth) const +{ + return AssemblyItem::swapN(_depth); +} + +AssemblyItem Assembly::newDupN(size_t _depth) const +{ + return AssemblyItem::dupN(_depth); +} + Assembly& Assembly::optimise(OptimiserSettings const& _settings) { optimiseInternal(_settings, {}); @@ -764,8 +829,8 @@ std::map const& Assembly::optimiseInternal( _tagsReferencedFromOutside, _settings.expectedExecutionsPerDeployment, isCreation(), - _settings.evmVersion} - .optimise(); + m_evmVersion + }.optimise(); } // TODO: verify this for EOF. if (_settings.runJumpdestRemover && !m_eofVersion.has_value()) @@ -880,7 +945,7 @@ std::map const& Assembly::optimiseInternal( ConstantOptimisationMethod::optimiseConstants( isCreation(), isCreation() ? 1 : _settings.expectedExecutionsPerDeployment, - _settings.evmVersion, + m_evmVersion, *this ); @@ -917,13 +982,101 @@ void appendBigEndianUint16(bytes& _dest, ValueT _value) assertThrow(_value <= 0xFFFF, AssemblyException, ""); appendBigEndian(_dest, 2, static_cast(_value)); } + +// Calculates maximum stack height for given code section. According to EIP5450 https://eips.ethereum.org/EIPS/eip-5450 +uint16_t calculateMaxStackHeight(Assembly::CodeSection const& _section) +{ + static auto constexpr UNVISITED = std::numeric_limits::max(); + + AssemblyItems const& items = _section.items; + solAssert(!items.empty()); + uint16_t overallMaxHeight = _section.inputs; + std::stack worklist; + std::vector maxStackHeights(items.size(), UNVISITED); + + // Init first item stack height to number of inputs to the code section + // maxStackHeights stores stack height for an item before the item execution + maxStackHeights[0] = _section.inputs; + // Push first item index to the worklist + worklist.push(0u); + while (!worklist.empty()) + { + size_t idx = worklist.top(); + worklist.pop(); + AssemblyItem const& item = items[idx]; + size_t stackHeightChange = item.deposit(); + size_t currentMaxHeight = maxStackHeights[idx]; + solAssert(currentMaxHeight != UNVISITED); + + std::vector successors; + + // Add next instruction to successors for non-control-flow-changing instructions + if ( + !(item.hasInstruction() && SemanticInformation::terminatesControlFlow(item.instruction())) && + item.type() != RelativeJump && + item.type() != RetF && + item.type() != JumpF + ) + { + solAssert(idx < items.size() - 1, "No terminating instruction."); + successors.emplace_back(idx + 1); + } + + // Add jumps destinations to successors + // TODO: Remember to add RJUMPV when it is supported. + if (item.type() == RelativeJump || item.type() == ConditionalRelativeJump) + { + auto const tagIt = std::find(items.begin(), items.end(), item.tag()); + solAssert(tagIt != items.end(), "Tag not found."); + successors.emplace_back(static_cast(std::distance(items.begin(), tagIt))); + // TODO: This assert fails until the code is not topologically sorted. Uncomment when sorting introduced. + // If backward jump the successor must be already visited. + // solAssert(idx <= successors.back() || maxStackHeights[successors.back()] != UNVISITED); + } + + solRequire( + currentMaxHeight + stackHeightChange <= std::numeric_limits::max(), + AssemblyException, + "Stack overflow in EOF function." + ); + overallMaxHeight = std::max(overallMaxHeight, static_cast(currentMaxHeight + stackHeightChange)); + currentMaxHeight += stackHeightChange; + + // Set stack height for all instruction successors + for (size_t successor: successors) + { + solAssert(successor < maxStackHeights.size()); + // Set stack height for newly visited + if (maxStackHeights[successor] == UNVISITED) + { + maxStackHeights[successor] = currentMaxHeight; + worklist.push(successor); + } + else + { + solAssert(successor < maxStackHeights.size()); + // For backward jump successor stack height must be equal + if (successor < idx) + solAssert(maxStackHeights[successor] == currentMaxHeight, "Stack height mismatch."); + + // If successor stack height is smaller update it and recalculate + if (currentMaxHeight > maxStackHeights[successor]) + { + maxStackHeights[successor] = currentMaxHeight; + worklist.push(successor); + } + } + } + } + return overallMaxHeight; +} } -std::tuple, size_t> Assembly::createEOFHeader(std::set const& _referencedSubIds) const +std::tuple, size_t> Assembly::createEOFHeader(std::set const& _referencedSubIds) const { bytes retBytecode; - std::vector codeSectionSizeOffsets; - size_t dataSectionSizeOffset; + std::vector codeSectionSizePositions; + size_t dataSectionSizePosition; retBytecode.push_back(0xef); retBytecode.push_back(0x00); @@ -938,7 +1091,7 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se for (auto const& codeSection: m_codeSections) { (void) codeSection; - codeSectionSizeOffsets.emplace_back(retBytecode.size()); + codeSectionSizePositions.emplace_back(retBytecode.size()); appendBigEndianUint16(retBytecode, 0u); // placeholder for length of code } @@ -952,7 +1105,7 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se } retBytecode.push_back(0x04); // kind=data - dataSectionSizeOffset = retBytecode.size(); + dataSectionSizePosition = retBytecode.size(); appendBigEndianUint16(retBytecode, 0u); // length of data retBytecode.push_back(0x00); // terminator @@ -960,12 +1113,12 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se for (auto const& codeSection: m_codeSections) { retBytecode.push_back(codeSection.inputs); - retBytecode.push_back(codeSection.outputs); - // TODO: Add stack height calculation - appendBigEndianUint16(retBytecode, 0xFFFFu); + // According to EOF spec function output num equals 0x80 means non-returning function + retBytecode.push_back(codeSection.nonReturning ? 0x80 : codeSection.outputs); + appendBigEndianUint16(retBytecode, calculateMaxStackHeight(codeSection)); } - return {retBytecode, codeSectionSizeOffsets, dataSectionSizeOffset}; + return {retBytecode, codeSectionSizePositions, dataSectionSizePosition}; } LinkerObject const& Assembly::assemble() const @@ -1128,6 +1281,21 @@ LinkerObject const& Assembly::assembleLegacy() const uint8_t tagPush = static_cast(pushInstruction(bytesPerTag)); uint8_t dataRefPush = static_cast(pushInstruction(bytesPerDataRef)); + LinkerObject::CodeSectionLocation codeSectionLocation; + codeSectionLocation.start = 0; + size_t assemblyItemIndex = 0; + auto assembleInstruction = [&](auto&& _addInstruction) { + size_t start = ret.bytecode.size(); + _addInstruction(); + size_t end = ret.bytecode.size(); + codeSectionLocation.instructionLocations.emplace_back( + LinkerObject::InstructionLocation{ + .start = start, + .end = end, + .assemblyItemIndex = assemblyItemIndex + } + ); + }; for (AssemblyItem const& item: items) { // store position of the invalid jump destination @@ -1137,63 +1305,81 @@ LinkerObject const& Assembly::assembleLegacy() const switch (item.type()) { case Operation: - ret.bytecode += assembleOperation(item); + assembleInstruction([&](){ + ret.bytecode += assembleOperation(item); + }); break; case Push: - ret.bytecode += assemblePush(item); + assembleInstruction([&](){ + ret.bytecode += assemblePush(item); + }); break; case PushTag: { - ret.bytecode.push_back(tagPush); - tagRefs[ret.bytecode.size()] = item.splitForeignPushTag(); - ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); + assembleInstruction([&](){ + ret.bytecode.push_back(tagPush); + tagRefs[ret.bytecode.size()] = item.splitForeignPushTag(); + ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); + }); break; } case PushData: - ret.bytecode.push_back(dataRefPush); - dataRefs.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + assembleInstruction([&]() { + ret.bytecode.push_back(dataRefPush); + dataRefs.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + }); break; case PushSub: - assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); - ret.bytecode.push_back(dataRefPush); - subRefs.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + assembleInstruction([&]() { + assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); + ret.bytecode.push_back(dataRefPush); + subRefs.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + }); break; case PushSubSize: { - assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); - auto s = subAssemblyById(static_cast(item.data()))->assemble().bytecode.size(); - item.setPushedValue(u256(s)); - unsigned b = std::max(1, numberEncodingSize(s)); - ret.bytecode.push_back(static_cast(pushInstruction(b))); - ret.bytecode.resize(ret.bytecode.size() + b); - bytesRef byr(&ret.bytecode.back() + 1 - b, b); - toBigEndian(s, byr); + assembleInstruction([&](){ + assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); + auto s = subAssemblyById(static_cast(item.data()))->assemble().bytecode.size(); + item.setPushedValue(u256(s)); + unsigned b = std::max(1, numberEncodingSize(s)); + ret.bytecode.push_back(static_cast(pushInstruction(b))); + ret.bytecode.resize(ret.bytecode.size() + b); + bytesRef byr(&ret.bytecode.back() + 1 - b, b); + toBigEndian(s, byr); + }); break; } case PushProgramSize: { - ret.bytecode.push_back(dataRefPush); - sizeRefs.push_back(static_cast(ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + assembleInstruction([&](){ + ret.bytecode.push_back(dataRefPush); + sizeRefs.push_back(static_cast(ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + }); break; } case PushLibraryAddress: { - auto const [bytecode, linkRef] = assemblePushLibraryAddress(item, ret.bytecode.size()); - ret.bytecode += bytecode; - ret.linkReferences.insert(linkRef); + assembleInstruction([&]() { + auto const [bytecode, linkRef] = assemblePushLibraryAddress(item, ret.bytecode.size()); + ret.bytecode += bytecode; + ret.linkReferences.insert(linkRef); + }); break; } case PushImmutable: - ret.bytecode.push_back(static_cast(Instruction::PUSH32)); - // Maps keccak back to the "identifier" std::string of that immutable. - ret.immutableReferences[item.data()].first = m_immutables.at(item.data()); - // Record the bytecode offset of the PUSH32 argument. - ret.immutableReferences[item.data()].second.emplace_back(ret.bytecode.size()); - // Advance bytecode by 32 bytes (default initialized). - ret.bytecode.resize(ret.bytecode.size() + 32); + assembleInstruction([&]() { + ret.bytecode.push_back(static_cast(Instruction::PUSH32)); + // Maps keccak back to the "identifier" std::string of that immutable. + ret.immutableReferences[item.data()].first = m_immutables.at(item.data()); + // Record the bytecode offset of the PUSH32 argument. + ret.immutableReferences[item.data()].second.emplace_back(ret.bytecode.size()); + // Advance bytecode by 32 bytes (default initialized). + ret.bytecode.resize(ret.bytecode.size() + 32); + }); break; case VerbatimBytecode: ret.bytecode += assembleVerbatimBytecode(item); @@ -1206,35 +1392,59 @@ LinkerObject const& Assembly::assembleLegacy() const { if (i != offsets.size() - 1) { - ret.bytecode.push_back(uint8_t(Instruction::DUP2)); - ret.bytecode.push_back(uint8_t(Instruction::DUP2)); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::DUP2)); + }); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::DUP2)); + }); } - // TODO: should we make use of the constant optimizer methods for pushing the offsets? - bytes offsetBytes = toCompactBigEndian(u256(offsets[i])); - ret.bytecode.push_back(static_cast(pushInstruction(static_cast(offsetBytes.size())))); - ret.bytecode += offsetBytes; - ret.bytecode.push_back(uint8_t(Instruction::ADD)); - ret.bytecode.push_back(uint8_t(Instruction::MSTORE)); + assembleInstruction([&]() { + // TODO: should we make use of the constant optimizer methods for pushing the offsets? + bytes offsetBytes = toCompactBigEndian(u256(offsets[i])); + ret.bytecode.push_back(static_cast(pushInstruction(static_cast(offsetBytes.size())))); + ret.bytecode += offsetBytes; + }); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::ADD)); + }); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::MSTORE)); + }); } if (offsets.empty()) { - ret.bytecode.push_back(uint8_t(Instruction::POP)); - ret.bytecode.push_back(uint8_t(Instruction::POP)); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::POP)); + }); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::POP)); + }); } immutableReferencesBySub.erase(item.data()); break; } case PushDeployTimeAddress: - ret.bytecode += assemblePushDeployTimeAddress(); + assembleInstruction([&]() { + ret.bytecode += assemblePushDeployTimeAddress(); + }); break; case Tag: - ret.bytecode += assembleTag(item, ret.bytecode.size(), true); + assembleInstruction([&](){ + ret.bytecode += assembleTag(item, ret.bytecode.size(), true); + }); break; default: - assertThrow(false, InvalidOpcode, "Unexpected opcode while assembling."); + solAssert(false, "Unexpected opcode while assembling."); } + + ++assemblyItemIndex; } + codeSectionLocation.end = ret.bytecode.size(); + + ret.codeSectionLocations.emplace_back(std::move(codeSectionLocation)); + if (!immutableReferencesBySub.empty()) throw langutil::Error( @@ -1325,22 +1535,27 @@ LinkerObject const& Assembly::assembleLegacy() const return ret; } -std::map Assembly::findReferencedContainers() const +std::map Assembly::findReferencedContainers() const { - std::set referencedSubcontainersIds; + std::set referencedSubcontainersIds; solAssert(m_subs.size() <= 0x100); // According to EOF spec - // TODO: Implement properly when opcodes referring sub containers added. - for (uint16_t i = 0; i < m_subs.size(); ++i) - referencedSubcontainersIds.insert(static_cast(i)); - // END TODO + for (auto&& codeSection: m_codeSections) + for (AssemblyItem const& item: codeSection.items) + if (item.type() == EOFCreate || item.type() == ReturnContract) + { + solAssert(item.data() <= m_subs.size(), "Invalid subcontainer index."); + auto const containerId = static_cast(item.data()); + referencedSubcontainersIds.insert(containerId); + } - std::map replacements; + std::map replacements; uint8_t nUnreferenced = 0; - for (uint8_t i = 0; i < static_cast(m_subs.size()); ++i) + for (size_t i = 0; i < m_subs.size(); ++i) { - if (referencedSubcontainersIds.count(i) > 0) - replacements[i] = static_cast(i - nUnreferenced); + solAssert(i <= std::numeric_limits::max()); + if (referencedSubcontainersIds.count(static_cast(i)) > 0) + replacements[static_cast(i)] = static_cast(i - nUnreferenced); else nUnreferenced++; } @@ -1348,6 +1563,23 @@ std::map Assembly::findReferencedContainers() const return replacements; } +std::optional Assembly::findMaxAuxDataLoadNOffset() const +{ + std::optional maxOffset = std::nullopt; + for (auto&& codeSection: m_codeSections) + for (AssemblyItem const& item: codeSection.items) + if (item.type() == AuxDataLoadN) + { + solAssert(item.data() <= std::numeric_limits::max(), "Invalid auxdataloadn index value."); + auto const offset = static_cast(item.data()); + if (!maxOffset.has_value() || offset > maxOffset.value()) + maxOffset = offset; + + } + + return maxOffset; +} + LinkerObject const& Assembly::assembleEOF() const { solAssert(m_eofVersion.has_value() && m_eofVersion == 1); @@ -1356,21 +1588,26 @@ LinkerObject const& Assembly::assembleEOF() const auto const subIdsReplacements = findReferencedContainers(); auto const referencedSubIds = keys(subIdsReplacements); - solRequire(!m_codeSections.empty(), AssemblyException, "Expected at least one code section."); - solRequire( - m_codeSections.front().inputs == 0 && m_codeSections.front().outputs == 0x80, AssemblyException, + solAssert(!m_codeSections.empty(), "Expected at least one code section."); + solAssert( + m_codeSections.front().inputs == 0 && m_codeSections.front().outputs == 0 && m_codeSections.front().nonReturning, "Expected the first code section to have zero inputs and be non-returning." ); + auto const maxAuxDataLoadNOffset = findMaxAuxDataLoadNOffset(); + // Insert EOF1 header. - auto [headerBytecode, codeSectionSizeOffsets, dataSectionSizeOffset] = createEOFHeader(referencedSubIds); + auto [headerBytecode, codeSectionSizePositions, dataSectionSizePosition] = createEOFHeader(referencedSubIds); ret.bytecode = headerBytecode; m_tagPositionsInBytecode = std::vector(m_usedTags, std::numeric_limits::max()); + std::map dataSectionRef; + std::map tagRef; for (auto&& [codeSectionIndex, codeSection]: m_codeSections | ranges::views::enumerate) { auto const sectionStart = ret.bytecode.size(); + solAssert(!codeSection.items.empty(), "Empty code section."); for (AssemblyItem const& item: codeSection.items) { // store position of the invalid jump destination @@ -1380,6 +1617,19 @@ LinkerObject const& Assembly::assembleEOF() const switch (item.type()) { case Operation: + solAssert( + item.instruction() != Instruction::DATALOADN && + item.instruction() != Instruction::RETURNCONTRACT && + item.instruction() != Instruction::EOFCREATE && + item.instruction() != Instruction::RJUMP && + item.instruction() != Instruction::RJUMPI && + item.instruction() != Instruction::CALLF && + item.instruction() != Instruction::JUMPF && + item.instruction() != Instruction::RETF && + item.instruction() != Instruction::DUPN && + item.instruction() != Instruction::SWAPN + ); + solAssert(!(item.instruction() >= Instruction::PUSH0 && item.instruction() <= Instruction::PUSH32)); ret.bytecode += assembleOperation(item); break; case Push: @@ -1392,6 +1642,32 @@ LinkerObject const& Assembly::assembleEOF() const ret.linkReferences.insert(linkRef); break; } + case RelativeJump: + case ConditionalRelativeJump: + { + ret.bytecode.push_back(static_cast(item.instruction())); + tagRef[ret.bytecode.size()] = item.relativeJumpTagID(); + appendBigEndianUint16(ret.bytecode, 0u); + break; + } + case EOFCreate: + { + ret.bytecode.push_back(static_cast(Instruction::EOFCREATE)); + solAssert(item.data() <= std::numeric_limits::max()); + auto const containerID = static_cast(item.data()); + solAssert(subIdsReplacements.count(containerID) == 1); + ret.bytecode.push_back(subIdsReplacements.at(containerID)); + break; + } + case ReturnContract: + { + ret.bytecode.push_back(static_cast(Instruction::RETURNCONTRACT)); + solAssert(item.data() <= std::numeric_limits::max()); + auto const containerID = static_cast(item.data()); + solAssert(subIdsReplacements.count(containerID) == 1); + ret.bytecode.push_back(subIdsReplacements.at(containerID)); + break; + } case VerbatimBytecode: ret.bytecode += assembleVerbatimBytecode(item); break; @@ -1401,16 +1677,87 @@ LinkerObject const& Assembly::assembleEOF() const case Tag: ret.bytecode += assembleTag(item, ret.bytecode.size(), false); break; + case AuxDataLoadN: + { + // In findMaxAuxDataLoadNOffset we already verified that unsigned data value fits 2 bytes + solAssert(item.data() <= std::numeric_limits::max(), "Invalid auxdataloadn position."); + ret.bytecode.push_back(uint8_t(Instruction::DATALOADN)); + dataSectionRef[ret.bytecode.size()] = static_cast(item.data()); + appendBigEndianUint16(ret.bytecode, item.data()); + break; + } + case CallF: + case JumpF: + { + ret.bytecode.push_back(static_cast(item.instruction())); + solAssert(item.data() <= std::numeric_limits::max(), "Invalid callf/jumpf index value."); + size_t const index = static_cast(item.data()); + solAssert(index < m_codeSections.size()); + solAssert(item.functionSignature().argsNum <= 127); + solAssert(item.functionSignature().retsNum <= 127); + solAssert(m_codeSections[index].inputs == item.functionSignature().argsNum); + solAssert(m_codeSections[index].outputs == item.functionSignature().retsNum); + // If CallF the function cannot be non-returning. + solAssert(item.type() == JumpF || !m_codeSections[index].nonReturning); + appendBigEndianUint16(ret.bytecode, item.data()); + break; + } + case RetF: + ret.bytecode.push_back(static_cast(Instruction::RETF)); + break; + case SwapN: + case DupN: + ret.bytecode.push_back(static_cast(item.instruction())); + solAssert(item.data() >= 1 && item.data() <= 256); + ret.bytecode.push_back(static_cast(item.data() - 1)); + break; default: - solThrow(InvalidOpcode, "Unexpected opcode while assembling."); + solAssert(false, "Unexpected opcode while assembling."); } } - setBigEndianUint16(ret.bytecode, codeSectionSizeOffsets[codeSectionIndex], ret.bytecode.size() - sectionStart); + if (ret.bytecode.size() - sectionStart > std::numeric_limits::max()) + // TODO: Include source location. Note that origin locations we have in debug data are + // not usable for error reporting when compiling pure Yul because they point at the optimized source. + throw Error( + 2202_error, + Error::Type::CodeGenerationError, + "Code section too large for EOF." + ); + setBigEndianUint16(ret.bytecode, codeSectionSizePositions[codeSectionIndex], ret.bytecode.size() - sectionStart); + } + + for (auto const& [refPos, tagId]: tagRef) + { + solAssert(tagId < m_tagPositionsInBytecode.size(), "Reference to non-existing tag."); + size_t tagPos = m_tagPositionsInBytecode[tagId]; + solAssert(tagPos != std::numeric_limits::max(), "Reference to tag without position."); + + ptrdiff_t const relativeJumpOffset = static_cast(tagPos) - (static_cast(refPos) + 2); + // This cannot happen in practice because we'll run into section size limit first. + if (!(-0x8000 <= relativeJumpOffset && relativeJumpOffset <= 0x7FFF)) + // TODO: Include source location. Note that origin locations we have in debug data are + // not usable for error reporting when compiling pure Yul because they point at the optimized source. + throw Error( + 2703_error, + Error::Type::CodeGenerationError, + "Relative jump too far" + ); + solAssert(relativeJumpOffset < -2 || 0 <= relativeJumpOffset, "Relative jump offset into immediate argument."); + setBigEndianUint16(ret.bytecode, refPos, static_cast(static_cast(relativeJumpOffset))); } for (auto i: referencedSubIds) - ret.bytecode += m_subs[i]->assemble().bytecode; + { + size_t const subAssemblyPositionInParentObject = ret.bytecode.size(); + auto const& subAssemblyLinkerObject = m_subs[i]->assemble(); + // Append subassembly bytecode to the parent assembly result bytecode + ret.bytecode += subAssemblyLinkerObject.bytecode; + // Add subassembly link references to parent linker object. + // Offset accordingly to subassembly position in parent object bytecode + for (auto const& [subAssemblyLinkRefPosition, linkRef]: subAssemblyLinkerObject.linkReferences) + ret.linkReferences[subAssemblyPositionInParentObject + subAssemblyLinkRefPosition] = linkRef; + } // TODO: Fill functionDebugData for EOF. It probably should be handled for new code section in the loop above. solRequire(m_namedTags.empty(), AssemblyException, "Named tags must be empty in EOF context."); @@ -1422,8 +1769,29 @@ LinkerObject const& Assembly::assembleEOF() const ret.bytecode += m_auxiliaryData; - auto dataLength = ret.bytecode.size() - dataStart; - setBigEndianUint16(ret.bytecode, dataSectionSizeOffset, dataLength); + auto const preDeployDataSectionSize = ret.bytecode.size() - dataStart; + // DATALOADN loads 32 bytes from EOF data section zero padded if reading out of data bounds. + // In our case we do not allow DATALOADN with offsets which reads out of data bounds. + auto const staticAuxDataSize = maxAuxDataLoadNOffset.has_value() ? (*maxAuxDataLoadNOffset + 32u) : 0u; + auto const preDeployAndStaticAuxDataSize = preDeployDataSectionSize + staticAuxDataSize; + + if (preDeployAndStaticAuxDataSize > std::numeric_limits::max()) + throw Error( + 3965_error, + Error::Type::CodeGenerationError, + "The highest accessed data offset exceeds the maximum possible size of the static auxdata section." + ); + + // If some data was already added to data section we need to update data section refs accordingly + if (preDeployDataSectionSize > 0) + for (auto [refPosition, staticAuxDataOffset] : dataSectionRef) + { + // staticAuxDataOffset + preDeployDataSectionSize value is already verified to fit 2 bytes because + // staticAuxDataOffset < staticAuxDataSize + setBigEndianUint16(ret.bytecode, refPosition, staticAuxDataOffset + preDeployDataSectionSize); + } + + setBigEndianUint16(ret.bytecode, dataSectionSizePosition, preDeployAndStaticAuxDataSize); return ret; } @@ -1476,10 +1844,10 @@ Assembly const* Assembly::subAssemblyById(size_t _subId) const return currentAssembly; } -Assembly::OptimiserSettings Assembly::OptimiserSettings::translateSettings(frontend::OptimiserSettings const& _settings, langutil::EVMVersion const& _evmVersion) +Assembly::OptimiserSettings Assembly::OptimiserSettings::translateSettings(frontend::OptimiserSettings const& _settings) { // Constructing it this way so that we notice changes in the fields. - evmasm::Assembly::OptimiserSettings asmSettings{false, false, false, false, false, false, _evmVersion, 0}; + OptimiserSettings asmSettings{false, false, false, false, false, false, 0}; asmSettings.runInliner = _settings.runInliner; asmSettings.runJumpdestRemover = _settings.runJumpdestRemover; asmSettings.runPeephole = _settings.runPeephole; @@ -1487,6 +1855,5 @@ Assembly::OptimiserSettings Assembly::OptimiserSettings::translateSettings(front asmSettings.runCSE = _settings.runCSE; asmSettings.runConstantOptimiser = _settings.runConstantOptimiser; asmSettings.expectedExecutionsPerDeployment = _settings.expectedExecutionsPerDeployment; - asmSettings.evmVersion = _evmVersion; return asmSettings; } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index de1ac20f2015..30b06dd367fb 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -61,12 +61,21 @@ class Assembly m_name(std::move(_name)) { // Code section number 0 has to be non-returning. - m_codeSections.emplace_back(CodeSection{0, 0x80, {}}); + m_codeSections.emplace_back(CodeSection{0, 0, true, {}}); } std::optional eofVersion() const { return m_eofVersion; } + bool supportsFunctions() const { return m_eofVersion.has_value(); } + bool supportsRelativeJumps() const { return m_eofVersion.has_value(); } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); } + + AssemblyItem newFunctionCall(uint16_t _functionID) const; + AssemblyItem newFunctionReturn() const; + uint16_t createFunction(uint8_t _args, uint8_t _rets, bool _nonReturning); + void beginFunction(uint16_t _functionID); + void endFunction(); + /// Returns a tag identified by the given name. Creates it if it does not yet exist. AssemblyItem namedTag(std::string const& _name, size_t _params, size_t _returns, std::optional _sourceID); AssemblyItem newData(bytes const& _data) { util::h256 h(util::keccak256(util::asString(_data))); m_data[h] = _data; return AssemblyItem(PushData, h); } @@ -79,6 +88,9 @@ class Assembly AssemblyItem newPushLibraryAddress(std::string const& _identifier); AssemblyItem newPushImmutable(std::string const& _identifier); AssemblyItem newImmutableAssignment(std::string const& _identifier); + AssemblyItem newAuxDataLoadN(size_t offset) const; + AssemblyItem newSwapN(size_t _depth) const; + AssemblyItem newDupN(size_t _depth) const; AssemblyItem const& append(AssemblyItem _i); AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); } @@ -91,12 +103,37 @@ class Assembly void appendLibraryAddress(std::string const& _identifier) { append(newPushLibraryAddress(_identifier)); } void appendImmutable(std::string const& _identifier) { append(newPushImmutable(_identifier)); } void appendImmutableAssignment(std::string const& _identifier) { append(newImmutableAssignment(_identifier)); } + void appendAuxDataLoadN(uint16_t _offset) { append(newAuxDataLoadN(_offset));} + void appendSwapN(size_t _depth) { append(newSwapN(_depth)); } + void appendDupN(size_t _depth) { append(newDupN(_depth)); } void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables) { append(AssemblyItem(std::move(_data), _arguments, _returnVariables)); } + AssemblyItem appendEOFCreate(ContainerID _containerId) + { + solAssert(_containerId < m_subs.size(), "EOF Create of undefined container."); + return append(AssemblyItem::eofCreate(_containerId)); + } + AssemblyItem appendReturnContract(ContainerID _containerId) + { + solAssert(_containerId < m_subs.size(), "Return undefined container ID."); + return append(AssemblyItem::returnContract(_containerId)); + } + + AssemblyItem appendFunctionCall(uint16_t _functionID) + { + return append(newFunctionCall(_functionID)); + } + + AssemblyItem appendFunctionReturn() + { + solAssert(m_currentCodeSection != 0, "Appending function return without begin function."); + return append(newFunctionReturn()); + } + AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; } @@ -113,8 +150,8 @@ class Assembly void appendToAuxiliaryData(bytes const& _data) { m_auxiliaryData += _data; } int deposit() const { return m_deposit; } - void adjustDeposit(int _adjustment) { m_deposit += _adjustment; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } - void setDeposit(int _deposit) { m_deposit = _deposit; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } + void adjustDeposit(int _adjustment) { m_deposit += _adjustment; solAssert(m_deposit >= 0); } + void setDeposit(int _deposit) { m_deposit = _deposit; solAssert(m_deposit >= 0); } std::string const& name() const { return m_name; } /// Changes the source location used for each appended item. @@ -133,12 +170,11 @@ class Assembly bool runDeduplicate = false; bool runCSE = false; bool runConstantOptimiser = false; - langutil::EVMVersion evmVersion; /// This specifies 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 gas usage. size_t expectedExecutionsPerDeployment = frontend::OptimiserSettings{}.expectedExecutionsPerDeployment; - static OptimiserSettings translateSettings(frontend::OptimiserSettings const& _settings, langutil::EVMVersion const& _evmVersion); + static OptimiserSettings translateSettings(frontend::OptimiserSettings const& _settings); }; /// Modify and return the current assembly such that creation and execution gas usage @@ -188,7 +224,10 @@ class Assembly struct CodeSection { uint8_t inputs = 0; + // Number of outputs needs to be set properly even for non-returning function. + // It matters in case of stack height calculation of the function call instruction. uint8_t outputs = 0; + bool nonReturning = false; AssemblyItems items{}; }; @@ -233,13 +272,15 @@ class Assembly std::shared_ptr sharedSourceName(std::string const& _name) const; /// Returns EOF header bytecode | code section sizes offsets | data section size offset - std::tuple, size_t> createEOFHeader(std::set const& _referencedSubIds) const; + std::tuple, size_t> createEOFHeader(std::set const& _referencedSubIds) const; LinkerObject const& assembleLegacy() const; LinkerObject const& assembleEOF() const; /// Returns map from m_subs to an index of subcontainer in the final EOF bytecode - std::map findReferencedContainers() const; + std::map findReferencedContainers() const; + /// Returns max AuxDataLoadN offset for the assembly. + std::optional findMaxAuxDataLoadNOffset() const; /// Assemble bytecode for AssemblyItem type. [[nodiscard]] bytes assembleOperation(AssemblyItem const& _item) const; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 1bc805780145..8a917986f915 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -62,19 +63,37 @@ AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const std::pair AssemblyItem::splitForeignPushTag() const { - assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); + solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); u256 combined = u256(data()); size_t subId = static_cast((combined >> 64) - 1); size_t tag = static_cast(combined & 0xffffffffffffffffULL); return std::make_pair(subId, tag); } +size_t AssemblyItem::relativeJumpTagID() const +{ + solAssert(m_type == RelativeJump || m_type == ConditionalRelativeJump); + auto const [subId, tagId] = splitForeignPushTag(); + solAssert(subId == std::numeric_limits::max(), "Relative jump to sub"); + return tagId; +} + std::pair AssemblyItem::nameAndData(langutil::EVMVersion _evmVersion) const { switch (type()) { case Operation: - return {instructionInfo(instruction(), _evmVersion).name, m_data != nullptr ? toStringInHex(*m_data) : ""}; + case EOFCreate: + case ReturnContract: + case RelativeJump: + case ConditionalRelativeJump: + case CallF: + case JumpF: + case RetF: + return {instructionInfo(instruction(), _evmVersion).name, ""}; + case SwapN: + case DupN: + return {instructionInfo(instruction(), _evmVersion).name, util::toString(static_cast(data())) }; case Push: return {"PUSH", toStringInHex(data())}; case PushTag: @@ -102,14 +121,19 @@ std::pair AssemblyItem::nameAndData(langutil::EVMVersi return {"PUSH data", toStringInHex(data())}; case VerbatimBytecode: return {"VERBATIM", util::toHex(verbatimData())}; - default: - assertThrow(false, InvalidOpcode, ""); + case AuxDataLoadN: + return {"AUXDATALOADN", util::toString(data())}; + case UndefinedItem: + solAssert(false); } + + util::unreachable(); } void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) { - assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); + solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); + solAssert(!(m_type == RelativeJump || m_type == ConditionalRelativeJump) || _subId == std::numeric_limits::max()); u256 data = _tag; if (_subId != std::numeric_limits::max()) data |= (u256(_subId) + 1) << 64; @@ -122,6 +146,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ { case Operation: case Tag: // 1 byte for the JUMPDEST + case RetF: return 1; case Push: return @@ -161,18 +186,42 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ } case VerbatimBytecode: return std::get<2>(*m_verbatimBytecode).size(); - default: - break; + case RelativeJump: + case ConditionalRelativeJump: + case AuxDataLoadN: + case JumpF: + case CallF: + return 1 + 2; + case EOFCreate: + return 2; + case ReturnContract: + return 2; + case SwapN: + return 2; + case DupN: + return 2; + case UndefinedItem: + solAssert(false); } - assertThrow(false, InvalidOpcode, ""); + + util::unreachable(); } size_t AssemblyItem::arguments() const { - if (type() == Operation) + if (type() == CallF || type() == JumpF) + return functionSignature().argsNum; + else if (type() == SwapN) + return static_cast(data()) + 1; + else if (type() == DupN) + return static_cast(data()); + else if (hasInstruction()) + { + solAssert(instruction() != Instruction::CALLF && instruction() != Instruction::JUMPF); // The latest EVMVersion is used here, since the InstructionInfo is assumed to be // the same across all EVM versions except for the instruction name. return static_cast(instructionInfo(instruction(), EVMVersion()).args); + } else if (type() == VerbatimBytecode) return std::get<0>(*m_verbatimBytecode); else if (type() == AssignImmutable) @@ -186,9 +235,17 @@ size_t AssemblyItem::returnValues() const switch (m_type) { case Operation: + case EOFCreate: + case ReturnContract: + case RelativeJump: + case ConditionalRelativeJump: + case RetF: // The latest EVMVersion is used here, since the InstructionInfo is assumed to be // the same across all EVM versions except for the instruction name. return static_cast(instructionInfo(instruction(), EVMVersion()).ret); + case SwapN: + case DupN: + return static_cast(data()) + 1; case Push: case PushTag: case PushData: @@ -203,7 +260,13 @@ size_t AssemblyItem::returnValues() const return 0; case VerbatimBytecode: return std::get<1>(*m_verbatimBytecode); - default: + case AuxDataLoadN: + return 1; + case JumpF: + case CallF: + return functionSignature().retsNum; + case AssignImmutable: + case UndefinedItem: break; } return 0; @@ -216,7 +279,16 @@ bool AssemblyItem::canBeFunctional() const switch (m_type) { case Operation: - return !isDupInstruction(instruction()) && !isSwapInstruction(instruction()); + case EOFCreate: + case ReturnContract: + case RelativeJump: + case ConditionalRelativeJump: + case CallF: + case JumpF: + case SwapN: + case DupN: + case RetF: + return !SemanticInformation::isDupInstruction(*this) && !SemanticInformation::isSwapInstruction(*this); case Push: case PushTag: case PushData: @@ -226,10 +298,13 @@ bool AssemblyItem::canBeFunctional() const case PushLibraryAddress: case PushDeployTimeAddress: case PushImmutable: + case AuxDataLoadN: return true; case Tag: return false; - default: + case AssignImmutable: + case VerbatimBytecode: + case UndefinedItem: break; } return false; @@ -327,8 +402,37 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const case VerbatimBytecode: text = std::string("verbatimbytecode_") + util::toHex(std::get<2>(*m_verbatimBytecode)); break; - default: - assertThrow(false, InvalidOpcode, ""); + case AuxDataLoadN: + assertThrow(data() <= std::numeric_limits::max(), AssemblyException, "Invalid auxdataloadn argument."); + text = "auxdataloadn{" + std::to_string(static_cast(data())) + "}"; + break; + case EOFCreate: + text = "eofcreate{" + std::to_string(static_cast(data())) + "}"; + break; + case ReturnContract: + text = "returncontract{" + std::to_string(static_cast(data())) + "}"; + break; + case RelativeJump: + text = "rjump{" + std::string("tag_") + std::to_string(relativeJumpTagID()) + "}"; + break; + case ConditionalRelativeJump: + text = "rjumpi{" + std::string("tag_") + std::to_string(relativeJumpTagID()) + "}"; + break; + case CallF: + text = "callf{" + std::string("code_section_") + std::to_string(static_cast(data())) + "}"; + break; + case JumpF: + text = "jumpf{" + std::string("code_section_") + std::to_string(static_cast(data())) + "}"; + break; + case RetF: + text = "retf"; + break; + case SwapN: + text = "swapn{" + std::to_string(static_cast(data())) + "}"; + break; + case DupN: + text = "dupn{" + std::to_string(static_cast(data())) + "}"; + break; } if (m_jumpType == JumpType::IntoFunction || m_jumpType == JumpType::OutOfFunction) { @@ -347,6 +451,15 @@ std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem cons switch (_item.type()) { case Operation: + case EOFCreate: + case ReturnContract: + case RelativeJump: + case ConditionalRelativeJump: + case CallF: + case JumpF: + case RetF: + case SwapN: + case DupN: _out << " " << instructionInfo(_item.instruction(), EVMVersion()).name; if (_item.instruction() == Instruction::JUMP || _item.instruction() == Instruction::JUMPI) _out << "\t" << _item.getJumpTypeAsString(); @@ -396,11 +509,12 @@ std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem cons case VerbatimBytecode: _out << " Verbatim " << util::toHex(_item.verbatimData()); break; + case AuxDataLoadN: + _out << " AuxDataLoadN " << util::toString(_item.data()); + break; case UndefinedItem: _out << " ???"; break; - default: - assertThrow(false, InvalidOpcode, ""); } return _out; } @@ -450,10 +564,9 @@ std::string AssemblyItem::computeSourceMapping( static_cast(_sourceIndicesMap.at(*location.sourceName)) : -1; char jump = '-'; - // TODO: Uncomment when EOF functions introduced. - if (item.getJumpType() == evmasm::AssemblyItem::JumpType::IntoFunction /*|| item.type() == CallF || item.type() == JumpF*/) + if (item.getJumpType() == evmasm::AssemblyItem::JumpType::IntoFunction || item.type() == CallF || item.type() == JumpF) jump = 'i'; - else if (item.getJumpType() == evmasm::AssemblyItem::JumpType::OutOfFunction /*|| item.type() == RetF*/) + else if (item.getJumpType() == evmasm::AssemblyItem::JumpType::OutOfFunction || item.type() == RetF) jump = 'o'; int modifierDepth = static_cast(item.m_modifierDepth); diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index f06c72bac2ff..b053c5b27598 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -51,7 +51,20 @@ enum AssemblyItemType PushDeployTimeAddress, ///< Push an address to be filled at deploy time. Should not be touched by the optimizer. PushImmutable, ///< Push the currently unknown value of an immutable variable. The actual value will be filled in by the constructor. AssignImmutable, ///< Assigns the current value on the stack to an immutable variable. Only valid during creation code. - VerbatimBytecode ///< Contains data that is inserted into the bytecode code section without modification. + + /// Loads 32 bytes from static auxiliary data of EOF data section. The offset does *not* have to be always from the beginning + /// of the data EOF section. More details here: https://github.com/ipsilon/eof/blob/main/spec/eof.md#data-section-lifecycle + AuxDataLoadN, + EOFCreate, ///< Creates new contract using subcontainer as initcode + ReturnContract, ///< Returns new container (with auxiliary data filled in) to be deployed + RelativeJump, ///< Jumps to relative position accordingly to its argument + ConditionalRelativeJump, ///< Same as RelativeJump but takes condition from the stack + CallF, ///< Jumps to a returning EOF function, adding a new frame to the return stack. + JumpF, ///< Jumps to a returning or non-returning EOF function without changing the return stack. + RetF, ///< Returns from an EOF function, removing a frame from the return stack. + VerbatimBytecode, ///< Contains data that is inserted into the bytecode code section without modification. + SwapN, ///< EOF SWAPN with immediate argument. + DupN, ///< EOF DUPN with immediate argument. }; enum class Precision { Precise , Approximate }; @@ -59,6 +72,7 @@ enum class Precision { Precise , Approximate }; class Assembly; class AssemblyItem; using AssemblyItems = std::vector; +using ContainerID = uint8_t; class AssemblyItem { @@ -81,6 +95,14 @@ class AssemblyItem else m_data = std::make_shared(std::move(_data)); } + + explicit AssemblyItem(AssemblyItemType _type, Instruction _instruction, u256 _data = 0, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): + m_type(_type), + m_instruction(_instruction), + m_data(std::make_shared(std::move(_data))), + m_debugData(std::move(_debugData)) + {} + explicit AssemblyItem(bytes _verbatimData, size_t _arguments, size_t _returnVariables): m_type(VerbatimBytecode), m_instruction{}, @@ -88,24 +110,76 @@ class AssemblyItem m_debugData{langutil::DebugData::create()} {} + static AssemblyItem functionCall(uint16_t _functionID, uint8_t _args, uint8_t _rets, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + // TODO: Make this constructor this way that it's impossible to create it without setting functions signature. + // It can be done by template constructor with Instruction as template parameter i.e. Same for JumpF below. + AssemblyItem result(CallF, Instruction::CALLF, _functionID, _debugData); + solAssert(_args <= 127 && _rets <= 127); + result.m_functionSignature = {_args, _rets}; + return result; + } + static AssemblyItem jumpToFunction(uint16_t _functionID, uint8_t _args, uint8_t _rets, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + AssemblyItem result(JumpF, Instruction::JUMPF, _functionID, _debugData); + solAssert(_args <= 127 && _rets <= 127); + result.m_functionSignature = {_args, _rets}; + return result; + } + static AssemblyItem functionReturn(langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + return AssemblyItem(RetF, Instruction::RETF, 0, std::move(_debugData)); + } + + static AssemblyItem eofCreate(ContainerID _containerID, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + return AssemblyItem(EOFCreate, Instruction::EOFCREATE, _containerID, std::move(_debugData)); + } + static AssemblyItem returnContract(ContainerID _containerID, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + return AssemblyItem(ReturnContract, Instruction::RETURNCONTRACT, _containerID, std::move(_debugData)); + } + static AssemblyItem relativeJumpTo(AssemblyItem _tag, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + solAssert(_tag.type() == Tag); + return AssemblyItem(RelativeJump, Instruction::RJUMP, _tag.data(), _debugData); + } + static AssemblyItem conditionalRelativeJumpTo(AssemblyItem _tag, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + solAssert(_tag.type() == Tag); + return AssemblyItem(ConditionalRelativeJump, Instruction::RJUMPI, _tag.data(), _debugData); + } + static AssemblyItem swapN(size_t _depth, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + solAssert(_depth >= 1 && _depth <= 256); + return AssemblyItem(SwapN, Instruction::SWAPN, _depth, _debugData); + } + static AssemblyItem dupN(size_t _depth, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + solAssert(_depth >= 1 && _depth <= 256); + return AssemblyItem(DupN, Instruction::DUPN, _depth, _debugData); + } + AssemblyItem(AssemblyItem const&) = default; AssemblyItem(AssemblyItem&&) = default; AssemblyItem& operator=(AssemblyItem const&) = default; AssemblyItem& operator=(AssemblyItem&&) = default; - AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); return AssemblyItem(Tag, data()); } - AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); return AssemblyItem(PushTag, data()); } + AssemblyItem tag() const { solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); return AssemblyItem(Tag, data()); } + AssemblyItem pushTag() const { solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); return AssemblyItem(PushTag, data()); } /// Converts the tag to a subassembly tag. This has to be called in order to move a tag across assemblies. /// @param _subId the identifier of the subassembly the tag is taken from. AssemblyItem toSubAssemblyTag(size_t _subId) const; /// @returns splits the data of the push tag into sub assembly id and actual tag id. /// The sub assembly id of non-foreign push tags is -1. std::pair splitForeignPushTag() const; + /// @returns relative jump target tag ID. Asserts that it is not foreign tag. + size_t relativeJumpTagID() const; /// Sets sub-assembly part and tag for a push tag. void setPushTagSubIdAndTag(size_t _subId, size_t _tag); AssemblyItemType type() const { return m_type; } - u256 const& data() const { assertThrow(m_type != Operation, util::Exception, ""); return *m_data; } + u256 const& data() const { solAssert(m_type != Operation && m_data != nullptr); return *m_data; } void setData(u256 const& _data) { assertThrow(m_type != Operation, util::Exception, ""); m_data = std::make_shared(_data); } /// This function is used in `Assembly::assemblyJSON`. @@ -118,8 +192,27 @@ class AssemblyItem bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return std::get<2>(*m_verbatimBytecode); } - /// @returns the instruction of this item (only valid if type() == Operation) - Instruction instruction() const { assertThrow(m_type == Operation, util::Exception, ""); return m_instruction; } + /// @returns true if the item has m_instruction properly set. + bool hasInstruction() const + { + return + m_type == Operation || + m_type == EOFCreate || + m_type == ReturnContract || + m_type == RelativeJump || + m_type == ConditionalRelativeJump || + m_type == CallF || + m_type == JumpF || + m_type == RetF || + m_type == SwapN || + m_type == DupN; + } + /// @returns the instruction of this item (only valid if hasInstruction returns true) + Instruction instruction() const + { + solAssert(hasInstruction()); + return m_instruction; + } /// @returns true if the type and data of the items are equal. bool operator==(AssemblyItem const& _other) const @@ -211,12 +304,28 @@ class AssemblyItem void setImmutableOccurrences(size_t _n) const { m_immutableOccurrences = _n; } + struct FunctionSignature + { + /// Number of EOF function arguments. must be less than 128 + uint8_t argsNum; + /// Number of EOF function return values. Must be less than 128. + uint8_t retsNum; + }; + + FunctionSignature const& functionSignature() const + { + solAssert(m_type == CallF || m_type == JumpF); + solAssert(m_functionSignature.has_value()); + return *m_functionSignature; + } + private: size_t opcodeCount() const noexcept; AssemblyItemType m_type; Instruction m_instruction; ///< Only valid if m_type == Operation std::shared_ptr m_data; ///< Only valid if m_type != Operation + std::optional m_functionSignature; ///< Only valid if m_type == CallF or JumpF /// If m_type == VerbatimBytecode, this holds number of arguments, number of /// return variables and verbatim bytecode. std::optional> m_verbatimBytecode; diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp index c978bae2bb39..3ba8cfcd3523 100644 --- a/libevmasm/BlockDeduplicator.cpp +++ b/libevmasm/BlockDeduplicator.cpp @@ -106,7 +106,7 @@ bool BlockDeduplicator::applyTagReplacement( { bool changed = false; for (AssemblyItem& item: _items) - if (item.type() == PushTag) + if (item.type() == PushTag || item.type() == RelativeJump || item.type() == ConditionalRelativeJump) { size_t subId; size_t tagId; @@ -131,7 +131,7 @@ BlockDeduplicator::BlockIterator& BlockDeduplicator::BlockIterator::operator++() { if (it == end) return *this; - if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem{Instruction::JUMPI}) + if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem{Instruction::JUMPI} && it->type() != ConditionalRelativeJump) it = end; else { diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index c1918540e625..a7441b85e264 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -4,6 +4,8 @@ set(sources Assembly.h AssemblyItem.cpp AssemblyItem.h + Ethdebug.cpp + Ethdebug.h EVMAssemblyStack.cpp EVMAssemblyStack.h BlockDeduplicator.cpp diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 6fdb42bd76d0..7cf00fc9ed41 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -140,6 +140,11 @@ bigint LiteralMethod::gasNeeded() const ); } +AssemblyItems LiteralMethod::execute(Assembly&) const +{ + return {}; +} + bigint CodeCopyMethod::gasNeeded() const { return combineGas( @@ -226,6 +231,23 @@ AssemblyItems CodeCopyMethod::copyRoutine(AssemblyItem* _pushData) const } } +ComputeMethod::ComputeMethod(Params const& _params, u256 const& _value): + ConstantOptimisationMethod(_params, _value) +{ + m_routine = findRepresentation(m_value); + assertThrow( + checkRepresentation(m_value, m_routine), + OptimizerException, + "Invalid constant expression created." + ); +} +ComputeMethod::~ComputeMethod() = default; + +AssemblyItems ComputeMethod::execute(Assembly&) const +{ + return m_routine; +} + AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) { if (_value < 0x10000) diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index 7a929939efe6..4952d7985d43 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -108,7 +108,7 @@ class LiteralMethod: public ConstantOptimisationMethod explicit LiteralMethod(Params const& _params, u256 const& _value): ConstantOptimisationMethod(_params, _value) {} bigint gasNeeded() const override; - AssemblyItems execute(Assembly&) const override { return AssemblyItems{}; } + AssemblyItems execute(Assembly&) const override; }; /** @@ -132,22 +132,11 @@ class CodeCopyMethod: public ConstantOptimisationMethod class ComputeMethod: public ConstantOptimisationMethod { public: - explicit ComputeMethod(Params const& _params, u256 const& _value): - ConstantOptimisationMethod(_params, _value) - { - m_routine = findRepresentation(m_value); - assertThrow( - checkRepresentation(m_value, m_routine), - OptimizerException, - "Invalid constant expression created." - ); - } + ComputeMethod(Params const& _params, u256 const& _value); + ~ComputeMethod() override; bigint gasNeeded() const override { return gasNeeded(m_routine); } - AssemblyItems execute(Assembly&) const override - { - return m_routine; - } + AssemblyItems execute(Assembly&) const override; protected: /// Tries to recursively find a way to compute @a _value. diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index df4517fc522b..7cb05bf8bf00 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -55,6 +55,7 @@ void EVMAssemblyStack::assemble() solAssert(m_evmAssembly->isCreation()); solAssert(!m_evmRuntimeAssembly); + m_evmAssembly->optimise(m_optimiserSettings); m_object = m_evmAssembly->assemble(); // TODO: Check for EOF solAssert(m_evmAssembly->codeSections().size() == 1); @@ -103,6 +104,25 @@ std::string const* EVMAssemblyStack::runtimeSourceMapping(std::string const& _co return &m_runtimeSourceMapping; } +Json EVMAssemblyStack::ethdebug(std::string const& _contractName) const +{ + solAssert(_contractName == m_name); + solAssert(m_ethdebug != nullptr); + return *m_ethdebug; +} + +Json EVMAssemblyStack::ethdebugRuntime(std::string const& _contractName) const +{ + solAssert(_contractName == m_name); + solAssert(m_ethdebugRuntime != nullptr); + return *m_ethdebugRuntime; +} + +Json EVMAssemblyStack::ethdebug() const +{ + return {}; +} + Json EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const { solAssert(_contractName == m_name); diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index cf959de79c1a..2fe63c11c2ec 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -26,6 +26,7 @@ #include #include +#include namespace solidity::evmasm { @@ -33,8 +34,15 @@ namespace solidity::evmasm class EVMAssemblyStack: public AbstractAssemblyStack { public: - explicit EVMAssemblyStack(langutil::EVMVersion _evmVersion, std::optional _eofVersion): - m_evmVersion(_evmVersion), m_eofVersion(_eofVersion) {} + explicit EVMAssemblyStack( + langutil::EVMVersion _evmVersion, + std::optional _eofVersion, + Assembly::OptimiserSettings _optimiserSettings + ): + m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), + m_optimiserSettings(std::move(_optimiserSettings)) + {} /// Runs parsing and analysis steps. /// Multiple calls overwrite the previous state. @@ -50,25 +58,29 @@ class EVMAssemblyStack: public AbstractAssemblyStack std::string const& name() const { return m_name; } - virtual LinkerObject const& object(std::string const& _contractName) const override; - virtual LinkerObject const& runtimeObject(std::string const& _contractName) const override; + LinkerObject const& object(std::string const& _contractName) const override; + LinkerObject const& runtimeObject(std::string const& _contractName) const override; std::shared_ptr const& evmAssembly() const { return m_evmAssembly; } std::shared_ptr const& evmRuntimeAssembly() const { return m_evmRuntimeAssembly; } - virtual std::string const* sourceMapping(std::string const& _contractName) const override; - virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const override; + std::string const* sourceMapping(std::string const& _contractName) const override; + std::string const* runtimeSourceMapping(std::string const& _contractName) const override; - virtual Json assemblyJSON(std::string const& _contractName) const override; - virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; + Json ethdebug(std::string const& _contractName) const override; + Json ethdebugRuntime(std::string const& _contractName) const override; + Json ethdebug() const override; - virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override; + Json assemblyJSON(std::string const& _contractName) const override; + std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; - virtual std::vector contractNames() const override { return {m_name}; } - virtual std::vector sourceNames() const override; + std::string const filesystemFriendlyName(std::string const& _contractName) const override; + + std::vector contractNames() const override { return {m_name}; } + std::vector sourceNames() const override; std::map sourceIndices() const; - virtual bool compilationSuccessful() const override { return m_evmAssembly != nullptr; } + bool compilationSuccessful() const override { return m_evmAssembly != nullptr; } void selectDebugInfo(langutil::DebugInfoSelection _debugInfoSelection) { @@ -78,6 +90,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack private: langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; + Assembly::OptimiserSettings m_optimiserSettings; std::string m_name; std::shared_ptr m_evmAssembly; std::shared_ptr m_evmRuntimeAssembly; @@ -87,6 +100,8 @@ class EVMAssemblyStack: public AbstractAssemblyStack langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); std::string m_sourceMapping; std::string m_runtimeSourceMapping; + std::unique_ptr m_ethdebug; + std::unique_ptr m_ethdebugRuntime; }; } // namespace solidity::evmasm diff --git a/libevmasm/Ethdebug.cpp b/libevmasm/Ethdebug.cpp new file mode 100644 index 000000000000..6e635ef57952 --- /dev/null +++ b/libevmasm/Ethdebug.cpp @@ -0,0 +1,113 @@ +/* + 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 + +using namespace solidity; +using namespace solidity::evmasm; +using namespace solidity::evmasm::ethdebug; + +namespace +{ + +Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId) +{ + solUnimplementedAssert(_assembly.eofVersion() == std::nullopt, "ethdebug does not yet support EOF."); + solUnimplementedAssert(_assembly.codeSections().size() == 1, "ethdebug does not yet support multiple code-sections."); + for (auto const& instruction: _assembly.codeSections()[0].items) + solUnimplementedAssert(instruction.type() != VerbatimBytecode, "Verbatim bytecode is currently not supported by ethdebug."); + + solAssert(_linkerObject.codeSectionLocations.size() == 1); + solAssert(_linkerObject.codeSectionLocations[0].end <= _linkerObject.bytecode.size()); + Json instructions = Json::array(); + for (size_t i = 0; i < _linkerObject.codeSectionLocations[0].instructionLocations.size(); ++i) + { + LinkerObject::InstructionLocation currentInstruction = _linkerObject.codeSectionLocations[0].instructionLocations[i]; + size_t start = currentInstruction.start; + size_t end = currentInstruction.end; + size_t assemblyItemIndex = currentInstruction.assemblyItemIndex; + solAssert(end <= _linkerObject.bytecode.size()); + solAssert(start < end); + solAssert(assemblyItemIndex < _assembly.codeSections().at(0).items.size()); + Json operation = Json::object(); + operation["mnemonic"] = instructionInfo(static_cast(_linkerObject.bytecode[start]), _assembly.evmVersion()).name; + static size_t constexpr instructionSize = 1; + if (start + instructionSize < end) + { + bytes const argumentData( + _linkerObject.bytecode.begin() + static_cast(start) + instructionSize, + _linkerObject.bytecode.begin() + static_cast(end) + ); + solAssert(!argumentData.empty()); + operation["arguments"] = Json::array({util::toHex(argumentData, util::HexPrefix::Add)}); + } + langutil::SourceLocation const& location = _assembly.codeSections().at(0).items.at(assemblyItemIndex).location(); + Json instruction = Json::object(); + instruction["offset"] = start; + instruction["operation"] = operation; + + instruction["context"] = Json::object(); + instruction["context"]["code"] = Json::object(); + instruction["context"]["code"]["source"] = Json::object(); + instruction["context"]["code"]["source"]["id"] = static_cast(_sourceId); + + instruction["context"]["code"]["range"] = Json::object(); + instruction["context"]["code"]["range"]["offset"] = location.start; + instruction["context"]["code"]["range"]["length"] = location.end - location.start; + instructions.emplace_back(instruction); + } + + return instructions; +} + +} // anonymous namespace + +Json ethdebug::program(std::string_view _name, unsigned _sourceId, Assembly const* _assembly, LinkerObject const& _linkerObject) +{ + Json result = Json::object(); + result["contract"] = Json::object(); + result["contract"]["name"] = _name; + result["contract"]["definition"] = Json::object(); + result["contract"]["definition"]["source"] = Json::object(); + result["contract"]["definition"]["source"]["id"] = _sourceId; + if (_assembly) + { + result["environment"] = _assembly->isCreation() ? "create" : "call"; + result["instructions"] = programInstructions(*_assembly, _linkerObject, _sourceId); + } + return result; +} + +Json ethdebug::resources(std::vector const& _sources, std::string const& _version) +{ + Json sources = Json::array(); + for (size_t id = 0; id < _sources.size(); ++id) + { + Json source = Json::object(); + source["id"] = id; + source["path"] = _sources[id]; + sources.push_back(source); + } + Json result = Json::object(); + result["compilation"] = Json::object(); + result["compilation"]["compiler"] = Json::object(); + result["compilation"]["compiler"]["name"] = "solc"; + result["compilation"]["compiler"]["version"] = _version; + result["compilation"]["sources"] = sources; + return result; +} diff --git a/libevmasm/Ethdebug.h b/libevmasm/Ethdebug.h new file mode 100644 index 000000000000..72ac16037969 --- /dev/null +++ b/libevmasm/Ethdebug.h @@ -0,0 +1,35 @@ +/* + 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 + +namespace solidity::evmasm::ethdebug +{ + +// returns ethdebug/format/program. +Json program(std::string_view _name, unsigned _sourceId, Assembly const* _assembly, LinkerObject const& _linkerObject); + +// returns ethdebug/format/info/resources +Json resources(std::vector const& _sources, std::string const& _version); + +} // namespace solidity::evmasm::ethdebug diff --git a/libevmasm/Exceptions.h b/libevmasm/Exceptions.h index ae6d1bf9c617..c9d0633e4c2c 100644 --- a/libevmasm/Exceptions.h +++ b/libevmasm/Exceptions.h @@ -33,7 +33,4 @@ struct OptimizerException: virtual AssemblyException {}; struct StackTooDeepException: virtual OptimizerException {}; struct ItemNotAvailableException: virtual OptimizerException {}; -DEV_SIMPLE_EXCEPTION(InvalidDeposit); -DEV_SIMPLE_EXCEPTION(InvalidOpcode); - } diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 81572d0e59e4..1f4a7ddb1844 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -316,17 +316,21 @@ GasMeter::GasConsumption GasMeter::memoryGasForWordArray(int _stackPosOffset, in })); } -unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVersion) +namespace { - if (_instruction == Instruction::JUMPDEST) - return 1; - - switch (instructionInfo(_instruction, _evmVersion).gasPriceTier) +std::optional gasCostForTier(Tier _tier) +{ + switch (_tier) { case Tier::Zero: return GasCosts::tier0Gas; case Tier::Base: return GasCosts::tier1Gas; + case Tier::RJump: return GasCosts::tier1Gas; + case Tier::RJumpI: return GasCosts::rjumpiGas; case Tier::VeryLow: return GasCosts::tier2Gas; + case Tier::RetF: return GasCosts::tier2Gas; case Tier::Low: return GasCosts::tier3Gas; + case Tier::CallF: return GasCosts::tier3Gas; + case Tier::JumpF: return GasCosts::tier3Gas; case Tier::Mid: return GasCosts::tier4Gas; case Tier::High: return GasCosts::tier5Gas; case Tier::BlockHash: return GasCosts::tier6Gas; @@ -334,10 +338,21 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer case Tier::Special: case Tier::Invalid: - assertThrow(false, OptimizerException, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); + return std::nullopt; } util::unreachable(); } +} + +unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVersion) +{ + if (_instruction == Instruction::JUMPDEST) + return 1; + + if (auto gasCost = gasCostForTier(instructionInfo(_instruction, _evmVersion).gasPriceTier)) + return *gasCost; + solAssert(false, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); +} unsigned GasMeter::pushGas(u256 _value, langutil::EVMVersion _evmVersion) { @@ -347,6 +362,24 @@ unsigned GasMeter::pushGas(u256 _value, langutil::EVMVersion _evmVersion) ); } +unsigned GasMeter::swapGas(size_t _depth, langutil::EVMVersion _evmVersion) +{ + if (_depth <= 16) + return runGas(evmasm::swapInstruction(static_cast(_depth)), _evmVersion); + auto gasCost = gasCostForTier(instructionInfo(evmasm::Instruction::SWAPN, _evmVersion).gasPriceTier); + solAssert(gasCost.has_value(), "Expected gas cost for SWAPN to be defined."); + return *gasCost; +} + +unsigned GasMeter::dupGas(size_t _depth, langutil::EVMVersion _evmVersion) +{ + if (_depth <= 16) + return runGas(evmasm::swapInstruction(static_cast(_depth)), _evmVersion); + auto gasCost = gasCostForTier(instructionInfo(evmasm::Instruction::DUPN, _evmVersion).gasPriceTier); + solAssert(gasCost.has_value(), "Expected gas cost for DUPN to be defined."); + return *gasCost; +} + u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersion _evmVersion) { bigint gas = 0; @@ -357,7 +390,7 @@ u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersio } else gas = bigint(GasCosts::createDataGas) * _data.size(); - assertThrow(gas < bigint(u256(-1)), OptimizerException, "Gas cost exceeds 256 bits."); + solAssert(gas < bigint(u256(-1)), "Gas cost exceeds 256 bits."); return u256(gas); } @@ -365,6 +398,6 @@ u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersio u256 GasMeter::dataGas(uint64_t _length, bool _inCreation, langutil::EVMVersion _evmVersion) { bigint gas = bigint(_length) * (_inCreation ? GasCosts::txDataNonZeroGas(_evmVersion) : GasCosts::createDataGas); - assertThrow(gas < bigint(u256(-1)), OptimizerException, "Gas cost exceeds 256 bits."); + solAssert(gas < bigint(u256(-1)), "Gas cost exceeds 256 bits."); return u256(gas); } diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index 213fad69cc98..7f2e4f6a3d00 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -177,6 +177,7 @@ namespace GasCosts return _evmVersion >= langutil::EVMVersion::istanbul() ? 16 : 68; } static unsigned const copyGas = 3; + static unsigned const rjumpiGas = 4; static unsigned const freezeV1Gas = 20000; static unsigned const expireTimeGas = 50; @@ -231,9 +232,18 @@ class GasMeter /// change with EVM versions) static unsigned runGas(Instruction _instruction, langutil::EVMVersion _evmVersion); - /// @returns gas costs for push instructions (may change depending on EVM version) + /// @returns gas costs for the cheapest push instructions for the given @a _value + /// (may change depending on EVM version) static unsigned pushGas(u256 _value, langutil::EVMVersion _evmVersion); + /// @returns gas costs for the cheapest swap instructions for the given @a _depth + /// (may change depending on EVM version) + static unsigned swapGas(size_t _depth, langutil::EVMVersion _evmVersion); + + /// @returns gas costs for the cheapest dup instructions for the given @a _depth + /// (may change depending on EVM version) + static unsigned dupGas(size_t _depth, langutil::EVMVersion _evmVersion); + /// @returns the gas cost of the supplied data, depending whether it is in creation code, or not. /// In case of @a _inCreation, the data is only sent as a transaction and is not stored, whereas /// otherwise code will be stored and have to pay "createDataGas" cost. diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 68de80037023..62c639aff117 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -184,12 +184,25 @@ std::map const solidity::evmasm::c_instructions = { "NATIVEWITHDRAWEXPIREUNFREEZE", Instruction::NATIVEWITHDRAWEXPIREUNFREEZE }, { "NATIVEDELEGATERESOURCE", Instruction::NATIVEDELEGATERESOURCE }, { "NATIVEUNDELEGATERESOURCE", Instruction::NATIVEUNDELEGATERESOURCE }, + { "DATALOADN", Instruction::DATALOADN }, + { "CALLF", Instruction::CALLF }, + { "RETF", Instruction::RETF }, + { "JUMPF", Instruction::JUMPF }, + { "DUPN", Instruction::DUPN }, + { "SWAPN", Instruction::SWAPN }, + { "RJUMP", Instruction::RJUMP }, + { "RJUMPI", Instruction::RJUMPI }, + { "EOFCREATE", Instruction::EOFCREATE }, + { "RETURNCONTRACT", Instruction::RETURNCONTRACT }, { "CREATE", Instruction::CREATE }, { "CALL", Instruction::CALL }, { "CALLCODE", Instruction::CALLCODE }, { "STATICCALL", Instruction::STATICCALL }, { "RETURN", Instruction::RETURN }, { "DELEGATECALL", Instruction::DELEGATECALL }, + { "EXTCALL", Instruction::EXTCALL }, + { "EXTSTATICCALL", Instruction::EXTSTATICCALL }, + { "EXTDELEGATECALL", Instruction::EXTDELEGATECALL }, { "CREATE2", Instruction::CREATE2 }, { "REVERT", Instruction::REVERT }, { "INVALID", Instruction::INVALID }, @@ -268,6 +281,9 @@ static std::map const c_instructionInfo = {Instruction::MSIZE, {"MSIZE", 0, 0, 1, false, Tier::Base}}, {Instruction::GAS, {"GAS", 0, 0, 1, false, Tier::Base}}, {Instruction::JUMPDEST, {"JUMPDEST", 0, 0, 0, true, Tier::Special}}, + {Instruction::DATALOADN, {"DATALOADN", 2, 0, 1, true, Tier::Low}}, + {Instruction::RJUMP, {"RJUMP", 2, 0, 0, true, Tier::RJump}}, + {Instruction::RJUMPI, {"RJUMPI", 2, 1, 0, true, Tier::RJumpI}}, {Instruction::PUSH0, {"PUSH0", 0, 0, 1, false, Tier::Base}}, {Instruction::PUSH1, {"PUSH1", 1, 0, 1, false, Tier::VeryLow}}, {Instruction::PUSH2, {"PUSH2", 2, 0, 1, false, Tier::VeryLow}}, @@ -354,12 +370,22 @@ static std::map const c_instructionInfo = {Instruction::NATIVEWITHDRAWEXPIREUNFREEZE, {"NATIVEWITHDRAWEXPIREUNFREEZE", 0, 0, 1, true, Tier::BlockHash}}, {Instruction::NATIVEDELEGATERESOURCE, {"NATIVEDELEGATERESOURCE", 0, 3, 1, true, Tier::BlockHash}}, {Instruction::NATIVEUNDELEGATERESOURCE, {"NATIVEUNDELEGATERESOURCE", 0, 3, 1, true, Tier::BlockHash}}, + {Instruction::RETF, {"RETF", 0, 0, 0, true, Tier::RetF}}, + {Instruction::CALLF, {"CALLF", 2, 0, 0, true, Tier::CallF}}, + {Instruction::JUMPF, {"JUMPF", 2, 0, 0, true, Tier::JumpF}}, + {Instruction::SWAPN, {"SWAPN", 1, 0, 0, false, Tier::VeryLow}}, + {Instruction::DUPN, {"DUPN", 1, 0, 0, false, Tier::VeryLow}}, + {Instruction::EOFCREATE, {"EOFCREATE", 1, 4, 1, true, Tier::Special}}, + {Instruction::RETURNCONTRACT, {"RETURNCONTRACT", 1, 2, 0, true, Tier::Special}}, {Instruction::CREATE, {"CREATE", 0, 3, 1, true, Tier::Special}}, {Instruction::CALL, {"CALL", 0, 7, 1, true, Tier::Special}}, {Instruction::CALLCODE, {"CALLCODE", 0, 7, 1, true, Tier::Special}}, {Instruction::RETURN, {"RETURN", 0, 2, 0, true, Tier::Zero}}, {Instruction::DELEGATECALL, {"DELEGATECALL", 0, 6, 1, true, Tier::Special}}, {Instruction::STATICCALL, {"STATICCALL", 0, 6, 1, true, Tier::Special}}, + {Instruction::EXTCALL, {"EXTCALL", 0, 4, 1, true, Tier::Special}}, + {Instruction::EXTDELEGATECALL,{"EXTDELEGATECALL", 0, 3, 1, true, Tier::Special}}, + {Instruction::EXTSTATICCALL, {"EXTSTATICCALL", 0, 3, 1, true, Tier::Special}}, {Instruction::CREATE2, {"CREATE2", 0, 4, 1, true, Tier::Special}}, {Instruction::REVERT, {"REVERT", 0, 2, 0, true, Tier::Zero}}, {Instruction::INVALID, {"INVALID", 0, 0, 0, true, Tier::Zero}}, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 171516e25ac2..22969c04e6b6 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace solidity::evmasm { @@ -199,13 +200,27 @@ enum class Instruction: uint8_t NATIVEDELEGATERESOURCE, NATIVEUNDELEGATERESOURCE, + DATALOADN = 0xef, ///< load data from EOF data section + + RJUMP = 0xe0, ///< relative jump + RJUMPI = 0xe1, ///< conditional relative jump + CALLF = 0xe3, ///< call function in a EOF code section + RETF = 0xe4, ///< return to caller from the code section of EOF container + JUMPF = 0xe5, ///< jump to a code section of EOF container without adding a new return stack frame. + DUPN = 0xe6, ///< copies a value at the stack depth given as immediate argument to the top of the stack + SWAPN = 0xe7, ///< swaps the highest value with a value at a stack depth given as immediate argument + EOFCREATE = 0xec, ///< create a new account with associated container code. + RETURNCONTRACT = 0xee, ///< return container to be deployed with axiliary data filled in. CREATE = 0xf0, ///< create a new account with associated code CALL, ///< message-call into an account CALLCODE, ///< message-call with another account's code only RETURN, ///< halt execution returning output data DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender CREATE2 = 0xf5, ///< create new account with associated code at address `sha3(0xff + sender + salt + init code) % 2**160` + EXTCALL = 0xf8, ///< EOF message-call into an account + EXTDELEGATECALL = 0xf9, ///< EOF delegate call STATICCALL = 0xfa, ///< like CALL but disallow state modifications + EXTSTATICCALL = 0xfb, ///< like EXTCALL but disallow state modifications REVERT = 0xfd, ///< halt execution, revert state and return output data INVALID = 0xfe, ///< invalid instruction for expressing runtime errors (e.g., division-by-zero) @@ -221,6 +236,9 @@ constexpr bool isCallInstruction(Instruction _inst) noexcept case Instruction::CALLCODE: case Instruction::DELEGATECALL: case Instruction::STATICCALL: + case Instruction::EXTCALL: + case Instruction::EXTSTATICCALL: + case Instruction::EXTDELEGATECALL: return true; default: return false; @@ -233,18 +251,6 @@ inline bool isPushInstruction(Instruction _inst) return Instruction::PUSH0 <= _inst && _inst <= Instruction::PUSH32; } -/// @returns true if the instruction is a DUP -inline bool isDupInstruction(Instruction _inst) -{ - return Instruction::DUP1 <= _inst && _inst <= Instruction::DUP16; -} - -/// @returns true if the instruction is a SWAP -inline bool isSwapInstruction(Instruction _inst) -{ - return Instruction::SWAP1 <= _inst && _inst <= Instruction::SWAP16; -} - /// @returns true if the instruction is a LOG inline bool isLogInstruction(Instruction _inst) { @@ -257,18 +263,6 @@ inline unsigned getPushNumber(Instruction _inst) return static_cast(_inst) - unsigned(Instruction::PUSH0); } -/// @returns the number of DUP Instruction _inst -inline unsigned getDupNumber(Instruction _inst) -{ - return static_cast(_inst) - unsigned(Instruction::DUP1) + 1; -} - -/// @returns the number of SWAP Instruction _inst -inline unsigned getSwapNumber(Instruction _inst) -{ - return static_cast(_inst) - unsigned(Instruction::SWAP1) + 1; -} - /// @returns the number of LOG Instruction _inst inline unsigned getLogNumber(Instruction _inst) { @@ -278,28 +272,28 @@ inline unsigned getLogNumber(Instruction _inst) /// @returns the PUSH<_number> instruction inline Instruction pushInstruction(unsigned _number) { - assertThrow(_number <= 32, InvalidOpcode, std::string("Invalid PUSH instruction requested (") + std::to_string(_number) + ")."); + solAssert(_number <= 32); return Instruction(unsigned(Instruction::PUSH0) + _number); } /// @returns the DUP<_number> instruction inline Instruction dupInstruction(unsigned _number) { - assertThrow(1 <= _number && _number <= 16, InvalidOpcode, std::string("Invalid DUP instruction requested (") + std::to_string(_number) + ")."); + solAssert(1 <= _number && _number <= 16); return Instruction(unsigned(Instruction::DUP1) + _number - 1); } /// @returns the SWAP<_number> instruction inline Instruction swapInstruction(unsigned _number) { - assertThrow(1 <= _number && _number <= 16, InvalidOpcode, std::string("Invalid SWAP instruction requested (") + std::to_string(_number) + ")."); + solAssert(1 <= _number && _number <= 16); return Instruction(unsigned(Instruction::SWAP1) + _number - 1); } /// @returns the LOG<_number> instruction inline Instruction logInstruction(unsigned _number) { - assertThrow(_number <= 4, InvalidOpcode, std::string("Invalid LOG instruction requested (") + std::to_string(_number) + ")."); + solAssert(_number <= 4); return Instruction(unsigned(Instruction::LOG0) + _number); } @@ -312,8 +306,13 @@ enum class Tier // NOTE: Tiers should be ordered by cost, since we sometimes perform comparisons between them. Zero = 0, // 0, Zero Base, // 2, Quick + RJump, // 2, RJump VeryLow, // 3, Fastest + RetF, // 3, + RJumpI, // 4, Low, // 5, Fast + CallF, // 5, + JumpF, // 5, Mid, // 8, Mid High, // 10, Slow BlockHash, // 20 diff --git a/libevmasm/JumpdestRemover.cpp b/libevmasm/JumpdestRemover.cpp index 7afa715a88df..7ded5ae90889 100644 --- a/libevmasm/JumpdestRemover.cpp +++ b/libevmasm/JumpdestRemover.cpp @@ -58,7 +58,7 @@ std::set JumpdestRemover::referencedTags(AssemblyItems const& _items, si { std::set ret; for (auto const& item: _items) - if (item.type() == PushTag) + if (item.type() == PushTag || item.type() == RelativeJump || item.type() == ConditionalRelativeJump) { auto subAndTag = item.splitForeignPushTag(); if (subAndTag.first == _subId) diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 3878ae0fdd75..6e1a00465b26 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -120,7 +120,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool } else if (_item.type() != Operation) { - assertThrow(_item.deposit() == 1, InvalidDeposit, ""); + solAssert(_item.deposit() == 1); if (_item.pushedValue()) // only available after assembly stage, should not be used for optimisation setStackElement(++m_stackHeight, m_expressionClasses->find(*_item.pushedValue())); @@ -137,14 +137,14 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool setStackElement( m_stackHeight + 1, stackElement( - m_stackHeight - static_cast(instruction) + static_cast(Instruction::DUP1), + m_stackHeight - (static_cast(SemanticInformation::getDupNumber(_item)) - 1), _item.debugData() ) ); else if (SemanticInformation::isSwapInstruction(_item)) swapStackElements( m_stackHeight, - m_stackHeight - 1 - static_cast(instruction) + static_cast(Instruction::SWAP1), + m_stackHeight - 1 - (static_cast(SemanticInformation::getSwapNumber(_item)) - 1), _item.debugData() ); else if (instruction != Instruction::POP) @@ -194,7 +194,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool resetStorage(); if (invMem || invStor) m_sequenceNumber += 2; // Increment by two because it can read and write - assertThrow(info.ret <= 1, InvalidDeposit, ""); + solAssert(info.ret <= 1); if (info.ret == 1) setStackElement( m_stackHeight + static_cast(_item.deposit()), diff --git a/libevmasm/LinkerObject.h b/libevmasm/LinkerObject.h index c103a565a069..34e696d4e159 100644 --- a/libevmasm/LinkerObject.h +++ b/libevmasm/LinkerObject.h @@ -46,6 +46,37 @@ struct LinkerObject /// to a list of offsets into the bytecode that refer to their values. std::map immutableReferences; + struct InstructionLocation + { + /// Absolute position of instruction's opcode within the bytecode. + /// The opcode takes up exactly one byte and is assumed to be followed by its immediate arguments. + size_t start{}; + /// Absolute position of the first byte past the end of the instruction, including potential immediate arguments. + size_t end{}; + /// Index of the AssemblyItem that produced the instruction within the Assembly. + /// While items of most types generate a single instruction, in general it can be more than one. + size_t assemblyItemIndex{}; + }; + struct CodeSectionLocation + { + /// Absolute position of the first byte belonging to the code section. + /// Equal to instructionLocations[0].start if the code section is not empty. + size_t start{}; + /// Absolute position of the first byte past end of the code section. + /// Greater or equal to start. Must be equal if instructionLocations is empty. + size_t end{}; + /// Descriptions of all instructions contained within the code section. + /// The instructions are assumed to fill the whole section, without any gaps or duplicates. + /// The areas between opcodes are assumed to contain their immediate arguments, of size appropriate for the opcode type. + /// The arguments of the last instruction extend to the end of the section. + /// The instructions must be ordered according to their positions (ascending). + std::vector instructionLocations; + }; + /// Descriptions of all code sections in the ascending order of their positions. + /// There are no duplicates and the sections never overlap. + /// Only sections belonging to the top-level assembly are included, even if the bytecode contains subassemblies. + std::vector codeSectionLocations; + struct FunctionDebugData { std::optional bytecodeOffset; diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 40937e73f107..879f5b3272dc 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -290,7 +290,7 @@ struct DupSwap: SimplePeepholeOptimizerMethod if ( SemanticInformation::isDupInstruction(_dupN) && SemanticInformation::isSwapInstruction(_swapN) && - getDupNumber(_dupN.instruction()) == getSwapNumber(_swapN.instruction()) + SemanticInformation::getDupNumber(_dupN) == SemanticInformation::getSwapNumber(_swapN) ) { *_out = _dupN; @@ -328,6 +328,29 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod } }; +struct IsZeroIsZeroRJumpI: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _iszero1, + AssemblyItem const& _iszero2, + AssemblyItem const& _rjumpi, + std::back_insert_iterator _out + ) + { + if ( + _iszero1 == Instruction::ISZERO && + _iszero2 == Instruction::ISZERO && + _rjumpi.type() == ConditionalRelativeJump + ) + { + *_out = _rjumpi; + return true; + } + else + return false; + } +}; + struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod { static size_t applySimple( @@ -355,6 +378,30 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod } }; +struct EqIsZeroRJumpI: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _eq, + AssemblyItem const& _iszero, + AssemblyItem const& _rjumpi, + std::back_insert_iterator _out + ) + { + if ( + _eq == Instruction::EQ && + _iszero == Instruction::ISZERO && + _rjumpi.type() == ConditionalRelativeJump + ) + { + *_out = AssemblyItem(Instruction::SUB, _eq.debugData()); + *_out = _rjumpi; + return true; + } + else + return false; + } +}; + // push_tag_1 jumpi push_tag_2 jump tag_1: -> iszero push_tag_2 jumpi tag_1: struct DoubleJump: SimplePeepholeOptimizerMethod { @@ -387,6 +434,33 @@ struct DoubleJump: SimplePeepholeOptimizerMethod } }; +// rjumpi(tag_1) rjump(tag_2) tag_1: -> iszero rjumpi(tag_2) tag_1: +struct DoubleRJump: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _rjumpi, + AssemblyItem const& _rjump, + AssemblyItem const& _tag1, + std::back_insert_iterator _out + ) + { + if ( + _rjumpi.type() == ConditionalRelativeJump && + _rjump.type() == RelativeJump && + _tag1.type() == Tag && + _rjumpi.data() == _tag1.data() + ) + { + *_out = AssemblyItem(Instruction::ISZERO, _rjumpi.debugData()); + *_out = AssemblyItem::conditionalRelativeJumpTo(_rjump.tag(), _rjump.debugData()); + *_out = _tag1; + return true; + } + else + return false; + } +}; + struct JumpToNext: SimplePeepholeOptimizerMethod { static size_t applySimple( @@ -413,6 +487,30 @@ struct JumpToNext: SimplePeepholeOptimizerMethod } }; +struct RJumpToNext: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _rjump, + AssemblyItem const& _tag, + std::back_insert_iterator _out + ) + { + if ( + (_rjump.type() == ConditionalRelativeJump || _rjump.type() == RelativeJump) && + _tag.type() == Tag && + _rjump.data() == _tag.data() + ) + { + if (_rjump.type() == ConditionalRelativeJump) + *_out = AssemblyItem(Instruction::POP, _rjump.debugData()); + *_out = _tag; + return true; + } + else + return false; + } +}; + struct TagConjunctions: SimplePeepholeOptimizerMethod { static bool applySimple( @@ -476,6 +574,7 @@ struct UnreachableCode return false; if ( it[0] != Instruction::JUMP && + it[0] != Instruction::RJUMP && it[0] != Instruction::RETURN && it[0] != Instruction::STOP && it[0] != Instruction::INVALID && @@ -610,6 +709,12 @@ size_t numberOfPops(AssemblyItems const& _items) } +PeepholeOptimiser::PeepholeOptimiser(AssemblyItems& _items, langutil::EVMVersion const _evmVersion): + m_items(_items), + m_evmVersion(_evmVersion) +{ +} + bool PeepholeOptimiser::optimise() { // Avoid referencing immutables too early by using approx. counting in bytesRequired() @@ -618,9 +723,30 @@ bool PeepholeOptimiser::optimise() while (state.i < m_items.size()) applyMethods( state, - PushPop(), OpPop(), OpStop(), OpReturnRevert(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), - DupSwap(), IsZeroIsZeroJumpI(), EqIsZeroJumpI(), DoubleJump(), JumpToNext(), UnreachableCode(), DeduplicateNextTagSize3(), - DeduplicateNextTagSize2(), DeduplicateNextTagSize1(), TagConjunctions(), TruthyAnd(), Identity() + PushPop(), + OpPop(), + OpStop(), + OpReturnRevert(), + DoublePush(), + DoubleSwap(), + CommutativeSwap(), + SwapComparison(), + DupSwap(), + IsZeroIsZeroJumpI(), + IsZeroIsZeroRJumpI(), // EOF specific + EqIsZeroJumpI(), + EqIsZeroRJumpI(), // EOF specific + DoubleJump(), + DoubleRJump(), // EOF specific + JumpToNext(), + RJumpToNext(), // EOF specific + UnreachableCode(), + DeduplicateNextTagSize3(), + DeduplicateNextTagSize2(), + DeduplicateNextTagSize1(), + TagConjunctions(), + TruthyAnd(), + Identity() ); if (m_optimisedItems.size() < m_items.size() || ( m_optimisedItems.size() == m_items.size() && ( diff --git a/libevmasm/PeepholeOptimiser.h b/libevmasm/PeepholeOptimiser.h index 8e3161b212aa..2a1b9ae5ba44 100644 --- a/libevmasm/PeepholeOptimiser.h +++ b/libevmasm/PeepholeOptimiser.h @@ -43,11 +43,7 @@ class PeepholeOptimisationMethod class PeepholeOptimiser { public: - explicit PeepholeOptimiser(AssemblyItems& _items, langutil::EVMVersion const _evmVersion): - m_items(_items), - m_evmVersion(_evmVersion) - { - } + explicit PeepholeOptimiser(AssemblyItems& _items, langutil::EVMVersion _evmVersion); virtual ~PeepholeOptimiser() = default; bool optimise(); diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 190a42dda128..c329dc849a39 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -170,6 +170,26 @@ std::vector SemanticInformation::readWriteOperat }); return operations; } + case Instruction::EXTCALL: + case Instruction::EXTSTATICCALL: + case Instruction::EXTDELEGATECALL: + { + size_t paramCount = static_cast(instructionInfo(_instruction, langutil::EVMVersion()).args); + size_t const memoryStartParam = _instruction == Instruction::EXTCALL ? paramCount - 3 : paramCount - 2; + size_t const memoryLengthParam = _instruction == Instruction::EXTCALL ? paramCount - 2 : paramCount - 1; + std::vector operations{ + Operation{Location::Memory, Effect::Read, memoryStartParam, memoryLengthParam, {}}, + Operation{Location::Storage, Effect::Read, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Read, {}, {}, {}} + }; + if (_instruction == Instruction::EXTDELEGATECALL) + { + operations.emplace_back(Operation{Location::Storage, Effect::Write, {}, {}, {}}); + operations.emplace_back(Operation{Location::TransientStorage, Effect::Write, {}, {}, {}}); + } + + return operations; + } case Instruction::CREATE: case Instruction::CREATE2: return std::vector{ @@ -185,6 +205,34 @@ std::vector SemanticInformation::readWriteOperat Operation{Location::TransientStorage, Effect::Read, {}, {}, {}}, Operation{Location::TransientStorage, Effect::Write, {}, {}, {}} }; + case Instruction::EOFCREATE: + return std::vector{ + Operation{ + Location::Memory, + Effect::Read, + 2, + 3, + {} + }, + Operation{Location::Storage, Effect::Read, {}, {}, {}}, + Operation{Location::Storage, Effect::Write, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Read, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Write, {}, {}, {}} + }; + case Instruction::RETURNCONTRACT: + return std::vector{ + Operation{ + Location::Memory, + Effect::Read, + 0, + 1, + {} + }, + Operation{Location::Storage, Effect::Read, {}, {}, {}}, + Operation{Location::Storage, Effect::Write, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Read, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Write, {}, {}, {}} + }; case Instruction::MSIZE: // This is just to satisfy the assert below. return std::vector{}; @@ -216,6 +264,9 @@ bool SemanticInformation::breaksCSEAnalysisBlock(AssemblyItem const& _item, bool case PushDeployTimeAddress: case AssignImmutable: case VerbatimBytecode: + case CallF: + case JumpF: + case RetF: return true; case Push: case PushTag: @@ -274,38 +325,46 @@ bool SemanticInformation::isCommutativeOperation(AssemblyItem const& _item) bool SemanticInformation::isDupInstruction(AssemblyItem const& _item) { + if (_item.type() == evmasm::DupN) + return true; if (_item.type() != evmasm::Operation) return false; - return evmasm::isDupInstruction(_item.instruction()); + auto inst = _item.instruction(); + return Instruction::DUP1 <= inst && inst <= Instruction::DUP16; } bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item) { + if (_item.type() == evmasm::SwapN) + return true; if (_item.type() != evmasm::Operation) return false; - return evmasm::isSwapInstruction(_item.instruction()); -} - -bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item) -{ - return _item == Instruction::JUMP || _item == Instruction::JUMPI; + auto inst = _item.instruction(); + return Instruction::SWAP1 <= inst && inst <= Instruction::SWAP16; } bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) { - if (_item.type() != evmasm::Operation) + if (!_item.hasInstruction()) return false; + switch (_item.instruction()) { // note that CALL, CALLCODE and CREATE do not really alter the control flow, because we // continue on the next instruction case Instruction::JUMP: case Instruction::JUMPI: + case Instruction::RJUMP: + case Instruction::RJUMPI: case Instruction::RETURN: case Instruction::SELFDESTRUCT: case Instruction::STOP: case Instruction::INVALID: case Instruction::REVERT: + case Instruction::RETURNCONTRACT: + case Instruction::CALLF: + case Instruction::JUMPF: + case Instruction::RETF: return true; default: return false; @@ -314,7 +373,7 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) bool SemanticInformation::terminatesControlFlow(AssemblyItem const& _item) { - if (_item.type() != evmasm::Operation) + if (!_item.hasInstruction()) return false; return terminatesControlFlow(_item.instruction()); } @@ -328,6 +387,7 @@ bool SemanticInformation::terminatesControlFlow(Instruction _instruction) case Instruction::STOP: case Instruction::INVALID: case Instruction::REVERT: + case Instruction::RETURNCONTRACT: return true; default: return false; @@ -346,11 +406,29 @@ bool SemanticInformation::reverts(Instruction _instruction) } } +size_t SemanticInformation::getDupNumber(AssemblyItem const& _item) +{ + assertThrow(isDupInstruction(_item), OptimizerException, "Not a DUP instruction."); + if (_item.type() == evmasm::DupN) + return static_cast(_item.data()); + auto inst = _item.instruction(); + return static_cast(inst) - static_cast(Instruction::DUP1) + 1; +} + +size_t SemanticInformation::getSwapNumber(AssemblyItem const& _item) +{ + assertThrow(isSwapInstruction(_item), OptimizerException, "Not a swap instruction."); + if (_item.type() == evmasm::SwapN) + return static_cast(_item.data()); + auto inst = _item.instruction(); + return static_cast(inst) - static_cast(Instruction::SWAP1) + 1; +} + bool SemanticInformation::isDeterministic(AssemblyItem const& _item) { assertThrow(_item.type() != VerbatimBytecode, AssemblyException, ""); - if (_item.type() != evmasm::Operation) + if (!_item.hasInstruction()) return true; switch (_item.instruction()) @@ -359,6 +437,9 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item) case Instruction::CALLCODE: case Instruction::DELEGATECALL: case Instruction::STATICCALL: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: + case Instruction::EXTSTATICCALL: case Instruction::CREATE: case Instruction::CREATE2: case Instruction::GAS: @@ -384,6 +465,9 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item) case Instruction::NATIVEWITHDRAWEXPIREUNFREEZE: case Instruction::NATIVEDELEGATERESOURCE: case Instruction::NATIVEUNDELEGATERESOURCE: + case Instruction::EOFCREATE: + case Instruction::CALLF: + case Instruction::JUMPF: return false; default: return true; @@ -468,6 +552,11 @@ SemanticInformation::Effect SemanticInformation::memory(Instruction _instruction case Instruction::LOG3: case Instruction::LOG4: case Instruction::NATIVEVOTE: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: + case Instruction::EXTSTATICCALL: return SemanticInformation::Read; default: @@ -509,10 +598,15 @@ SemanticInformation::Effect SemanticInformation::storage(Instruction _instructio case Instruction::CREATE: case Instruction::CREATE2: case Instruction::SSTORE: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: return SemanticInformation::Write; case Instruction::SLOAD: case Instruction::STATICCALL: + case Instruction::EXTSTATICCALL: return SemanticInformation::Read; default: @@ -531,10 +625,15 @@ SemanticInformation::Effect SemanticInformation::transientStorage(Instruction _i case Instruction::CREATE: case Instruction::CREATE2: case Instruction::TSTORE: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: return SemanticInformation::Write; case Instruction::TLOAD: case Instruction::STATICCALL: + case Instruction::EXTSTATICCALL: return SemanticInformation::Read; default: @@ -552,7 +651,12 @@ SemanticInformation::Effect SemanticInformation::otherState(Instruction _instruc case Instruction::DELEGATECALL: case Instruction::CREATE: case Instruction::CREATE2: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: case Instruction::SELFDESTRUCT: + case Instruction::EXTSTATICCALL: case Instruction::STATICCALL: // because it can affect returndatasize // Strictly speaking, log0, .., log4 writes to the state, but the EVM cannot read it, so they // are just marked as having 'other side effects.' @@ -612,6 +716,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction) case Instruction::NUMBER: case Instruction::PREVRANDAO: case Instruction::GASLIMIT: + case Instruction::EXTSTATICCALL: case Instruction::STATICCALL: case Instruction::SLOAD: case Instruction::TLOAD: @@ -629,6 +734,8 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction) bool SemanticInformation::invalidInViewFunctions(Instruction _instruction) { + // Relative jumps cannot jump out of the current code section of EOF so they are valid in view functions + // (under the assumption that every Solidity function actually gets its own code section). switch (_instruction) { case Instruction::SSTORE: @@ -656,6 +763,12 @@ bool SemanticInformation::invalidInViewFunctions(Instruction _instruction) case Instruction::CALL: case Instruction::CALLCODE: case Instruction::DELEGATECALL: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: + // According to EOF spec https://eips.ethereum.org/EIPS/eip-7620#eofcreate + case Instruction::EOFCREATE: + // According to EOF spec https://eips.ethereum.org/EIPS/eip-7620#returncontract + case Instruction::RETURNCONTRACT: case Instruction::CREATE2: return true; default: diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index b62832f238af..8dae6acad6f6 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -82,11 +82,14 @@ struct SemanticInformation static bool isCommutativeOperation(AssemblyItem const& _item); static bool isDupInstruction(AssemblyItem const& _item); static bool isSwapInstruction(AssemblyItem const& _item); - static bool isJumpInstruction(AssemblyItem const& _item); static bool altersControlFlow(AssemblyItem const& _item); static bool terminatesControlFlow(AssemblyItem const& _item); static bool terminatesControlFlow(Instruction _instruction); static bool reverts(Instruction _instruction); + /// @returns the 1-based DUP depth a DUP AssembleItem @a _item + static size_t getDupNumber(AssemblyItem const& _item); + /// @returns the 1-based SWAP depth a DUP AssembleItem @a _item + static size_t getSwapNumber(AssemblyItem const& _item); /// @returns false if the value put on the stack by _item depends on anything else than /// the information in the current block header, memory, storage, transient storage or stack. static bool isDeterministic(AssemblyItem const& _item); diff --git a/liblangutil/DebugInfoSelection.cpp b/liblangutil/DebugInfoSelection.cpp index ad0b615c1c1e..dfd623646e3a 100644 --- a/liblangutil/DebugInfoSelection.cpp +++ b/liblangutil/DebugInfoSelection.cpp @@ -49,6 +49,14 @@ DebugInfoSelection const DebugInfoSelection::Only(bool DebugInfoSelection::* _me return result; } +DebugInfoSelection const DebugInfoSelection::AllExcept(std::vector const& _members) noexcept +{ + DebugInfoSelection result = All(); + for (bool DebugInfoSelection::* member: _members) + result.*member = false; + return result; +} + std::optional DebugInfoSelection::fromString(std::string_view _input) { // TODO: Make more stuff constexpr and make it a static_assert(). @@ -56,7 +64,7 @@ std::optional DebugInfoSelection::fromString(std::string_vie solAssert(componentMap().count("none") == 0, ""); if (_input == "all") - return All(); + return AllExceptExperimental(); if (_input == "none") return None(); @@ -74,7 +82,7 @@ std::optional DebugInfoSelection::fromComponents( for (auto const& component: _componentNames) { if (component == "*") - return (_acceptWildcards ? std::make_optional(DebugInfoSelection::All()) : std::nullopt); + return (_acceptWildcards ? std::make_optional(AllExceptExperimental()) : std::nullopt); if (!selection.enable(component)) return std::nullopt; diff --git a/liblangutil/DebugInfoSelection.h b/liblangutil/DebugInfoSelection.h index 3a9432de6d02..daf4b950f2e9 100644 --- a/liblangutil/DebugInfoSelection.h +++ b/liblangutil/DebugInfoSelection.h @@ -42,7 +42,9 @@ struct DebugInfoSelection static DebugInfoSelection const All(bool _value = true) noexcept; static DebugInfoSelection const None() noexcept { return All(false); } static DebugInfoSelection const Only(bool DebugInfoSelection::* _member) noexcept; - static DebugInfoSelection const Default() noexcept { return All(); } + static DebugInfoSelection const Default() noexcept { return AllExceptExperimental(); } + static DebugInfoSelection const AllExcept(std::vector const& _members) noexcept; + static DebugInfoSelection const AllExceptExperimental() noexcept { return AllExcept({&DebugInfoSelection::ethdebug}); } static std::optional fromString(std::string_view _input); static std::optional fromComponents( @@ -72,13 +74,24 @@ struct DebugInfoSelection {"location", &DebugInfoSelection::location}, {"snippet", &DebugInfoSelection::snippet}, {"ast-id", &DebugInfoSelection::astID}, + {"ethdebug", &DebugInfoSelection::ethdebug}, }; return components; } + std::vector selectedNames() const + { + std::vector result; + for (auto const& component: componentMap()) + if (this->*(component.second)) + result.push_back(component.first); + return result; + } + bool location = false; ///< Include source location. E.g. `@src 3:50:100` bool snippet = false; ///< Include source code snippet next to location. E.g. `@src 3:50:100 "contract C {..."` bool astID = false; ///< Include ID of the Solidity AST node. E.g. `@ast-id 15` + bool ethdebug = false; ///< Include ethdebug related debug information. }; std::ostream& operator<<(std::ostream& _stream, DebugInfoSelection const& _selection); diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 6435e0f15455..4fbfe8de41b0 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -28,8 +28,8 @@ using namespace solidity::langutil; bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersion) const { - // EOF version can be only defined since prague - assert(!_eofVersion.has_value() || this->m_version >= prague()); + // EOF version can be only defined since osaka + assert(!_eofVersion.has_value() || *this >= EVMVersion::firstWithEOF()); switch (_opcode) { @@ -76,6 +76,21 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersi case Instruction::EXTCODECOPY: case Instruction::GAS: return !_eofVersion.has_value(); + // Instructions below available only in EOF + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: + case Instruction::DATALOADN: + case Instruction::RJUMP: + case Instruction::RJUMPI: + case Instruction::CALLF: + case Instruction::JUMPF: + case Instruction::DUPN: + case Instruction::SWAPN: + case Instruction::RETF: + case Instruction::EXTCALL: + case Instruction::EXTSTATICCALL: + case Instruction::EXTDELEGATECALL: + return _eofVersion.has_value(); default: return true; } diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 3d58fed43709..a159f2e4bb2f 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -21,9 +21,12 @@ #pragma once +#include + #include #include #include +#include #include @@ -61,10 +64,10 @@ class EVMVersion: static EVMVersion shanghai() { return {Version::Shanghai}; } static EVMVersion cancun() { return {Version::Cancun}; } static EVMVersion prague() { return {Version::Prague}; } + static EVMVersion osaka() { return {Version::Osaka}; } - static std::optional fromString(std::string const& _version) - { - for (auto const& v: { + static std::vector allVersions() { + return { homestead(), tangerineWhistle(), spuriousDragon(), @@ -77,13 +80,25 @@ class EVMVersion: paris(), shanghai(), cancun(), - prague() - }) + prague(), + osaka(), + }; + } + + static std::optional fromString(std::string const& _version) + { + for (auto const& v: allVersions()) if (_version == v.name()) return v; return std::nullopt; } + static EVMVersion firstWithEOF() { return {Version::Osaka}; } + + bool isExperimental() const { + return *this > EVMVersion{}; + } + bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; } bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; } @@ -104,8 +119,9 @@ class EVMVersion: case Version::Shanghai: return "shanghai"; case Version::Cancun: return "cancun"; case Version::Prague: return "prague"; + case Version::Osaka: return "osaka"; } - return "INVALID"; + util::unreachable(); } /// Has the RETURNDATACOPY and RETURNDATASIZE opcodes. @@ -123,6 +139,7 @@ class EVMVersion: bool hasBlobHash() const { return *this >= cancun(); } bool hasMcopy() const { return *this >= cancun(); } bool supportsTransientStorage() const { return *this >= cancun(); } + bool supportsEOF() const { return *this >= firstWithEOF(); } bool hasOpcode(evmasm::Instruction _opcode, std::optional _eofVersion) const; @@ -144,7 +161,8 @@ class EVMVersion: Paris, Shanghai, Cancun, - Prague + Prague, + Osaka, }; EVMVersion(Version _version): m_version(_version) {} diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp index ddb6b70d1253..9f3e293f53da 100644 --- a/liblangutil/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -23,6 +23,9 @@ #include #include + +#include + #include #include @@ -121,7 +124,7 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type) if (m_errorCount > c_maxErrorsAllowed) { m_errorList.push_back(std::make_shared(4013_error, Error::Type::Warning, "There are more than 256 errors. Aborting.")); - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, "There are more than 256 errors. Aborting."); } } @@ -131,13 +134,13 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type) void ErrorReporter::fatalError(ErrorId _error, Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description) { error(_error, _type, _location, _secondaryLocation, _description); - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, _description); } void ErrorReporter::fatalError(ErrorId _error, Error::Type _type, SourceLocation const& _location, std::string const& _description) { error(_error, _type, _location, _description); - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, _description); } ErrorList const& ErrorReporter::errors() const @@ -190,6 +193,17 @@ void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location, ); } +void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description) +{ + error( + _error, + Error::Type::ParserError, + _location, + _secondaryLocation, + _description + ); +} + void ErrorReporter::fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description) { fatalError( @@ -273,6 +287,23 @@ void ErrorReporter::unimplementedFeatureError(ErrorId _error, SourceLocation con ); } +void ErrorReporter::codeGenerationError(ErrorId _error, SourceLocation const& _location, std::string const& _description) +{ + error(_error, Error::Type::CodeGenerationError, _location, _description); +} + +void ErrorReporter::codeGenerationError(Error const& _error) +{ + solAssert(_error.type() == Error::Type::CodeGenerationError); + solAssert(_error.comment(), "Errors must include a message for the user."); + solUnimplementedAssert(!_error.secondarySourceLocation(), "Secondary locations not supported yet."); + codeGenerationError( + _error.errorId(), + _error.sourceLocation() ? *_error.sourceLocation() : SourceLocation{}, + *_error.comment() + ); +} + void ErrorReporter::info( ErrorId _error, SourceLocation const& _location, diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index 989cc4d5e3a0..dc359c1b05e0 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -87,6 +87,7 @@ class ErrorReporter void fatalDeclarationError(ErrorId _error, SourceLocation const& _location, std::string const& _description); void parserError(ErrorId _error, SourceLocation const& _location, std::string const& _description); + void parserError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description); void fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description); @@ -120,6 +121,9 @@ class ErrorReporter void unimplementedFeatureError(ErrorId _error, SourceLocation const& _location, std::string const& _description); + void codeGenerationError(ErrorId _error, SourceLocation const& _location, std::string const& _description); + void codeGenerationError(Error const& _error); + ErrorList const& errors() const; void clear(); diff --git a/liblangutil/ParserBase.cpp b/liblangutil/ParserBase.cpp index fde0f27ecc5a..00a38727daa1 100644 --- a/liblangutil/ParserBase.cpp +++ b/liblangutil/ParserBase.cpp @@ -43,7 +43,7 @@ Token ParserBase::peekNextToken() const return m_scanner->peekNextToken(); } -std::string ParserBase::currentLiteral() const +std::string_view ParserBase::currentLiteral() const { return m_scanner->currentLiteral(); } diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h index 88fc76a9c307..cd84da2234f7 100644 --- a/liblangutil/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -71,7 +71,8 @@ class ParserBase Token currentToken() const; Token peekNextToken() const; std::string tokenName(Token _token); - std::string currentLiteral() const; + /// Points to the current literal. The string view invalidates when the parser advances. + std::string_view currentLiteral() const; virtual Token advance(); ///@} diff --git a/liblangutil/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp index c48cb328d5f9..12308bf0d40b 100644 --- a/liblangutil/SourceReferenceFormatter.cpp +++ b/liblangutil/SourceReferenceFormatter.cpp @@ -114,11 +114,11 @@ AnsiColorized SourceReferenceFormatter::diagColored() const void SourceReferenceFormatter::printSourceLocation(SourceReference const& _ref) { - if (_ref.sourceName.empty()) - return; // Nothing we can print here - if (_ref.position.line < 0) { + if (_ref.sourceName.empty()) + return; // Nothing we can print here + frameColored() << "-->"; m_stream << ' ' << _ref.sourceName << '\n'; return; // No line available, nothing else to print diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp index 8a860791fa45..1c5ae6f4e707 100644 --- a/liblangutil/Token.cpp +++ b/liblangutil/Token.cpp @@ -134,20 +134,20 @@ std::string friendlyName(Token tok) } -static Token keywordByName(std::string const& _name) +static Token keywordByName(std::string_view const _name) { // The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored // and keywords to be put inside the keywords variable. #define KEYWORD(name, string, precedence) {string, Token::name}, #define TOKEN(name, string, precedence) - static std::map const keywords({TOKEN_LIST(TOKEN, KEYWORD)}); + static std::map> const keywords({TOKEN_LIST(TOKEN, KEYWORD)}); #undef KEYWORD #undef TOKEN auto it = keywords.find(_name); return it == keywords.end() ? Token::Identifier : it->second; } -bool isYulKeyword(std::string const& _literal) +bool isYulKeyword(std::string_view const _literal) { return _literal == "leave" || isYulKeyword(keywordByName(_literal)); } diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 49d739b5e32b..686635d2fe61 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -381,7 +381,7 @@ namespace TokenTraits return _token > Token::NonExperimentalEnd && _token < Token::ExperimentalEnd; } - bool isYulKeyword(std::string const& _literal); + bool isYulKeyword(std::string_view _literal); Token AssignmentToBinaryOp(Token op); diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index d23249d2200d..6b0534296f29 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -27,8 +27,8 @@ #include #include -#include #include +#include #include #include @@ -93,25 +93,32 @@ void CHCSmtLib2Interface::addRule(Expression const& _expr, std::string const& /* CHCSolverInterface::QueryResult CHCSmtLib2Interface::query(Expression const& _block) { std::string query = dumpQuery(_block); - std::string response = querySolver(query); + try + { + std::string response = querySolver(query); - CheckResult result; - // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking - // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. - // So we have to flip the answer. - if (boost::starts_with(response, "sat")) + CheckResult result; + // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking + // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. + // So we have to flip the answer. + if (boost::starts_with(response, "sat")) + { + auto maybeInvariants = invariantsFromSolverResponse(response); + return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + } + else if (boost::starts_with(response, "unsat")) + result = CheckResult::SATISFIABLE; + else if (boost::starts_with(response, "unknown")) + result = CheckResult::UNKNOWN; + else + result = CheckResult::ERROR; + return {result, Expression(true), {}}; + } + catch(smtutil::SMTSolverInteractionError const&) { - auto maybeInvariants = invariantsFromSolverResponse(response); - return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + return {CheckResult::ERROR, Expression(true), {}}; } - else if (boost::starts_with(response, "unsat")) - result = CheckResult::SATISFIABLE; - else if (boost::starts_with(response, "unknown")) - result = CheckResult::UNKNOWN; - else - result = CheckResult::ERROR; - return {result, Expression(true), {}}; } void CHCSmtLib2Interface::declareVariable(std::string const& _name, SortPointer const& _sort) @@ -250,7 +257,7 @@ SortPointer CHCSmtLib2Interface::ScopedParser::toSort(SMTLib2Expression const& _ auto const& args = asSubExpressions(_expr); if (asAtom(args[0]) == "Array") { - smtAssert(args.size() == 3); + smtSolverInteractionRequire(args.size() == 3, "Wrong format of Array sort in solver's response"); auto domainSort = toSort(args[1]); auto codomainSort = toSort(args[2]); return std::make_shared(std::move(domainSort), std::move(codomainSort)); @@ -259,7 +266,7 @@ SortPointer CHCSmtLib2Interface::ScopedParser::toSort(SMTLib2Expression const& _ && asAtom(args[1]) == "int2bv") return std::make_shared(std::stoul(asAtom(args[2]))); } - smtAssert(false, "Unknown sort encountered"); + smtSolverInteractionRequire(false, "Unknown sort encountered"); } smtutil::Expression CHCSmtLib2Interface::ScopedParser::parseQuantifier( @@ -270,20 +277,20 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::parseQuantifier( std::vector> boundVariables; for (auto const& sortedVar: _varList) { - smtAssert(!isAtom(sortedVar)); + smtSolverInteractionRequire(!isAtom(sortedVar), "Wrong format of quantified expression in solver's response"); auto varSortPair = asSubExpressions(sortedVar); - smtAssert(varSortPair.size() == 2); + smtSolverInteractionRequire(varSortPair.size() == 2, "Wrong format of quantified expression in solver's response"); boundVariables.emplace_back(asAtom(varSortPair[0]), toSort(varSortPair[1])); } for (auto const& [var, sort]: boundVariables) { - smtAssert(m_localVariables.count(var) == 0); // TODO: deal with shadowing? + smtSolverInteractionRequire(m_localVariables.count(var) == 0, "Quantifying over previously encountered variable"); // TODO: deal with shadowing? m_localVariables.emplace(var, sort); } auto core = toSMTUtilExpression(_coreExpression); for (auto const& [var, sort]: boundVariables) { - smtAssert(m_localVariables.count(var) != 0); + smtSolverInteractionRequire(m_localVariables.count(var) != 0, "Error in processing quantified expression"); m_localVariables.erase(var); } return Expression(_quantifierName, {core}, SortProvider::boolSort); // TODO: what about the bound variables? @@ -313,7 +320,7 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi return smtutil::Expression(_atom, {}, std::make_shared(_atom, std::vector{}, std::vector{})); } else - smtAssert(false, "Unhandled atomic SMT expression"); + smtSolverInteractionRequire(false, "Unhandled atomic SMT expression"); }, [&](std::vector const& _subExpr) { @@ -325,13 +332,13 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi if (op == "!") { // named term, we ignore the name - smtAssert(_subExpr.size() > 2); + smtSolverInteractionRequire(_subExpr.size() > 2, "Wrong format of named SMT-LIB term"); return toSMTUtilExpression(_subExpr[1]); } if (op == "exists" || op == "forall") { - smtAssert(_subExpr.size() == 3); - smtAssert(!isAtom(_subExpr[1])); + smtSolverInteractionRequire(_subExpr.size() == 3, "Wrong format of quantified expression"); + smtSolverInteractionRequire(!isAtom(_subExpr[1]), "Wrong format of quantified expression"); return parseQuantifier(op, asSubExpressions(_subExpr[1]), _subExpr[2]); } for (size_t i = 1; i < _subExpr.size(); i++) @@ -348,13 +355,28 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi auto accessor = maybeTupleAccessor.value(); return smtutil::Expression("dt_accessor_" + accessor.first, std::move(arguments), accessor.second); } + if (op == "select") + { + smtSolverInteractionRequire(arguments.size() == 2, "Select has two arguments: array and index"); + return smtutil::Expression::select(arguments[0], arguments[1]); + } + if (op == "store") + { + smtSolverInteractionRequire(arguments.size() == 3, "Store has three arguments: array, index and element"); + return smtutil::Expression::store(arguments[0], arguments[1], arguments[2]); + } + if (op == "bv2int") + { + smtSolverInteractionRequire(arguments.size() == 1, "bv2int has one argument"); + return smtutil::Expression::bv2int(arguments[0]); + } else { std::set boolOperators{"and", "or", "not", "=", "<", ">", "<=", ">=", "=>"}; sort = contains(boolOperators, op) ? SortProvider::boolSort : arguments.back().sort; return smtutil::Expression(op, std::move(arguments), std::move(sort)); } - smtAssert(false, "Unhandled case in expression conversion"); + smtSolverInteractionRequire(false, "Unhandled case in expression conversion"); } else { @@ -374,7 +396,7 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi && typeArgs[1].toString() == "int2bv") { auto bvSort = std::dynamic_pointer_cast(toSort(_subExpr[0])); - smtAssert(bvSort); + smtSolverInteractionRequire(bvSort, "Invalid format of bitvector sort"); return smtutil::Expression::int2bv(toSMTUtilExpression(_subExpr[1]), bvSort->size); } if (typeArgs.size() == 4 && typeArgs[0].toString() == "_" @@ -385,7 +407,7 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi SortProvider::bitVectorSort // TODO: Compute bit size properly? ); } - smtAssert(false, "Unhandled case in expression conversion"); + smtSolverInteractionRequire(false, "Unhandled case in expression conversion"); } } }, @@ -394,15 +416,15 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi } -#define precondition(CONDITION) if (!(CONDITION)) return {} std::optional CHCSmtLib2Interface::invariantsFromSolverResponse(std::string const& _response) const { std::stringstream ss(_response); std::string answer; ss >> answer; - precondition(answer == "sat"); + smtSolverInteractionRequire(answer == "sat", "CHC model can only be extracted from sat answer"); SMTLib2Parser parser(ss); - precondition(!parser.isEOF()); // There has to be a model + if (parser.isEOF()) + return {}; std::vector parsedOutput; try { @@ -411,25 +433,25 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp } catch(SMTLib2Parser::ParsingException&) { - return {}; + smtSolverInteractionRequire(false, "Error during parsing CHC model"); } - smtAssert(parser.isEOF()); - precondition(!parsedOutput.empty()); + smtSolverInteractionRequire(parser.isEOF(), "Error during parsing CHC model"); + smtSolverInteractionRequire(!parsedOutput.empty(), "Error during parsing CHC model"); auto& commands = parsedOutput.size() == 1 ? asSubExpressions(parsedOutput[0]) : parsedOutput; std::vector definitions; for (auto& command: commands) { auto& args = asSubExpressions(command); - precondition(args.size() == 5); + smtSolverInteractionRequire(args.size() == 5, "Invalid format of CHC model"); // args[0] = "define-fun" // args[1] = predicate name // args[2] = formal arguments of the predicate // args[3] = return sort // args[4] = body of the predicate's interpretation - precondition(isAtom(args[0]) && asAtom(args[0]) == "define-fun"); - precondition(isAtom(args[1])); - precondition(!isAtom(args[2])); - precondition(isAtom(args[3]) && asAtom(args[3]) == "Bool"); + smtSolverInteractionRequire(isAtom(args[0]) && asAtom(args[0]) == "define-fun", "Invalid format of CHC model"); + smtSolverInteractionRequire(isAtom(args[1]), "Invalid format of CHC model"); + smtSolverInteractionRequire(!isAtom(args[2]), "Invalid format of CHC model"); + smtSolverInteractionRequire(isAtom(args[3]) && asAtom(args[3]) == "Bool", "Invalid format of CHC model"); auto& interpretation = args[4]; inlineLetExpressions(interpretation); ScopedParser scopedParser(m_context); @@ -437,10 +459,10 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp std::vector predicateArgs; for (auto const& formalArgument: formalArguments) { - precondition(!isAtom(formalArgument)); + smtSolverInteractionRequire(!isAtom(formalArgument), "Invalid format of CHC model"); auto const& nameSortPair = asSubExpressions(formalArgument); - precondition(nameSortPair.size() == 2); - precondition(isAtom(nameSortPair[0])); + smtSolverInteractionRequire(nameSortPair.size() == 2, "Invalid format of CHC model"); + smtSolverInteractionRequire(isAtom(nameSortPair[0]), "Invalid format of CHC model"); SortPointer varSort = scopedParser.toSort(nameSortPair[1]); scopedParser.addVariableDeclaration(asAtom(nameSortPair[0]), varSort); // FIXME: Why Expression here? @@ -450,12 +472,17 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp auto parsedInterpretation = scopedParser.toSMTUtilExpression(interpretation); + // Hack to make invariants more stable across operating systems + if (parsedInterpretation.name == "and" || parsedInterpretation.name == "or") + ranges::sort(parsedInterpretation.arguments, [](Expression const& first, Expression const& second) { + return first.name < second.name; + }); + Expression predicate(asAtom(args[1]), predicateArgs, SortProvider::boolSort); definitions.push_back(predicate == parsedInterpretation); } return Expression::mkAnd(std::move(definitions)); } -#undef precondition namespace { @@ -472,8 +499,8 @@ struct LetBindings SMTLib2Expression& operator[](std::string const& varName) { auto it = bindings.find(varName); - smtAssert(it != bindings.end()); - smtAssert(!it->second.empty()); + smtSolverInteractionRequire(it != bindings.end(), "Error in processing let bindings"); + smtSolverInteractionRequire(!it->second.empty(), "Error in processing let bindings"); return it->second.back(); } @@ -481,13 +508,13 @@ struct LetBindings void popScope() { - smtAssert(!scopeBounds.empty()); + smtSolverInteractionRequire(!scopeBounds.empty(), "Error in processing let bindings"); auto bound = scopeBounds.back(); while (varNames.size() > bound) { auto const& varName = varNames.back(); auto it = bindings.find(varName); - smtAssert(it != bindings.end()); + smtSolverInteractionRequire(it != bindings.end(), "Error in processing let bindings"); auto& record = it->second; record.pop_back(); if (record.empty()) @@ -518,21 +545,21 @@ void inlineLetExpressions(SMTLib2Expression& _expr, LetBindings& _bindings) return; } auto& subexprs = asSubExpressions(_expr); - smtAssert(!subexprs.empty()); + smtSolverInteractionRequire(!subexprs.empty(), "Invalid let expression"); auto const& first = subexprs.at(0); if (isAtom(first) && asAtom(first) == "let") { - smtAssert(subexprs.size() == 3); - smtAssert(!isAtom(subexprs[1])); + smtSolverInteractionRequire(subexprs.size() == 3, "Invalid let expression"); + smtSolverInteractionRequire(!isAtom(subexprs[1]), "Invalid let expression"); auto& bindingExpressions = asSubExpressions(subexprs[1]); // process new bindings std::vector> newBindings; for (auto& binding: bindingExpressions) { - smtAssert(!isAtom(binding)); + smtSolverInteractionRequire(!isAtom(binding), "Invalid let expression"); auto& bindingPair = asSubExpressions(binding); - smtAssert(bindingPair.size() == 2); - smtAssert(isAtom(bindingPair.at(0))); + smtSolverInteractionRequire(bindingPair.size() == 2, "Invalid let expression"); + smtSolverInteractionRequire(isAtom(bindingPair.at(0)), "Invalid let expression"); inlineLetExpressions(bindingPair.at(1), _bindings); newBindings.emplace_back(asAtom(bindingPair.at(0)), bindingPair.at(1)); } @@ -556,7 +583,7 @@ void inlineLetExpressions(SMTLib2Expression& _expr, LetBindings& _bindings) { // A little hack to ensure quantified variables are not substituted because of some outer let definition: // We define the current binding of the variable to itself, before we recurse in to subterm - smtAssert(subexprs.size() == 3); + smtSolverInteractionRequire(subexprs.size() == 3, "Invalid let expression"); _bindings.pushScope(); for (auto const& sortedVar: asSubExpressions(subexprs.at(1))) { diff --git a/libsmtutil/CMakeLists.txt b/libsmtutil/CMakeLists.txt index c89c56f4f583..8b22da7dbd3b 100644 --- a/libsmtutil/CMakeLists.txt +++ b/libsmtutil/CMakeLists.txt @@ -16,30 +16,6 @@ set(sources Helpers.h ) -if (${Z3_FOUND}) - set(z3_SRCS Z3Interface.cpp Z3Interface.h Z3CHCInterface.cpp Z3CHCInterface.h) -else() - set(z3_SRCS) -endif() -if (${USE_Z3_DLOPEN}) - file(GLOB Z3_HEADERS ${Z3_HEADER_PATH}/z3*.h) - set(Z3_WRAPPER ${CMAKE_CURRENT_BINARY_DIR}/z3wrapper.cpp) - add_custom_command( - OUTPUT ${Z3_WRAPPER} - COMMAND ${Python3_EXECUTABLE} genz3wrapper.py ${Z3_HEADERS} > ${Z3_WRAPPER} - DEPENDS ${Z3_HEADERS} genz3wrapper.py - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - set(z3_SRCS ${z3_SRCS} ${Z3_WRAPPER} Z3Loader.cpp Z3Loader.h) -endif() - -add_library(smtutil ${sources} ${z3_SRCS}) +add_library(smtutil ${sources}) target_link_libraries(smtutil PUBLIC solutil Boost::boost) - -if (${USE_Z3_DLOPEN}) - target_include_directories(smtutil PUBLIC ${Z3_HEADER_PATH}) - target_link_libraries(smtutil PUBLIC ${CMAKE_DL_LIBS}) -elseif (${Z3_FOUND}) - target_link_libraries(smtutil PUBLIC z3::libz3) -endif() diff --git a/libsmtutil/Exceptions.h b/libsmtutil/Exceptions.h index 2a32c4fcda63..5c642b0e2a64 100644 --- a/libsmtutil/Exceptions.h +++ b/libsmtutil/Exceptions.h @@ -48,4 +48,16 @@ struct SMTLogicError: virtual util::Exception {}; "SMT assertion failed" \ ) + +// Error to indicate that some problem occurred during an interaction with external solver. +// This could be a problem with calling the solver or unexpected situation during the processing of solver's response. +struct SMTSolverInteractionError: virtual util::Exception {}; + +#define smtSolverInteractionRequire(CONDITION, DESCRIPTION) \ + assertThrowWithDefaultDescription( \ + (CONDITION), \ + ::solidity::smtutil::SMTSolverInteractionError, \ + (DESCRIPTION), \ + "Encountered problem during interaction with a solver" \ + ) } diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index 0914f8305dc3..0430f0d21ea0 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -119,7 +119,7 @@ std::vector parseValuesFromResponse(std::string const& _response) std::stringstream ss(_response); std::string answer; ss >> answer; - smtAssert(answer == "sat"); + smtSolverInteractionRequire(answer == "sat", "SMT: Parsing model values only possible after sat answer"); std::vector parsedOutput; SMTLib2Parser parser(ss); @@ -130,16 +130,16 @@ std::vector parseValuesFromResponse(std::string const& _response) } catch(SMTLib2Parser::ParsingException&) { - return {}; + smtSolverInteractionRequire(false, "Error during parsing SMT answer"); } - smtAssert(parsedOutput.size() == 1, "SMT: Expected model values as a single s-expression"); + smtSolverInteractionRequire(parsedOutput.size() == 1, "SMT: Expected model values as a single s-expression"); auto const& values = parsedOutput[0]; - smtAssert(!isAtom(values)); + smtSolverInteractionRequire(!isAtom(values), "Invalid format of values in SMT answer"); std::vector parsedValues; for (auto const& nameValuePair: asSubExpressions(values)) { - smtAssert(!isAtom(nameValuePair)); - smtAssert(asSubExpressions(nameValuePair).size() == 2); + smtSolverInteractionRequire(!isAtom(nameValuePair), "Invalid format of values in SMT answer"); + smtSolverInteractionRequire(asSubExpressions(nameValuePair).size() == 2, "Invalid format of values in SMT answer"); auto const& value = asSubExpressions(nameValuePair)[1]; parsedValues.push_back(value.toString()); } diff --git a/libsmtutil/SMTLib2Interface.h b/libsmtutil/SMTLib2Interface.h index 02b1c85ffe0e..fe5421acd202 100644 --- a/libsmtutil/SMTLib2Interface.h +++ b/libsmtutil/SMTLib2Interface.h @@ -105,7 +105,7 @@ class SMTLib2Interface: public BMCSolverInterface std::string checkSatAndGetValuesCommand(std::vector const& _expressionsToEvaluate); /// Communicates with the solver via the callback. Throws SMTSolverError on error. - std::string querySolver(std::string const& _input); + virtual std::string querySolver(std::string const& _input); SMTLib2Commands m_commands; SMTLib2Context m_context; diff --git a/libsmtutil/Z3CHCInterface.cpp b/libsmtutil/Z3CHCInterface.cpp deleted file mode 100644 index a79630b6e59b..000000000000 --- a/libsmtutil/Z3CHCInterface.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -// SPDX-License-Identifier: GPL-3.0 - -#include - -#include - -#include -#include - -using namespace solidity; -using namespace solidity::smtutil; - -Z3CHCInterface::Z3CHCInterface(std::optional _queryTimeout): - CHCSolverInterface(_queryTimeout), - m_z3Interface(std::make_unique(m_queryTimeout)), - m_context(m_z3Interface->context()), - m_solver(*m_context) -{ - Z3_get_version( - &std::get<0>(m_version), - &std::get<1>(m_version), - &std::get<2>(m_version), - &std::get<3>(m_version) - ); - - // These need to be set globally. - z3::set_param("rewriter.pull_cheap_ite", true); - - if (m_queryTimeout) - m_context->set("timeout", int(*m_queryTimeout)); - else - z3::set_param("rlimit", Z3Interface::resourceLimit); - - setSpacerOptions(); -} - -void Z3CHCInterface::declareVariable(std::string const& _name, SortPointer const& _sort) -{ - smtAssert(_sort, ""); - m_z3Interface->declareVariable(_name, _sort); -} - -void Z3CHCInterface::registerRelation(Expression const& _expr) -{ - smtAssert(_expr.sort->kind == Kind::Function); - m_z3Interface->declareVariable(_expr.name, _expr.sort); - m_solver.register_relation(m_z3Interface->functions().at(_expr.name)); -} - -void Z3CHCInterface::addRule(Expression const& _expr, std::string const& _name) -{ - z3::expr rule = m_z3Interface->toZ3Expr(_expr); - if (m_z3Interface->constants().empty()) - m_solver.add_rule(rule, m_context->str_symbol(_name.c_str())); - else - { - z3::expr_vector variables(*m_context); - for (auto const& var: m_z3Interface->constants()) - variables.push_back(var.second); - z3::expr boundRule = z3::forall(variables, rule); - m_solver.add_rule(boundRule, m_context->str_symbol(_name.c_str())); - } -} - -CHCSolverInterface::QueryResult Z3CHCInterface::query(Expression const& _expr) -{ - CheckResult result; - try - { - z3::expr z3Expr = m_z3Interface->toZ3Expr(_expr); - switch (m_solver.query(z3Expr)) - { - case z3::check_result::sat: - { - result = CheckResult::SATISFIABLE; - // z3 version 4.8.8 modified Spacer to also return - // proofs containing nonlinear clauses. - if (m_version >= std::tuple(4, 8, 8, 0)) - { - auto proof = m_solver.get_answer(); - return {result, Expression(true), cexGraph(proof)}; - } - break; - } - case z3::check_result::unsat: - { - result = CheckResult::UNSATISFIABLE; - auto invariants = m_z3Interface->fromZ3Expr(m_solver.get_answer()); - return {result, std::move(invariants), {}}; - } - case z3::check_result::unknown: - { - result = CheckResult::UNKNOWN; - break; - } - } - // TODO retrieve model / invariants - } - catch (z3::exception const& _err) - { - std::set msgs{ - /// Resource limit (rlimit) exhausted. - "max. resource limit exceeded", - /// User given timeout exhausted. - "canceled" - }; - if (msgs.count(_err.msg())) - result = CheckResult::UNKNOWN; - else - result = CheckResult::ERROR; - } - - return {result, Expression(true), {}}; -} - -void Z3CHCInterface::setSpacerOptions(bool _preProcessing) -{ - // Spacer options. - // These needs to be set in the solver. - // https://github.com/Z3Prover/z3/blob/master/src/muz/base/fp_params.pyg - z3::params p(*m_context); - // These are useful for solving problems with arrays and loops. - // Use quantified lemma generalizer. - p.set("fp.spacer.q3.use_qgen", true); - p.set("fp.spacer.mbqi", false); - // Ground pobs by using values from a model. - p.set("fp.spacer.ground_pobs", false); - - // Spacer optimization should be - // - enabled for better solving (default) - // - disable for counterexample generation - p.set("fp.xform.slice", _preProcessing); - p.set("fp.xform.inline_linear", _preProcessing); - p.set("fp.xform.inline_eager", _preProcessing); - - m_solver.set(p); -} - -/** -Convert a ground refutation into a linear or nonlinear counterexample. -The counterexample is given as an implication graph of the form -`premises => conclusion` where `premises` are the predicates -from the body of nonlinear clauses, representing the proof graph. - -This function is based on and similar to -https://github.com/Z3Prover/z3/blob/z3-4.8.8/src/muz/spacer/spacer_context.cpp#L2919 -(spacer::context::get_ground_sat_answer) -which generates linear counterexamples. -It is modified here to accept nonlinear CHCs as well, generating a DAG -instead of a path. -*/ -CHCSolverInterface::CexGraph Z3CHCInterface::cexGraph(z3::expr const& _proof) -{ - /// The root fact of the refutation proof is `false`. - /// The node itself is not a hyper resolution, so we need to - /// extract the `query` hyper resolution node from the - /// `false` node (the first child). - /// The proof has the shape above for z3 >=4.8.8. - /// If an older version is used, this check will fail and no - /// counterexample will be generated. - if (!_proof.is_app() || fact(_proof).decl().decl_kind() != Z3_OP_FALSE) - return {}; - - CexGraph graph; - - std::stack proofStack; - proofStack.push(_proof.arg(0)); - - auto const& root = proofStack.top(); - graph.nodes.emplace(root.id(), m_z3Interface->fromZ3Expr(fact(root))); - - std::set visited; - visited.insert(root.id()); - - while (!proofStack.empty()) - { - z3::expr proofNode = proofStack.top(); - smtAssert(graph.nodes.count(proofNode.id()), ""); - proofStack.pop(); - - if (proofNode.is_app() && proofNode.decl().decl_kind() == Z3_OP_PR_HYPER_RESOLVE) - { - smtAssert(proofNode.num_args() > 0, ""); - for (unsigned i = 1; i < proofNode.num_args() - 1; ++i) - { - z3::expr child = proofNode.arg(i); - if (!visited.count(child.id())) - { - visited.insert(child.id()); - proofStack.push(child); - } - - if (!graph.nodes.count(child.id())) - { - graph.nodes.emplace(child.id(), m_z3Interface->fromZ3Expr(fact(child))); - graph.edges[child.id()] = {}; - } - - graph.edges[proofNode.id()].push_back(child.id()); - } - } - } - - return graph; -} - -z3::expr Z3CHCInterface::fact(z3::expr const& _node) -{ - smtAssert(_node.is_app(), ""); - if (_node.num_args() == 0) - return _node; - return _node.arg(_node.num_args() - 1); -} - -std::string Z3CHCInterface::name(z3::expr const& _predicate) -{ - smtAssert(_predicate.is_app(), ""); - return _predicate.decl().name().str(); -} - -std::vector Z3CHCInterface::arguments(z3::expr const& _predicate) -{ - smtAssert(_predicate.is_app(), ""); - std::vector args; - for (unsigned i = 0; i < _predicate.num_args(); ++i) - args.emplace_back(_predicate.arg(i).to_string()); - return args; -} diff --git a/libsmtutil/Z3CHCInterface.h b/libsmtutil/Z3CHCInterface.h deleted file mode 100644 index 98f21246c297..000000000000 --- a/libsmtutil/Z3CHCInterface.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -// SPDX-License-Identifier: GPL-3.0 - -/** - * Z3 specific Horn solver interface. - */ - -#pragma once - -#include -#include - -#include -#include - -namespace solidity::smtutil -{ - -class Z3CHCInterface: public CHCSolverInterface -{ -public: - Z3CHCInterface(std::optional _queryTimeout = {}); - - /// Forwards variable declaration to Z3Interface. - void declareVariable(std::string const& _name, SortPointer const& _sort) override; - - void registerRelation(Expression const& _expr) override; - - void addRule(Expression const& _expr, std::string const& _name) override; - - QueryResult query(Expression const& _expr) override; - - Z3Interface* z3Interface() const { return m_z3Interface.get(); } - - void setSpacerOptions(bool _preProcessing = true); - -private: - /// Constructs a nonlinear counterexample graph from the refutation. - CHCSolverInterface::CexGraph cexGraph(z3::expr const& _proof); - /// @returns the fact from a proof node. - z3::expr fact(z3::expr const& _node); - /// @returns @a _predicate's name. - std::string name(z3::expr const& _predicate); - /// @returns the arguments of @a _predicate. - std::vector arguments(z3::expr const& _predicate); - - // Used to handle variables. - std::unique_ptr m_z3Interface; - - z3::context* m_context; - // Horn solver. - z3::fixedpoint m_solver; - - std::tuple m_version = std::tuple(0, 0, 0, 0); -}; - -} diff --git a/libsmtutil/Z3Interface.cpp b/libsmtutil/Z3Interface.cpp deleted file mode 100644 index efd656259819..000000000000 --- a/libsmtutil/Z3Interface.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -// SPDX-License-Identifier: GPL-3.0 - -#include - -#include -#include -#include - -#ifdef HAVE_Z3_DLOPEN -#include -#endif - -using namespace solidity::smtutil; -using namespace solidity::util; - -bool Z3Interface::available() -{ -#ifdef HAVE_Z3_DLOPEN - return Z3Loader::get().available(); -#else - return true; -#endif -} - -Z3Interface::Z3Interface(std::optional _queryTimeout): - BMCSolverInterface(_queryTimeout), - m_solver(m_context) -{ - // These need to be set globally. - z3::set_param("rewriter.pull_cheap_ite", true); - - if (m_queryTimeout) - m_context.set("timeout", int(*m_queryTimeout)); - else - z3::set_param("rlimit", resourceLimit); -} - -void Z3Interface::reset() -{ - m_constants.clear(); - m_functions.clear(); - m_solver.reset(); -} - -void Z3Interface::push() -{ - m_solver.push(); -} - -void Z3Interface::pop() -{ - m_solver.pop(); -} - -void Z3Interface::declareVariable(std::string const& _name, SortPointer const& _sort) -{ - smtAssert(_sort, ""); - if (_sort->kind == Kind::Function) - declareFunction(_name, *_sort); - else if (m_constants.count(_name)) - m_constants.at(_name) = m_context.constant(_name.c_str(), z3Sort(*_sort)); - else - m_constants.emplace(_name, m_context.constant(_name.c_str(), z3Sort(*_sort))); -} - -void Z3Interface::declareFunction(std::string const& _name, Sort const& _sort) -{ - smtAssert(_sort.kind == Kind::Function, ""); - FunctionSort fSort = dynamic_cast(_sort); - if (m_functions.count(_name)) - m_functions.at(_name) = m_context.function(_name.c_str(), z3Sort(fSort.domain), z3Sort(*fSort.codomain)); - else - m_functions.emplace(_name, m_context.function(_name.c_str(), z3Sort(fSort.domain), z3Sort(*fSort.codomain))); -} - -void Z3Interface::addAssertion(Expression const& _expr) -{ - m_solver.add(toZ3Expr(_expr)); -} - -std::pair> Z3Interface::check(std::vector const& _expressionsToEvaluate) -{ - CheckResult result; - std::vector values; - try - { - switch (m_solver.check()) - { - case z3::check_result::sat: - result = CheckResult::SATISFIABLE; - break; - case z3::check_result::unsat: - result = CheckResult::UNSATISFIABLE; - break; - case z3::check_result::unknown: - result = CheckResult::UNKNOWN; - break; - } - - if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty()) - { - z3::model m = m_solver.get_model(); - for (Expression const& e: _expressionsToEvaluate) - values.push_back(util::toString(m.eval(toZ3Expr(e)))); - } - } - catch (z3::exception const& _err) - { - std::set msgs{ - /// Resource limit (rlimit) exhausted. - "max. resource limit exceeded", - /// User given timeout exhausted. - "canceled" - }; - - if (msgs.count(_err.msg())) - result = CheckResult::UNKNOWN; - else - result = CheckResult::ERROR; - values.clear(); - } - - return std::make_pair(result, values); -} - -z3::expr Z3Interface::toZ3Expr(Expression const& _expr) -{ - if (_expr.arguments.empty() && m_constants.count(_expr.name)) - return m_constants.at(_expr.name); - z3::expr_vector arguments(m_context); - for (auto const& arg: _expr.arguments) - arguments.push_back(toZ3Expr(arg)); - - try - { - std::string const& n = _expr.name; - if (m_functions.count(n)) - return m_functions.at(n)(arguments); - else if (m_constants.count(n)) - { - smtAssert(arguments.empty(), ""); - return m_constants.at(n); - } - else if (arguments.empty()) - { - if (n == "true") - return m_context.bool_val(true); - else if (n == "false") - return m_context.bool_val(false); - else if (_expr.sort->kind == Kind::Sort) - { - auto sortSort = std::dynamic_pointer_cast(_expr.sort); - smtAssert(sortSort, ""); - return m_context.constant(n.c_str(), z3Sort(*sortSort->inner)); - } - else if (n == "tuple_constructor") - { - auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, z3Sort(*_expr.sort))); - smtAssert(constructor.arity() == arguments.size()); - return constructor(); - } - else - try - { - return m_context.int_val(n.c_str()); - } - catch (z3::exception const& _e) - { - smtAssert(false, _e.msg()); - } - } - - smtAssert(_expr.hasCorrectArity(), ""); - if (n == "ite") - return z3::ite(arguments[0], arguments[1], arguments[2]); - else if (n == "not") - return !arguments[0]; - else if (n == "and") - return arguments[0] && arguments[1]; - else if (n == "or") - return arguments[0] || arguments[1]; - else if (n == "=>") - return z3::implies(arguments[0], arguments[1]); - else if (n == "=") - return arguments[0] == arguments[1]; - else if (n == "<") - return arguments[0] < arguments[1]; - else if (n == "<=") - return arguments[0] <= arguments[1]; - else if (n == ">") - return arguments[0] > arguments[1]; - else if (n == ">=") - return arguments[0] >= arguments[1]; - else if (n == "+") - return arguments[0] + arguments[1]; - else if (n == "-") - return arguments[0] - arguments[1]; - else if (n == "*") - return arguments[0] * arguments[1]; - else if (n == "div") - return arguments[0] / arguments[1]; - else if (n == "mod") - return z3::mod(arguments[0], arguments[1]); - else if (n == "bvnot") - return ~arguments[0]; - else if (n == "bvand") - return arguments[0] & arguments[1]; - else if (n == "bvor") - return arguments[0] | arguments[1]; - else if (n == "bvxor") - return arguments[0] ^ arguments[1]; - else if (n == "bvshl") - return z3::shl(arguments[0], arguments[1]); - else if (n == "bvlshr") - return z3::lshr(arguments[0], arguments[1]); - else if (n == "bvashr") - return z3::ashr(arguments[0], arguments[1]); - else if (n == "int2bv") - { - size_t size = std::stoul(_expr.arguments[1].name); - return z3::int2bv(static_cast(size), arguments[0]); - } - else if (n == "bv2int") - { - auto intSort = std::dynamic_pointer_cast(_expr.sort); - smtAssert(intSort, ""); - return z3::bv2int(arguments[0], intSort->isSigned); - } - else if (n == "select") - return z3::select(arguments[0], arguments[1]); - else if (n == "store") - return z3::store(arguments[0], arguments[1], arguments[2]); - else if (n == "const_array") - { - std::shared_ptr sortSort = std::dynamic_pointer_cast(_expr.arguments[0].sort); - smtAssert(sortSort, ""); - auto arraySort = std::dynamic_pointer_cast(sortSort->inner); - smtAssert(arraySort && arraySort->domain, ""); - return z3::const_array(z3Sort(*arraySort->domain), arguments[1]); - } - else if (n == "tuple_get") - { - size_t index = stoul(_expr.arguments[1].name); - return z3::func_decl(m_context, Z3_get_tuple_sort_field_decl(m_context, z3Sort(*_expr.arguments[0].sort), static_cast(index)))(arguments[0]); - } - else if (n == "tuple_constructor") - { - auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, z3Sort(*_expr.sort))); - smtAssert(constructor.arity() == arguments.size(), ""); - z3::expr_vector args(m_context); - for (auto const& arg: arguments) - args.push_back(arg); - return constructor(args); - } - - smtAssert(false); - } - catch (z3::exception const& _e) - { - smtAssert(false, _e.msg()); - } - - smtAssert(false); - - // FIXME: Workaround for spurious GCC 12.1 warning (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105794) - util::unreachable(); -} - -Expression Z3Interface::fromZ3Expr(z3::expr const& _expr) -{ - auto sort = fromZ3Sort(_expr.get_sort()); - if (_expr.is_const() || _expr.is_var()) - return Expression(_expr.to_string(), {}, sort); - - if (_expr.is_quantifier()) - { - std::string quantifierName; - if (_expr.is_exists()) - quantifierName = "exists"; - else if (_expr.is_forall()) - quantifierName = "forall"; - else if (_expr.is_lambda()) - quantifierName = "lambda"; - else - smtAssert(false, ""); - return Expression(quantifierName, {fromZ3Expr(_expr.body())}, sort); - } - smtAssert(_expr.is_app(), ""); - std::vector arguments; - for (unsigned i = 0; i < _expr.num_args(); ++i) - arguments.push_back(fromZ3Expr(_expr.arg(i))); - - auto kind = _expr.decl().decl_kind(); - - if (_expr.is_ite()) - return Expression::ite(arguments[0], arguments[1], arguments[2]); - else if (_expr.is_not()) - return !arguments[0]; - else if (_expr.is_and()) - return Expression::mkAnd(arguments); - else if (_expr.is_or()) - return Expression::mkOr(arguments); - else if (_expr.is_implies()) - return Expression::implies(arguments[0], arguments[1]); - else if (_expr.is_eq()) - { - smtAssert(arguments.size() == 2, ""); - return arguments[0] == arguments[1]; - } - else if (kind == Z3_OP_ULT || kind == Z3_OP_SLT) - return arguments[0] < arguments[1]; - else if (kind == Z3_OP_LE || kind == Z3_OP_ULEQ || kind == Z3_OP_SLEQ) - return arguments[0] <= arguments[1]; - else if (kind == Z3_OP_GT || kind == Z3_OP_SGT) - return arguments[0] > arguments[1]; - else if (kind == Z3_OP_GE || kind == Z3_OP_UGEQ || kind == Z3_OP_SGEQ) - return arguments[0] >= arguments[1]; - else if (kind == Z3_OP_ADD) - return Expression::mkPlus(arguments); - else if (kind == Z3_OP_SUB) - { - smtAssert(arguments.size() == 2, ""); - return arguments[0] - arguments[1]; - } - else if (kind == Z3_OP_MUL) - return Expression::mkMul(arguments); - else if (kind == Z3_OP_DIV) - { - smtAssert(arguments.size() == 2, ""); - return arguments[0] / arguments[1]; - } - else if (kind == Z3_OP_MOD) - return arguments[0] % arguments[1]; - else if (kind == Z3_OP_XOR) - return arguments[0] ^ arguments[1]; - else if (kind == Z3_OP_BOR) - return arguments[0] | arguments[1]; - else if (kind == Z3_OP_BAND) - return arguments[0] & arguments[1]; - else if (kind == Z3_OP_BXOR) - return arguments[0] ^ arguments[1]; - else if (kind == Z3_OP_BNOT) - return !arguments[0]; - else if (kind == Z3_OP_BSHL) - return arguments[0] << arguments[1]; - else if (kind == Z3_OP_BLSHR) - return arguments[0] >> arguments[1]; - else if (kind == Z3_OP_BASHR) - return Expression::ashr(arguments[0], arguments[1]); - else if (kind == Z3_OP_INT2BV) - return Expression::int2bv(arguments[0], _expr.get_sort().bv_size()); - else if (kind == Z3_OP_BV2INT) - return Expression::bv2int(arguments[0]); - else if (kind == Z3_OP_EXTRACT) - return Expression("extract", arguments, sort); - else if (kind == Z3_OP_SELECT) - return Expression::select(arguments[0], arguments[1]); - else if (kind == Z3_OP_STORE) - return Expression::store(arguments[0], arguments[1], arguments[2]); - else if (kind == Z3_OP_CONST_ARRAY) - { - auto sortSort = std::make_shared(fromZ3Sort(_expr.get_sort())); - return Expression::const_array(Expression(sortSort), arguments[0]); - } - else if (kind == Z3_OP_DT_CONSTRUCTOR) - { - auto sortSort = std::make_shared(fromZ3Sort(_expr.get_sort())); - return Expression::tuple_constructor(Expression(sortSort), arguments); - } - else if (kind == Z3_OP_DT_ACCESSOR) - return Expression("dt_accessor_" + _expr.decl().name().str(), arguments, sort); - else if (kind == Z3_OP_DT_IS) - return Expression("dt_is", {arguments.at(0)}, sort); - else if ( - kind == Z3_OP_UNINTERPRETED || - kind == Z3_OP_RECURSIVE - ) - return Expression(_expr.decl().name().str(), arguments, fromZ3Sort(_expr.get_sort())); - else if (kind == Z3_OP_CONCAT) - return Expression("concat", arguments, sort); - - smtAssert(false); - - // FIXME: Workaround for spurious GCC 12.1 warning (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105794) - util::unreachable(); -} - -z3::sort Z3Interface::z3Sort(Sort const& _sort) -{ - switch (_sort.kind) - { - case Kind::Bool: - return m_context.bool_sort(); - case Kind::Int: - return m_context.int_sort(); - case Kind::BitVector: - return m_context.bv_sort(dynamic_cast(_sort).size); - case Kind::Array: - { - auto const& arraySort = dynamic_cast(_sort); - return m_context.array_sort(z3Sort(*arraySort.domain), z3Sort(*arraySort.range)); - } - case Kind::Tuple: - { - auto const& tupleSort = dynamic_cast(_sort); - std::vector cMembers; - for (auto const& member: tupleSort.members) - cMembers.emplace_back(member.c_str()); - /// Using this instead of the function below because with that one - /// we can't use `&sorts[0]` here. - std::vector sorts; - for (auto const& sort: tupleSort.components) - sorts.push_back(z3Sort(*sort)); - z3::func_decl_vector projs(m_context); - z3::func_decl tupleConstructor = m_context.tuple_sort( - tupleSort.name.c_str(), - static_cast(tupleSort.members.size()), - cMembers.data(), - sorts.data(), - projs - ); - return tupleConstructor.range(); - } - - default: - break; - } - smtAssert(false, ""); - // Cannot be reached. - return m_context.int_sort(); -} - -z3::sort_vector Z3Interface::z3Sort(std::vector const& _sorts) -{ - z3::sort_vector z3Sorts(m_context); - for (auto const& _sort: _sorts) - z3Sorts.push_back(z3Sort(*_sort)); - return z3Sorts; -} - -SortPointer Z3Interface::fromZ3Sort(z3::sort const& _sort) -{ - if (_sort.is_bool()) - return SortProvider::boolSort; - if (_sort.is_int()) - return SortProvider::sintSort; - if (_sort.is_bv()) - return std::make_shared(_sort.bv_size()); - if (_sort.is_array()) - return std::make_shared(fromZ3Sort(_sort.array_domain()), fromZ3Sort(_sort.array_range())); - if (_sort.is_datatype()) - { - auto name = _sort.name().str(); - auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, _sort)); - std::vector memberNames; - std::vector memberSorts; - for (unsigned i = 0; i < constructor.arity(); ++i) - { - auto accessor = z3::func_decl(m_context, Z3_get_tuple_sort_field_decl(m_context, _sort, i)); - memberNames.push_back(accessor.name().str()); - memberSorts.push_back(fromZ3Sort(accessor.range())); - } - return std::make_shared(name, memberNames, memberSorts); - } - smtAssert(false, ""); -} - -std::vector Z3Interface::fromZ3Sort(z3::sort_vector const& _sorts) -{ - return applyMap(_sorts, [this](auto const& sort) { return fromZ3Sort(sort); }); -} diff --git a/libsmtutil/Z3Interface.h b/libsmtutil/Z3Interface.h deleted file mode 100644 index ee5270f440c9..000000000000 --- a/libsmtutil/Z3Interface.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -// SPDX-License-Identifier: GPL-3.0 - -#pragma once - -#include -#include - -namespace solidity::smtutil -{ - -class Z3Interface: public BMCSolverInterface -{ -public: - /// Noncopyable. - Z3Interface(Z3Interface const&) = delete; - Z3Interface& operator=(Z3Interface const&) = delete; - - Z3Interface(std::optional _queryTimeout = {}); - - static bool available(); - - void reset() override; - - void push() override; - void pop() override; - - void declareVariable(std::string const& _name, SortPointer const& _sort) override; - - void addAssertion(Expression const& _expr) override; - std::pair> check(std::vector const& _expressionsToEvaluate) override; - - z3::expr toZ3Expr(Expression const& _expr); - smtutil::Expression fromZ3Expr(z3::expr const& _expr); - - std::map constants() const { return m_constants; } - std::map functions() const { return m_functions; } - - z3::context* context() { return &m_context; } - - // Z3 "basic resources" limit. - // This is used to make the runs more deterministic and platform/machine independent. - static int const resourceLimit = 2000000; - -private: - void declareFunction(std::string const& _name, Sort const& _sort); - - z3::sort z3Sort(Sort const& _sort); - z3::sort_vector z3Sort(std::vector const& _sorts); - smtutil::SortPointer fromZ3Sort(z3::sort const& _sort); - std::vector fromZ3Sort(z3::sort_vector const& _sorts); - - z3::context m_context; - z3::solver m_solver; - - std::map m_constants; - std::map m_functions; -}; - -} diff --git a/libsmtutil/Z3Loader.cpp b/libsmtutil/Z3Loader.cpp deleted file mode 100644 index 0211f600d9f1..000000000000 --- a/libsmtutil/Z3Loader.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -// SPDX-License-Identifier: GPL-3.0 - -#include -#include -#include -#include -#include - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include - -using namespace solidity; -using namespace solidity::smtutil; - -Z3Loader const& Z3Loader::get() -{ - static Z3Loader z3; - return z3; -} - -void* Z3Loader::loadSymbol(char const* _name) const -{ - smtAssert(m_handle, "Attempted to use dynamically loaded Z3, even though it is not available."); - void* sym = dlsym(m_handle, _name); - smtAssert(sym, std::string("Symbol \"") + _name + "\" not found in libz3.so"); - return sym; -} - -bool Z3Loader::available() const -{ - if (m_handle == nullptr) - return false; - unsigned major = 0; - unsigned minor = 0; - unsigned build = 0; - unsigned rev = 0; - Z3_get_version(&major, &minor, &build, &rev); - return major == Z3_MAJOR_VERSION && minor == Z3_MINOR_VERSION; -} - -Z3Loader::Z3Loader() -{ - std::string libname{"libz3.so." + std::to_string(Z3_MAJOR_VERSION) + "." + std::to_string(Z3_MINOR_VERSION)}; - m_handle = dlmopen(LM_ID_NEWLM, libname.c_str(), RTLD_NOW); -} - -Z3Loader::~Z3Loader() -{ - if (m_handle) - dlclose(m_handle); -} diff --git a/libsmtutil/genz3wrapper.py b/libsmtutil/genz3wrapper.py deleted file mode 100755 index 9b24b32dbfe1..000000000000 --- a/libsmtutil/genz3wrapper.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python3 -# ------------------------------------------------------------------------------ -# 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 -#------------------------------------------------------------------------------ -# -# Script that generates a dlsym-wrapper for Z3 from the header files. -# Expects all Z3 headers as arguments and outputs the wrapper code to stdout. - -import sys -import re - -# Patterns to match Z3 API entry point definitions. -def_pat = re.compile(" *def_API(.*)") -extradef_pat = re.compile(" *extra_API(.*)") -# Pattern to extract name and arguments from the above. -def_args_pat = re.compile("\('([^']*)'[^\(\)]*\((.*)\)\s*\)") -# Pattern to extract a list of arguments from the above. -arg_list_pat = re.compile("[^\(]*\([^\)]*\)[, ]*") - -def generateEntryPoint(line, args): - m = def_args_pat.match(args) - if not m: - raise Exception('Could not parse entry point definition: ' + line) - name = m.group(1) - num_args = len(arg_list_pat.findall(m.group(2))) - arglist = ', '.join(f"_{i}" for i in range(num_args)) - paramlist = ', '.join(f"ArgType<&{name}, {i}> _{i}" for i in range(num_args)) - print(f'ResultType<&{name}> Z3_API {name}({paramlist})') - print('{') - print(f'\tstatic auto sym = reinterpret_cast(Z3Loader::get().loadSymbol(\"{name}\"));') - print(f'\treturn sym({arglist});') - print('}') - - -print(r"""// This file is auto-generated from genz3wrapper.py -#include -#include -#include - -namespace -{ - -template -struct FunctionTrait; - -template -struct FunctionTrait -{ - using ResultType = R; - template - using ArgType = std::tuple_element_t>; -}; - -template -using ResultType = typename FunctionTrait::ResultType; - -template -using ArgType = typename FunctionTrait::template ArgType; - -} - -using namespace solidity; -using namespace solidity::smtutil; - -extern "C" -{ - -void Z3_API Z3_set_error_handler(Z3_context c, Z3_error_handler h) -{ - static auto sym = reinterpret_cast(Z3Loader::get().loadSymbol("Z3_set_error_handler")); - sym(c, h); -} -""") - -for header in sys.argv[1:]: - with open(header, 'r') as f: - for line in f: - line = line.strip('\r\n\t ') - m = def_pat.match(line) - if m: - generateEntryPoint(line, m.group(1).strip('\r\n\t ')) - m = extradef_pat.match(line) - if m: - generateEntryPoint(line, m.group(1).strip('\r\n\t ')) - -print('}') diff --git a/libsolc/libsolc.cpp b/libsolc/libsolc.cpp index b49905130ccc..47dddb3aea08 100644 --- a/libsolc/libsolc.cpp +++ b/libsolc/libsolc.cpp @@ -63,7 +63,7 @@ std::string takeOverAllocation(char const* _data) abort(); } -/// Resizes a std::std::string to the proper length based on the occurrence of a zero terminator. +/// Resizes a std::string to the proper length based on the occurrence of a zero terminator. void truncateCString(std::string& _data) { size_t pos = _data.find('\0'); diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 0b796035d313..5925a50ac480 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -141,6 +141,10 @@ set(sources formal/SymbolicVariables.h formal/VariableUsage.cpp formal/VariableUsage.h + formal/Z3CHCSmtLib2Interface.cpp + formal/Z3CHCSmtLib2Interface.h + formal/Z3SMTLib2Interface.cpp + formal/Z3SMTLib2Interface.h interface/ABI.cpp interface/ABI.h interface/CompilerStack.cpp @@ -220,3 +224,9 @@ set(sources add_library(solidity ${sources}) target_link_libraries(solidity PUBLIC yul evmasm langutil smtutil solutil Boost::boost fmt::fmt-header-only Threads::Threads) +if (EMSCRIPTEN) + if(NOT ${Z3_FOUND}) + message(FATAL_ERROR "Z3 library must be present for EMSCRIPTEN build") + endif() + target_link_libraries(solidity PUBLIC z3::libz3) +endif() diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 8e18183a81f9..0d953be93ff4 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -269,6 +269,20 @@ std::optional ConstantEvaluator::evaluate( return ConstantEvaluator{_errorReporter}.evaluate(_expr); } +std::optional ConstantEvaluator::tryEvaluate(Expression const& _expr) +{ + ErrorList errorList; + ErrorReporter errorReporter(errorList); + try + { + return ConstantEvaluator{errorReporter}.evaluate(_expr); + } + catch (FatalError const&) + { + return std::nullopt; + } +} + std::optional ConstantEvaluator::evaluate(ASTNode const& _node) { diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 5b4b3460446b..297d5f6e80c9 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -57,6 +57,10 @@ class ConstantEvaluator: private ASTConstVisitor Expression const& _expr ); + /// Works the same as `evaluate` but swallows any errors that might occur in the evaluation and simply returns + /// `std::nullopt` instead. + static std::optional tryEvaluate(Expression const& _expr); + /// Performs arbitrary-precision evaluation of a binary operator. Returns nullopt on cases like /// division by zero or e.g. bit operators applied to fractional values. static std::optional evaluateBinaryOperator(Token _operator, rational const& _left, rational const& _right); diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index eaeaf4851710..08d8fc9f779b 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,7 @@ #include +#include #include using namespace solidity; @@ -97,10 +99,44 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkBaseABICompatibility(_contract); checkPayableFallbackWithoutReceive(_contract); checkStorageSize(_contract); + checkStorageLayoutSpecifier(_contract); return !Error::containsErrors(m_errorReporter.errors()); } +void ContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinition const& _contract) +{ + if (_contract.storageLayoutSpecifier()) + { + solAssert(!_contract.isLibrary() && !_contract.isInterface()); + + if (_contract.abstract()) + m_errorReporter.typeError( + 7587_error, + _contract.storageLayoutSpecifier()->location(), + "Storage layout cannot be specified for abstract contracts." + ); + } + + for (auto const& baseContractSpecifier: _contract.baseContracts()) + { + auto const* baseContract = dynamic_cast( + baseContractSpecifier->name().annotation().referencedDeclaration + ); + + solAssert(baseContract); + if (baseContract->storageLayoutSpecifier()) + m_errorReporter.typeError( + 8894_error, + baseContractSpecifier->location(), + SecondarySourceLocation().append( + "Custom storage layout defined here:", + baseContract->storageLayoutSpecifier()->location() + ), + "Cannot inherit from a contract with a custom storage layout." + ); + } +} void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _contract) { /// Checks that two functions with the same name defined in this contract have different @@ -555,16 +591,16 @@ void ContractLevelChecker::checkPayableFallbackWithoutReceive(ContractDefinition void ContractLevelChecker::checkStorageSize(ContractDefinition const& _contract) { - bigint size = 0; - for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts | ranges::views::reverse) - for (VariableDeclaration const* variable: contract->stateVariables()) - if (!(variable->isConstant() || variable->immutable())) - { - size += variable->annotation().type->storageSizeUpperBound(); - if (size >= bigint(1) << 256) - { - m_errorReporter.typeError(7676_error, _contract.location(), "Contract requires too much storage."); - break; - } - } + using enum VariableDeclaration::Location; + for (VariableDeclaration::Location location: {Unspecified, Transient}) + { + bigint size = contractStorageSizeUpperBound(_contract, location); + if (size >= bigint(1) << 256) + { + if (location == Unspecified) + m_errorReporter.typeError(7676_error, _contract.location(), "Contract requires too much storage."); + else + m_errorReporter.typeError(5026_error, _contract.location(), "Contract requires too much transient storage."); + } + } } diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index 1f5826fdc059..e51e39dc3963 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -88,8 +88,10 @@ class ContractLevelChecker /// Warns if the contract has a payable fallback, but no receive ether function. void checkPayableFallbackWithoutReceive(ContractDefinition const& _contract); - /// Error if the contract requires too much storage + /// Error if the contract requires too much storage or transient storage void checkStorageSize(ContractDefinition const& _contract); + /// Checks if the storage layout specifier is properly assigned in the inheritance tree and not applied to an abstract contract + void checkStorageLayoutSpecifier(ContractDefinition const& _contract); OverrideChecker m_overrideChecker; langutil::ErrorReporter& m_errorReporter; diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp index 7ae1aa76e2b9..8c9c6ba5c4fa 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.cpp +++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp @@ -74,12 +74,12 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod bool propagateFrom(NodeInfo const& _entryNode) { size_t previousUnassignedVariablesAtEntry = unassignedVariablesAtEntry.size(); - size_t previousUninitializedVariableAccessess = uninitializedVariableAccesses.size(); + size_t previousUninitializedVariableAccesses = uninitializedVariableAccesses.size(); unassignedVariablesAtEntry += _entryNode.unassignedVariablesAtExit; uninitializedVariableAccesses += _entryNode.uninitializedVariableAccesses; return unassignedVariablesAtEntry.size() > previousUnassignedVariablesAtEntry || - uninitializedVariableAccesses.size() > previousUninitializedVariableAccessess + uninitializedVariableAccesses.size() > previousUninitializedVariableAccesses ; } }; diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index 7bc0ebc7bf58..11d8e84c6601 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include using namespace solidity::langutil; @@ -582,7 +583,7 @@ void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall) solAssert(m_currentNode && m_inlineAssembly, ""); yul::ASTWalker::operator()(_functionCall); - if (auto const *builtinFunction = m_inlineAssembly->dialect().builtin(_functionCall.functionName.name)) + if (auto const* builtinFunction = resolveBuiltinFunction(_functionCall.functionName, m_inlineAssembly->dialect())) { if (builtinFunction->controlFlowSideEffects.canTerminate) connect(m_currentNode, m_transactionReturnNode); diff --git a/libsolidity/analysis/ControlFlowBuilder.h b/libsolidity/analysis/ControlFlowBuilder.h index 93bc52bd6936..7af843fcaec9 100644 --- a/libsolidity/analysis/ControlFlowBuilder.h +++ b/libsolidity/analysis/ControlFlowBuilder.h @@ -137,7 +137,7 @@ class ControlFlowBuilder: private ASTConstVisitor, private yul::ASTWalker } /// Merges the control flow of @a _nodes to @a _endNode. - /// If @a _endNode is nullptr, a new node is creates and used as end node. + /// If @a _endNode is nullptr, a new node is created and used as end node. /// Sets the merge destination as current node. /// Note: @a _endNode may be one of the nodes in @a _nodes. template diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 32ef6d476b22..2d55b46fc9f7 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -61,9 +61,14 @@ bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode { DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errorReporter, m_globalContext, _currentScope); } - catch (langutil::FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } return false; } return true; @@ -135,9 +140,14 @@ bool NameAndTypeResolver::resolveNamesAndTypes(SourceUnit& _source) return false; } } - catch (langutil::FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } return false; } return true; @@ -150,9 +160,14 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) m_scopes[nullptr]->registerDeclaration(_declaration, false, true); solAssert(_declaration.scope() == nullptr, "Updated declaration outside global scope."); } - catch (langutil::FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } return false; } return true; @@ -299,6 +314,10 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res if (!resolveNamesAndTypesInternal(*baseContract, true)) success = false; + if (StorageLayoutSpecifier* storageLayoutSpecifier = contract->storageLayoutSpecifier()) + if (!resolveNamesAndTypesInternal(*storageLayoutSpecifier, true)) + success = false; + setScope(contract); if (success) @@ -716,7 +735,7 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio ); // NOTE: We're registering the function outside of its scope(). This will only affect - // name lookups. An more general alternative would be to modify Scoper to simply assign it + // name lookups. A more general alternative would be to modify Scoper to simply assign it // that scope in the first place, but this would complicate the AST traversal here, which // currently assumes that scopes follow ScopeOpener nesting. registerDeclaration(*m_scopes.at(quantifier->scope()), _declaration, nullptr, nullptr, false /* inactive */, m_errorReporter); diff --git a/libsolidity/analysis/OverrideChecker.cpp b/libsolidity/analysis/OverrideChecker.cpp index f2a99340deee..f51aa2b6e5e0 100644 --- a/libsolidity/analysis/OverrideChecker.cpp +++ b/libsolidity/analysis/OverrideChecker.cpp @@ -801,7 +801,7 @@ void OverrideChecker::checkAmbiguousOverridesInternal(std::set _b std::string callableName = _baseCallables.begin()->astNodeName(); if (_baseCallables.begin()->isVariable()) callableName = "function"; - std::string distinguishigProperty = _baseCallables.begin()->distinguishingProperty(); + std::string distinguishingProperty = _baseCallables.begin()->distinguishingProperty(); bool foundVariable = false; for (auto const& base: _baseCallables) @@ -811,7 +811,7 @@ void OverrideChecker::checkAmbiguousOverridesInternal(std::set _b std::string message = "Derived contract must override " + callableName + " \"" + _baseCallables.begin()->name() + - "\". Two or more base classes define " + callableName + " with same " + distinguishigProperty + "."; + "\". Two or more base classes define " + callableName + " with same " + distinguishingProperty + "."; if (foundVariable) message += diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.cpp b/libsolidity/analysis/PostTypeContractLevelChecker.cpp index 6d8dc416aa00..c7b7b0961622 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.cpp +++ b/libsolidity/analysis/PostTypeContractLevelChecker.cpp @@ -22,13 +22,21 @@ #include +#include #include +#include +#include #include #include +#include + +#include + using namespace solidity; using namespace solidity::langutil; using namespace solidity::frontend; +using namespace solidity::util; bool PostTypeContractLevelChecker::check(SourceUnit const& _sourceUnit) { @@ -51,7 +59,7 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract) for (ErrorDefinition const* error: _contract.interfaceErrors()) { std::string signature = error->functionType(true)->externalSignature(); - uint32_t hash = util::selectorFromSignatureU32(signature); + uint32_t hash = selectorFromSignatureU32(signature); // Fail if there is a different signature for the same hash. if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature)) { @@ -67,5 +75,134 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract) errorHashes[hash][signature] = error->location(); } + if (_contract.storageLayoutSpecifier()) + checkStorageLayoutSpecifier(_contract); + + warnStorageLayoutBaseNearStorageEnd(_contract); + return !Error::containsErrors(m_errorReporter.errors()); } + +void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinition const& _contract) +{ + StorageLayoutSpecifier const* storageLayoutSpecifier = _contract.storageLayoutSpecifier(); + solAssert(storageLayoutSpecifier); + Expression const& baseSlotExpression = storageLayoutSpecifier->baseSlotExpression(); + + if (!*baseSlotExpression.annotation().isPure) + { + // TODO: introduce and handle erc7201 as a builtin function + m_errorReporter.typeError( + 1139_error, + baseSlotExpression.location(), + "The base slot of the storage layout must be a compile-time constant expression." + ); + return; + } + + auto const* baseSlotExpressionType = type(baseSlotExpression); + auto const* rationalType = dynamic_cast(baseSlotExpressionType); + if (!rationalType) + { + m_errorReporter.typeError( + 6396_error, + baseSlotExpression.location(), + "The base slot of the storage layout must evaluate to a rational number." + ); + return; + } + + if (rationalType->isFractional()) + { + m_errorReporter.typeError( + 1763_error, + baseSlotExpression.location(), + "The base slot of the storage layout must evaluate to an integer." + ); + return; + } + solAssert(rationalType->value().denominator() == 1); + + bigint baseSlot = rationalType->value().numerator(); + if (!(0 <= baseSlot && baseSlot <= std::numeric_limits::max())) + { + m_errorReporter.typeError( + 6753_error, + baseSlotExpression.location(), + fmt::format( + "The base slot of the storage layout evaluates to {}, which is outside the range of type uint256.", + formatNumberReadable(baseSlot) + ) + ); + return; + } + + solAssert(baseSlotExpressionType->isImplicitlyConvertibleTo(*TypeProvider::uint256())); + storageLayoutSpecifier->annotation().baseSlot = u256(baseSlot); + + bigint size = contractStorageSizeUpperBound(_contract, VariableDeclaration::Location::Unspecified); + solAssert(size < bigint(1) << 256); + if (baseSlot + size >= bigint(1) << 256) + m_errorReporter.typeError( + 5015_error, + baseSlotExpression.location(), + "Contract extends past the end of storage when this base slot value is specified." + ); +} + +namespace +{ + +VariableDeclaration const* findLastStorageVariable(ContractDefinition const& _contract) +{ + for (ContractDefinition const* baseContract: ranges::actions::reverse(_contract.annotation().linearizedBaseContracts)) + for (VariableDeclaration const* stateVariable: ranges::actions::reverse(baseContract->stateVariables())) + if (stateVariable->referenceLocation() == VariableDeclaration::Location::Unspecified) + return stateVariable; + + return nullptr; +} + +} + +void PostTypeContractLevelChecker::warnStorageLayoutBaseNearStorageEnd(ContractDefinition const& _contract) +{ + // In case of most errors the warning is pointless. E.g. if we're already past storage end. + // If the errors were in the layout specifier, we may not even be able to get values to validate. + if (Error::containsErrors(m_errorReporter.errors())) + return; + + bigint storageSize = contractStorageSizeUpperBound(_contract, VariableDeclaration::Location::Unspecified); + u256 baseSlot = layoutBaseForInheritanceHierarchy(_contract, DataLocation::Storage); + solAssert(baseSlot + storageSize <= std::numeric_limits::max()); + + if ( + u256 slotsLeft = std::numeric_limits::max() - baseSlot - u256(storageSize); + slotsLeft <= u256(1) << 64 + ) + { + auto const& location = _contract.storageLayoutSpecifier() ? + _contract.storageLayoutSpecifier()->location() : + _contract.location(); + + VariableDeclaration const* lastStorageVariable = findLastStorageVariable(_contract); + + auto errorID = 3495_error; + std::string errorMsg = "This contract is very close to the end of storage. This limits its future upgradability."; + if (lastStorageVariable) + m_errorReporter.warning( + errorID, + location, + errorMsg, + SecondarySourceLocation{}.append( + fmt::format( + "There are {} storage slots between this state variable and the end of storage.", + formatNumberReadable(slotsLeft) + ), + lastStorageVariable->location() + ) + ); + else + m_errorReporter.warning(errorID, location, errorMsg); + } +} diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.h b/libsolidity/analysis/PostTypeContractLevelChecker.h index e12e37184687..ca7247c4671a 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.h +++ b/libsolidity/analysis/PostTypeContractLevelChecker.h @@ -50,6 +50,10 @@ class PostTypeContractLevelChecker /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings bool check(ContractDefinition const& _contract); + void checkStorageLayoutSpecifier(ContractDefinition const& _contract); + + void warnStorageLayoutBaseNearStorageEnd(ContractDefinition const& _contract); + langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 0a0e9370a657..5c8c53613482 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -86,6 +86,9 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.baseContracts(), *this); + if (StorageLayoutSpecifier const* layoutSpecifier = _contract.storageLayoutSpecifier()) + layoutSpecifier->accept(*this); + for (auto const& n: _contract.subNodes()) n->accept(*this); @@ -1324,7 +1327,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) solAssert(m_errorReporter.hasErrors(), "Should have errors!"); for (auto const& var: variables) if (var && !var->annotation().type) - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, "Type checker failed to determine types of all variables within the declaration."); } return false; @@ -1377,7 +1380,7 @@ bool TypeChecker::visit(Conditional const& _conditional) commonType = falseType; if (!trueType && !falseType) - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, "Both sides of the ternary expression have invalid types."); else if (trueType && falseType) { commonType = Type::commonType(trueType, falseType); @@ -1454,10 +1457,7 @@ void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const& bool TypeChecker::visit(Assignment const& _assignment) { - requireLValue( - _assignment.leftHandSide(), - _assignment.assignmentOperator() == Token::Assign - ); + requireLValue(_assignment.leftHandSide()); Type const* t = type(_assignment.leftHandSide()); _assignment.annotation().type = t; _assignment.annotation().isPure = false; @@ -1518,10 +1518,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) for (auto const& component: components) if (component) { - requireLValue( - *component, - _tuple.annotation().lValueOfOrdinaryAssignment - ); + requireLValue(*component); types.push_back(type(*component)); } else @@ -1614,7 +1611,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation) Token op = _operation.getOperator(); bool const modifying = (op == Token::Inc || op == Token::Dec || op == Token::Delete); if (modifying) - requireLValue(_operation.subExpression(), false); + requireLValue(_operation.subExpression()); else _operation.subExpression().accept(*this); Type const* operandType = type(_operation.subExpression()); @@ -2968,6 +2965,12 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions) _functionCallOptions.location(), "Function call option \"gas\" cannot be used with \"new\"." ); + else if (m_eofVersion.has_value()) + m_errorReporter.typeError( + 3765_error, + _functionCallOptions.location(), + "Function call option \"gas\" cannot be used when compiling to EOF." + ); else { expectType(*_functionCallOptions.options()[i], *TypeProvider::uint256()); @@ -4140,10 +4143,9 @@ bool TypeChecker::expectType(Expression const& _expression, Type const& _expecte return true; } -void TypeChecker::requireLValue(Expression const& _expression, bool _ordinaryAssignment) +void TypeChecker::requireLValue(Expression const& _expression) { _expression.annotation().willBeWrittenTo = true; - _expression.annotation().lValueOfOrdinaryAssignment = _ordinaryAssignment; _expression.accept(*this); if (*_expression.annotation().isLValue) diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index b3bd8b91fb09..e4bc12705314 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -47,8 +47,9 @@ class TypeChecker: private ASTConstVisitor { public: /// @param _errorReporter provides the error logging functionality. - TypeChecker(langutil::EVMVersion _evmVersion, langutil::ErrorReporter& _errorReporter): + TypeChecker(langutil::EVMVersion _evmVersion, std::optional _eofVersion, langutil::ErrorReporter& _errorReporter): m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), m_errorReporter(_errorReporter) {} @@ -174,7 +175,7 @@ class TypeChecker: private ASTConstVisitor /// convertible to @a _expectedType. bool expectType(Expression const& _expression, Type const& _expectedType); /// Runs type checks on @a _expression to infer its type and then checks that it is an LValue. - void requireLValue(Expression const& _expression, bool _ordinaryAssignment); + void requireLValue(Expression const& _expression); bool useABICoderV2() const; @@ -192,6 +193,7 @@ class TypeChecker: private ASTConstVisitor ContractDefinition const* m_currentContract = nullptr; langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 88cc1fb49822..1788f97f0018 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -18,8 +18,9 @@ #include #include -#include #include +#include +#include #include #include @@ -66,9 +67,9 @@ class AssemblyViewPureChecker void operator()(yul::FunctionCall const& _funCall) { if (yul::EVMDialect const* dialect = dynamic_cast(&m_dialect)) - if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) - if (fun->instruction) - checkInstruction(nativeLocationOf(_funCall), *fun->instruction); + if (yul::BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_funCall.functionName, *dialect)) + if (builtin->instruction) + checkInstruction(nativeLocationOf(_funCall), *builtin->instruction); for (auto const& arg: _funCall.arguments) std::visit(*this, arg); diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index a3aab07fba29..b59273b18d5d 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -130,18 +130,23 @@ SourceUnitAnnotation& SourceUnit::annotation() const std::set SourceUnit::referencedSourceUnits(bool _recurse, std::set _skipList) const { std::set sourceUnits; + referencedSourceUnits(sourceUnits, _recurse, _skipList); + return sourceUnits; +} + +void SourceUnit::referencedSourceUnits(std::set& _referencedSourceUnits, bool _recurse, std::set& _skipList) const +{ for (ImportDirective const* importDirective: filteredNodes(nodes())) { auto const& sourceUnit = importDirective->annotation().sourceUnit; - if (!_skipList.count(sourceUnit)) + auto [skipListIt, notOnSkipListYet] = _skipList.insert(sourceUnit); + if (notOnSkipListYet) { - _skipList.insert(sourceUnit); - sourceUnits.insert(sourceUnit); + _referencedSourceUnits.insert(sourceUnit); if (_recurse) - sourceUnits += sourceUnit->referencedSourceUnits(true, _skipList); + sourceUnit->referencedSourceUnits(_referencedSourceUnits, true, _skipList); } } - return sourceUnits; } ImportAnnotation& ImportDirective::annotation() const @@ -366,6 +371,22 @@ std::multimap const& ContractDefinition: }); } +StorageLayoutSpecifier::StorageLayoutSpecifier( + int64_t _id, + SourceLocation const& _location, + ASTPointer _baseSlotExpression +): + ASTNode(_id, _location), + m_baseSlotExpression(_baseSlotExpression) +{ + solAssert(m_baseSlotExpression); + solAssert(_location.contains(m_baseSlotExpression->location())); +} + +StorageLayoutSpecifierAnnotation& StorageLayoutSpecifier::annotation() const +{ + return initAnnotation(); +} TypeNameAnnotation& TypeName::annotation() const { diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index db5cd5786bb3..0ca4ffcf927c 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -49,7 +49,7 @@ namespace solidity::yul { // Forward-declaration to class AST; -struct Dialect; +class Dialect; } namespace solidity::frontend @@ -193,6 +193,12 @@ class SourceUnit: public ASTNode, public ScopeOpener bool experimentalSolidity() const { return m_experimentalSolidity; } private: + void referencedSourceUnits( + std::set& _referencedSourceUnits, + bool _recurse, + std::set& _skipList + ) const; + std::optional m_licenseString; std::vector> m_nodes; bool m_experimentalSolidity = false; @@ -503,14 +509,16 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub std::vector> _baseContracts, std::vector> _subNodes, ContractKind _contractKind = ContractKind::Contract, - bool _abstract = false + bool _abstract = false, + ASTPointer _storageLayoutSpecifier = nullptr ): Declaration(_id, _location, _name, std::move(_nameLocation)), StructurallyDocumented(_documentation), m_baseContracts(std::move(_baseContracts)), m_subNodes(std::move(_subNodes)), m_contractKind(_contractKind), - m_abstract(_abstract) + m_abstract(_abstract), + m_storageLayoutSpecifier(_storageLayoutSpecifier) {} void accept(ASTVisitor& _visitor) override; @@ -580,6 +588,9 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub bool abstract() const { return m_abstract; } + StorageLayoutSpecifier const* storageLayoutSpecifier() const { return m_storageLayoutSpecifier.get(); } + StorageLayoutSpecifier* storageLayoutSpecifier() { return m_storageLayoutSpecifier.get(); } + ContractDefinition const* superContract(ContractDefinition const& _mostDerivedContract) const; /// @returns the next constructor in the inheritance hierarchy. FunctionDefinition const* nextConstructor(ContractDefinition const& _mostDerivedContract) const; @@ -591,12 +602,32 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub std::vector> m_subNodes; ContractKind m_contractKind; bool m_abstract{false}; + ASTPointer m_storageLayoutSpecifier; util::LazyInit, FunctionTypePointer>>> m_interfaceFunctionList[2]; util::LazyInit> m_interfaceEvents; util::LazyInit> m_definedFunctionsByName; }; + +class StorageLayoutSpecifier : public ASTNode +{ +public: + StorageLayoutSpecifier( + int64_t _id, + SourceLocation const& _location, + ASTPointer _baseSlotExpression + ); + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; + + Expression const& baseSlotExpression() const { solAssert(m_baseSlotExpression); return *m_baseSlotExpression; } + StorageLayoutSpecifierAnnotation& annotation() const override; + +private: + ASTPointer m_baseSlotExpression; +}; + /** * A sequence of identifiers separated by dots used outside the expression context. Inside the expression context, this is a sequence of Identifier and MemberAccess. */ @@ -2048,7 +2079,7 @@ class Assignment: public Expression ): Expression(_id, _location), m_leftHandSide(std::move(_leftHandSide)), - m_assigmentOperator(_assignmentOperator), + m_assignmentOperator(_assignmentOperator), m_rightHandSide(std::move(_rightHandSide)) { solAssert(TokenTraits::isAssignmentOp(_assignmentOperator), ""); @@ -2057,12 +2088,12 @@ class Assignment: public Expression void accept(ASTConstVisitor& _visitor) const override; Expression const& leftHandSide() const { return *m_leftHandSide; } - Token assignmentOperator() const { return m_assigmentOperator; } + Token assignmentOperator() const { return m_assignmentOperator; } Expression const& rightHandSide() const { return *m_rightHandSide; } private: ASTPointer m_leftHandSide; - Token m_assigmentOperator; + Token m_assignmentOperator; ASTPointer m_rightHandSide; }; diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 81b3b8374697..7adfc7a4aa2e 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -39,7 +40,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; struct Identifier; -struct Dialect; +class Dialect; } namespace solidity::frontend @@ -173,6 +174,12 @@ struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocu std::map internalFunctionIDs; }; +struct StorageLayoutSpecifierAnnotation: ASTAnnotation +{ + // The evaluated value of the expression specifying the contract storage layout base + util::SetOnce baseSlot; +}; + struct CallableDeclarationAnnotation: DeclarationAnnotation { /// The set of functions/modifiers/events this callable overrides. @@ -279,10 +286,6 @@ struct ExpressionAnnotation: ASTAnnotation util::SetOnce isLValue; /// Whether the expression is used in a context where the LValue is actually required. bool willBeWrittenTo = false; - /// Whether the expression is an lvalue that is only assigned. - /// Would be false for --, ++, delete, +=, -=, .... - /// Only relevant if isLvalue == true - bool lValueOfOrdinaryAssignment = false; /// Types and - if given - names of arguments if the expr. is a function /// that is called, used for overload resolution diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h index b8a3a4ae0057..d0fe7d97afa1 100644 --- a/libsolidity/ast/ASTForward.h +++ b/libsolidity/ast/ASTForward.h @@ -98,6 +98,7 @@ class Identifier; class ElementaryTypeNameExpression; class Literal; class StructuredDocumentation; +class StorageLayoutSpecifier; /// Experimental Solidity nodes /// @{ diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 7183c64a3f18..42627b5f7f7c 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -210,6 +210,13 @@ Json ASTJsonExporter::toJson(ASTNode const& _node) return util::removeNullMembers(std::move(m_currentValue)); } +Json ASTJsonExporter::toJson(ASTNode const* _node) +{ + if (!_node) + return Json(); + return toJson(*_node); +} + bool ASTJsonExporter::visit(SourceUnit const& _node) { std::vector> attributes = { @@ -279,6 +286,14 @@ bool ASTJsonExporter::visit(ImportDirective const& _node) return false; } +bool ASTJsonExporter::visit(StorageLayoutSpecifier const& _node) +{ + setJsonNode(_node, "StorageLayoutSpecifier", { + {"baseSlotExpression", toJson(_node.baseSlotExpression())} + }); + return false; +} + bool ASTJsonExporter::visit(ContractDefinition const& _node) { std::vector> attributes = { @@ -293,7 +308,8 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node) std::make_pair("usedEvents", getContainerIds(_node.interfaceEvents(false))), std::make_pair("usedErrors", getContainerIds(_node.interfaceErrors(false))), std::make_pair("nodes", toJson(_node.subNodes())), - std::make_pair("scope", idOrNull(_node.scope())) + std::make_pair("scope", idOrNull(_node.scope())), + std::make_pair("storageLayout", toJson(_node.storageLayoutSpecifier())) }; addIfSet(attributes, "canonicalName", _node.annotation().canonicalName); @@ -667,7 +683,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) auto const& evmDialect = dynamic_cast(_node.dialect()); std::vector> attributes = { - std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations().root()))), + std::make_pair("AST", Json(yul::AsmJsonConverter(evmDialect, sourceIndexFromLocation(_node.location()))(_node.operations().root()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), std::make_pair("evmVersion", evmDialect.evmVersion().name()) }; diff --git a/libsolidity/ast/ASTJsonExporter.h b/libsolidity/ast/ASTJsonExporter.h index c7933120a974..3174dc1865ea 100644 --- a/libsolidity/ast/ASTJsonExporter.h +++ b/libsolidity/ast/ASTJsonExporter.h @@ -60,6 +60,7 @@ class ASTJsonExporter: public ASTConstVisitor /// Output the json representation of the AST to _stream. void print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format); Json toJson(ASTNode const& _node); + Json toJson(ASTNode const* _node); template Json toJson(std::vector> const& _nodes) { @@ -126,6 +127,7 @@ class ASTJsonExporter: public ASTConstVisitor bool visit(ElementaryTypeNameExpression const& _node) override; bool visit(Literal const& _node) override; bool visit(StructuredDocumentation const& _node) override; + bool visit(StorageLayoutSpecifier const& _node) override; void endVisit(EventDefinition const&) override; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 777d1d13163e..a2617fcd08da 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -37,6 +37,8 @@ #include #include +#include + namespace solidity::frontend { @@ -255,6 +257,8 @@ ASTPointer ASTJsonImporter::convertJsonToASTNode(Json const& _json) return createLiteral(_json); if (nodeType == "StructuredDocumentation") return createDocumentation(_json); + if (nodeType == "StorageLayoutSpecifier") + return createStorageLayoutSpecifier(_json); else astAssert(false, "Unknown type of ASTNode: " + nodeType); @@ -348,7 +352,17 @@ ASTPointer ASTJsonImporter::createContractDefinition(Json co baseContracts, subNodes, contractKind(_node), - memberAsBool(_node, "abstract") + memberAsBool(_node, "abstract"), + nullOrCast(member(_node, "storageLayout")) + ); +} + +ASTPointer ASTJsonImporter::createStorageLayoutSpecifier(Json const& _node) +{ + astAssert(_node.contains("baseSlotExpression"), "Expected field \"baseSlotExpression\" is missing."); + return createASTNode( + _node, + convertJsonToASTNode(_node["baseSlotExpression"]) ); } @@ -742,7 +756,9 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _no flags->emplace_back(std::make_shared(flag.get())); } } - std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames).createAST(member(_node, "AST"))); + std::shared_ptr operations = std::make_shared( + yul::AsmJsonImporter(dialect, m_sourceNames).createAST(member(_node, "AST")) + ); return createASTNode( _node, nullOrASTString(_node, "documentation"), diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index e4a7c2da3fe9..7c5dd5be9f99 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -131,10 +131,11 @@ class ASTJsonImporter ASTPointer createElementaryTypeNameExpression(Json const& _node); ASTPointer createLiteral(Json const& _node); ASTPointer createDocumentation(Json const& _node); + ASTPointer createStorageLayoutSpecifier(Json const& _node); ///@} // =============== general helper functions =================== - /// @returns the member of a given JSON object, throws if member does not exist + /// @returns the member of a given JSON object or null if member does not exist Json member(Json const& _node, std::string const& _name); /// @returns the appropriate TokenObject used in parsed Strings (pragma directive or operator) Token scanSingleToken(Json const& _node); diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index 7d434f896d12..5ae3366194c6 100644 --- a/libsolidity/ast/ASTUtils.cpp +++ b/libsolidity/ast/ASTUtils.cpp @@ -107,4 +107,34 @@ Type const* type(VariableDeclaration const& _variable) return _variable.annotation().type; } +bigint contractStorageSizeUpperBound(ContractDefinition const& _contract, VariableDeclaration::Location _location) +{ + solAssert(_location == VariableDeclaration::Location::Unspecified || _location == VariableDeclaration::Location::Transient); + + bigint size = 0; + for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) + for (VariableDeclaration const* variable: contract->stateVariables()) + if ( + !(variable->isConstant() || variable->immutable()) && + variable->referenceLocation() == _location + ) + size += variable->annotation().type->storageSizeUpperBound(); + + return size; +} + +u256 layoutBaseForInheritanceHierarchy(ContractDefinition const& _topLevelContract, DataLocation _location) +{ + if (_location != DataLocation::Storage) + { + solAssert(_location == DataLocation::Transient); + return 0; + } + + if (auto const* storageLayoutSpecifier = _topLevelContract.storageLayoutSpecifier()) + return *storageLayoutSpecifier->annotation().baseSlot; + + return 0; +} + } diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h index b31bd20d5845..d29bda35ff8c 100644 --- a/libsolidity/ast/ASTUtils.h +++ b/libsolidity/ast/ASTUtils.h @@ -18,6 +18,8 @@ #pragma once +#include + namespace solidity::frontend { @@ -26,6 +28,7 @@ class Declaration; class Expression; class SourceUnit; class VariableDeclaration; +class ContractDefinition; /// Find the topmost referenced constant variable declaration when the given variable /// declaration value is an identifier. Works only for constant variable declarations. @@ -48,4 +51,14 @@ Type const* type(Expression const& _expression); /// (this can happen for variables with non-explicit types before their types are resolved) Type const* type(VariableDeclaration const& _variable); +/// @returns The number of slots occupied by all state variables in contract's inheritance hierarchy, +/// located in @a _location (either storage or transient storage). +bigint contractStorageSizeUpperBound(ContractDefinition const& _contract, VariableDeclaration::Location _location); + +/// @returns The base slot of the inheritance hierarchy rooted at the specified contract. +/// The value comes from the inheritance specifier of the contract and defaults to zero. +/// The value is zero also when the contract is an interface or a library (and cannot have storage). +/// Assumes analysis was successful. +u256 layoutBaseForInheritanceHierarchy(ContractDefinition const& _topLevelContract, DataLocation _location); + } diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h index f985a449019a..010e99ec3d72 100644 --- a/libsolidity/ast/ASTVisitor.h +++ b/libsolidity/ast/ASTVisitor.h @@ -109,6 +109,7 @@ class ASTVisitor virtual bool visit(ElementaryTypeNameExpression& _node) { return visitNode(_node); } virtual bool visit(Literal& _node) { return visitNode(_node); } virtual bool visit(StructuredDocumentation& _node) { return visitNode(_node); } + virtual bool visit(StorageLayoutSpecifier& _node) { return visitNode(_node); } /// Experimental Solidity nodes /// @{ virtual bool visit(TypeClassDefinition& _node) { return visitNode(_node); } @@ -174,6 +175,7 @@ class ASTVisitor virtual void endVisit(ElementaryTypeNameExpression& _node) { endVisitNode(_node); } virtual void endVisit(Literal& _node) { endVisitNode(_node); } virtual void endVisit(StructuredDocumentation& _node) { endVisitNode(_node); } + virtual void endVisit(StorageLayoutSpecifier& _node) { endVisitNode(_node); } /// Experimental Solidity nodes /// @{ virtual void endVisit(TypeClassDefinition& _node) { endVisitNode(_node); } @@ -261,6 +263,7 @@ class ASTConstVisitor virtual bool visit(ElementaryTypeNameExpression const& _node) { return visitNode(_node); } virtual bool visit(Literal const& _node) { return visitNode(_node); } virtual bool visit(StructuredDocumentation const& _node) { return visitNode(_node); } + virtual bool visit(StorageLayoutSpecifier const& _node) { return visitNode(_node); } /// Experimental Solidity nodes /// @{ virtual bool visit(TypeClassDefinition const& _node) { return visitNode(_node); } @@ -326,6 +329,7 @@ class ASTConstVisitor virtual void endVisit(ElementaryTypeNameExpression const& _node) { endVisitNode(_node); } virtual void endVisit(Literal const& _node) { endVisitNode(_node); } virtual void endVisit(StructuredDocumentation const& _node) { endVisitNode(_node); } + virtual void endVisit(StorageLayoutSpecifier const& _node) { endVisitNode(_node); } /// Experimental Solidity nodes /// @{ virtual void endVisit(TypeClassDefinition const& _node) { endVisitNode(_node); } diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h index 55ebe2a78c61..1cd771f9d4a8 100644 --- a/libsolidity/ast/AST_accept.h +++ b/libsolidity/ast/AST_accept.h @@ -93,6 +93,8 @@ void ContractDefinition::accept(ASTVisitor& _visitor) if (m_documentation) m_documentation->accept(_visitor); listAccept(m_baseContracts, _visitor); + if (m_storageLayoutSpecifier) + m_storageLayoutSpecifier->accept(_visitor); listAccept(m_subNodes, _visitor); } _visitor.endVisit(*this); @@ -105,6 +107,8 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const if (m_documentation) m_documentation->accept(_visitor); listAccept(m_baseContracts, _visitor); + if (m_storageLayoutSpecifier) + m_storageLayoutSpecifier->accept(_visitor); listAccept(m_subNodes, _visitor); } _visitor.endVisit(*this); @@ -1160,6 +1164,22 @@ void ForAllQuantifier::accept(ASTConstVisitor& _visitor) const } _visitor.endVisit(*this); } + +void StorageLayoutSpecifier::accept(ASTVisitor& _visitor) +{ + if (_visitor.visit(*this)) + m_baseSlotExpression->accept(_visitor); + + _visitor.endVisit(*this); +} + +void StorageLayoutSpecifier::accept(ASTConstVisitor& _visitor) const +{ + if (_visitor.visit(*this)) + m_baseSlotExpression->accept(_visitor); + + _visitor.endVisit(*this); +} /// @} } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index ed58820095e3..46086f8f5d62 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -138,23 +139,23 @@ void Type::clearCache() const m_stackSize.reset(); } -void StorageOffsets::computeOffsets(TypePointers const& _types) +void StorageOffsets::computeOffsets(TypePointers const& _types, u256 _baseSlot) { - bigint slotOffset = 0; + bigint slotOffset = bigint(_baseSlot); unsigned byteOffset = 0; std::map> offsets; for (size_t i = 0; i < _types.size(); ++i) { Type const* type = _types[i]; - if (!type->canBeStored()) - continue; + solAssert(type->canBeStored()); + solAssert(type->storageBytes() <= 32); if (byteOffset + type->storageBytes() > 32) { // would overflow, go to next slot ++slotOffset; byteOffset = 0; } - solAssert(slotOffset < bigint(1) << 256 ,"Object too large for storage."); + solAssert(slotOffset < bigint(1) << 256, "Object extends past the end of storage."); offsets[i] = std::make_pair(u256(slotOffset), byteOffset); solAssert(type->storageSize() >= 1, "Invalid storage size."); if (type->storageSize() == 1 && byteOffset + type->storageBytes() <= 32) @@ -167,8 +168,9 @@ void StorageOffsets::computeOffsets(TypePointers const& _types) } if (byteOffset > 0) ++slotOffset; - solAssert(slotOffset < bigint(1) << 256, "Object too large for storage."); - m_storageSize = u256(slotOffset); + + solAssert(slotOffset < bigint(1) << 256, "Object extends past the end of storage."); + m_storageSize = u256(slotOffset - _baseSlot); swap(m_offsets, offsets); } @@ -762,8 +764,12 @@ bool IntegerType::operator==(Type const& _other) const { if (_other.category() != category()) return false; - IntegerType const& other = dynamic_cast(_other); - return other.m_bits == m_bits && other.m_modifier == m_modifier; + return *this == dynamic_cast(_other); +} + +bool IntegerType::operator==(IntegerType const& _other) const +{ + return _other.m_bits == m_bits && _other.m_modifier == m_modifier; } std::string IntegerType::toString(bool) const @@ -1808,17 +1814,21 @@ bool ArrayType::operator==(Type const& _other) const { if (_other.category() != category()) return false; - ArrayType const& other = dynamic_cast(_other); + return *this == dynamic_cast(_other); +} + +bool ArrayType::operator==(ArrayType const& _other) const +{ if ( - !equals(other) || - other.isByteArray() != isByteArray() || - other.isString() != isString() || - other.isDynamicallySized() != isDynamicallySized() + !equals(_other) || + _other.isByteArray() != isByteArray() || + _other.isString() != isString() || + _other.isDynamicallySized() != isDynamicallySized() ) return false; - if (*other.baseType() != *baseType()) + if (*_other.baseType() != *baseType()) return false; - return isDynamicallySized() || length() == other.length(); + return isDynamicallySized() || length() == _other.length(); } BoolResult ArrayType::validForLocation(DataLocation _loc) const @@ -2249,7 +2259,7 @@ FunctionType const* ContractType::newExpressionType() const return m_constructorType; } -std::vector> ContractType::stateVariables(DataLocation _location) const +std::vector> ContractType::linearizedStateVariables(DataLocation _location) const { VariableDeclaration::Location location; switch (_location) @@ -2269,11 +2279,12 @@ std::vector> ContractType for (VariableDeclaration const* variable: contract->stateVariables()) if (!(variable->isConstant() || variable->immutable()) && variable->referenceLocation() == location) variables.push_back(variable); + TypePointers types; for (auto variable: variables) types.push_back(variable->annotation().type); StorageOffsets offsets; - offsets.computeOffsets(types); + offsets.computeOffsets(types, layoutBaseForInheritanceHierarchy(m_contract, _location)); std::vector> variablesAndOffsets; for (size_t index = 0; index < variables.size(); ++index) @@ -2813,7 +2824,12 @@ bool UserDefinedValueType::operator==(Type const& _other) const if (_other.category() != category()) return false; UserDefinedValueType const& other = dynamic_cast(_other); - return other.definition() == definition(); + return *this == other; +} + +bool UserDefinedValueType::operator==(UserDefinedValueType const& _other) const +{ + return _other.definition() == definition(); } std::string UserDefinedValueType::toString(bool /* _withoutDataLocation */) const @@ -4240,6 +4256,11 @@ bool ModifierType::operator==(Type const& _other) const { if (_other.category() != category()) return false; + return *this == dynamic_cast(_other); +} + +bool ModifierType::operator==(ModifierType const& _other) const +{ ModifierType const& other = dynamic_cast(_other); if (m_parameterTypes.size() != other.m_parameterTypes.size()) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index e23629e21554..722fcd556d96 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -81,7 +81,10 @@ class StorageOffsets public: /// Resets the StorageOffsets objects and determines the position in storage for each /// of the elements of @a _types. - void computeOffsets(TypePointers const& _types); + /// Calculated positions are absolute and start at @a _baseSlot. + /// Assumes that @a _types is small enough to fit in the area between @a _baseSlot and the end of storage + /// (the caller is responsible for validating that). + void computeOffsets(TypePointers const& _types, u256 _baseSlot = 0); /// @returns the offset of the given member, might be null if the member is not part of storage. std::pair const* offset(size_t _index) const; /// @returns the total number of slots occupied by all members. @@ -496,6 +499,7 @@ class IntegerType: public Type TypeResult unaryOperatorResult(Token _operator) const override; TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override; + bool operator==(IntegerType const& _other) const; bool operator==(Type const& _other) const override; unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_bits / 8; } @@ -856,6 +860,7 @@ class ArrayType: public ReferenceType BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override; BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override; std::string richIdentifier() const override; + bool operator==(ArrayType const& _other) const; bool operator==(Type const& _other) const override; unsigned calldataEncodedSize(bool) const override; unsigned calldataEncodedTailSize() const override; @@ -1002,9 +1007,12 @@ class ContractType: public Type /// Returns the function type of the constructor modified to return an object of the contract's type. FunctionType const* newExpressionType() const; - /// @returns a list of all state variables (including inherited) of the contract and their - /// offsets in storage/transient storage. - std::vector> stateVariables(DataLocation _location) const; + /// @returns a list of all state variables in the linearized inheritance hierarchy and + /// their respective slots and offsets in storage/transient storage. + /// It should only be called for the top level contract in order to get the absolute slots and + /// offsets values in storage/transient storage. Otherwise, the slots of the state variables + /// will be relative to the contract position in the hierarchy. + std::vector> linearizedStateVariables(DataLocation _location) const; /// @returns a list of all immutable variables (including inherited) of the contract. std::vector immutableVariables() const; protected: @@ -1150,6 +1158,7 @@ class UserDefinedValueType: public Type Declaration const* typeDefinition() const override; std::string richIdentifier() const override; + bool operator==(UserDefinedValueType const& _other) const; bool operator==(Type const& _other) const override; unsigned calldataEncodedSize(bool _padded) const override { return underlyingType().calldataEncodedSize(_padded); } @@ -1667,6 +1676,7 @@ class ModifierType: public Type bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } std::string richIdentifier() const override; bool operator==(Type const& _other) const override; + bool operator==(ModifierType const& _other) const; std::string toString(bool _withoutDataLocation) const override; protected: std::vector> makeStackItems() const override { return {}; } diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index b7f7f8ae5735..d357447ac3e8 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -56,13 +56,14 @@ class ABIFunctions public: explicit ABIFunctions( langutil::EVMVersion _evmVersion, + std::optional _eofVersion, RevertStrings _revertStrings, MultiUseYulFunctionCollector& _functionCollector ): m_evmVersion(_evmVersion), m_revertStrings(_revertStrings), m_functionCollector(_functionCollector), - m_utils(_evmVersion, m_revertStrings, m_functionCollector) + m_utils(_evmVersion, _eofVersion, m_revertStrings, m_functionCollector) {} /// @returns name of an assembly function to ABI-encode values of @a _givenTypes diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 5dd94aebc4f0..455cfe0842ed 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -710,7 +710,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const CompilerUtils(_context).computeHashStatic(); _context << Instruction::SSTORE; // stack: ref new_length current_length - // Store new length: Compule 2*length + 1 and store it. + // Store new length: Compute 2*length + 1 and store it. _context << Instruction::DUP2 << Instruction::DUP1 << Instruction::ADD; _context << u256(1) << Instruction::ADD; // stack: ref new_length current_length 2*new_length+1 diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 1267c1a2d92c..bc801ff5782b 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -37,10 +37,15 @@ namespace solidity::frontend class Compiler { public: - Compiler(langutil::EVMVersion _evmVersion, RevertStrings _revertStrings, OptimiserSettings _optimiserSettings): + Compiler( + langutil::EVMVersion _evmVersion, + std::optional _eofVersion, + RevertStrings _revertStrings, + OptimiserSettings _optimiserSettings + ): m_optimiserSettings(std::move(_optimiserSettings)), - m_runtimeContext(_evmVersion, _revertStrings), - m_context(_evmVersion, _revertStrings, &m_runtimeContext) + m_runtimeContext(_evmVersion, _eofVersion, _revertStrings), + m_context(_evmVersion, _eofVersion, _revertStrings, &m_runtimeContext) { } /// Compiles a contract. diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 4a0f636dc974..4d53b9c234b9 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -444,7 +444,7 @@ void CompilerContext::appendInlineAssembly( yul::Parser(errorReporter, dialect, std::move(locationOverride)) .parse(charStream); #ifdef SOL_OUTPUT_ASM - cout << yul::AsmPrinter(&dialect)(*parserResult) << endl; + std::cout << yul::AsmPrinter::format(*parserResult) << std::endl; #endif auto reportError = [&](std::string const& _context) @@ -485,25 +485,24 @@ void CompilerContext::appendInlineAssembly( obj.setCode(parserResult, std::make_shared(analysisInfo)); solAssert(!dialect.providesObjectAccess()); - optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers); + optimizeYul(obj, _optimiserSettings, externallyUsedIdentifiers); if (_system) { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter()(obj.code()->root()); - std::string code = yul::AsmPrinter{}(obj.code()->root()); + m_generatedYulUtilityCode = yul::AsmPrinter::format(*obj.code()); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.setCode(yul::Parser(errorReporter, dialect).parse(charStream)); - obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj)); + obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(obj)); } analysisInfo = std::move(*obj.analysisInfo); toBeAssembledAST = obj.code(); #ifdef SOL_OUTPUT_ASM - cout << "After optimizer:" << endl; - cout << yul::AsmPrinter(&dialect)(*parserResult) << endl; + std::cout << "After optimizer:" << std::endl; + std::cout << yul::AsmPrinter::format(*parserResult) << std::endl; #endif } else if (_system) @@ -533,16 +532,18 @@ void CompilerContext::appendInlineAssembly( } -void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) +void CompilerContext::optimizeYul(yul::Object& _object, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) { + yulAssert(_object.dialect()); + auto const* evmDialect = dynamic_cast(_object.dialect()); + yulAssert(evmDialect); #ifdef SOL_OUTPUT_ASM - cout << yul::AsmPrinter(*dialect)(*_object.code) << endl; + std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl; #endif bool const isCreation = runtimeContext() != nullptr; - yul::GasMeter meter(_dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); + yul::GasMeter meter(*evmDialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); yul::OptimiserSuite::run( - _dialect, &meter, _object, _optimiserSettings.optimizeStackAllocation, @@ -553,8 +554,8 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _ ); #ifdef SOL_OUTPUT_ASM - cout << "After optimizer:" << endl; - cout << yul::AsmPrinter(*dialect)(*object.code) << endl; + std::cout << "After optimizer:" << std::endl; + std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl; #endif } diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 3469ee7d278a..e8c4e9bc77f7 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -62,6 +62,7 @@ class CompilerContext public: explicit CompilerContext( langutil::EVMVersion _evmVersion, + std::optional _eofVersion, RevertStrings _revertStrings, CompilerContext* _runtimeContext = nullptr ): @@ -70,8 +71,8 @@ class CompilerContext m_revertStrings(_revertStrings), m_reservedMemory{0}, m_runtimeContext(_runtimeContext), - m_abiFunctions(m_evmVersion, m_revertStrings, m_yulFunctionCollector), - m_yulUtilFunctions(m_evmVersion, m_revertStrings, m_yulFunctionCollector) + m_abiFunctions(m_evmVersion, _eofVersion, m_revertStrings, m_yulFunctionCollector), + m_yulUtilFunctions(m_evmVersion, _eofVersion, m_revertStrings, m_yulFunctionCollector) { if (m_runtimeContext) m_runtimeSub = size_t(m_asm->newSub(m_runtimeContext->m_asm).data()); @@ -277,13 +278,13 @@ class CompilerContext /// Otherwise returns "revert(0, 0)". std::string revertReasonIfDebug(std::string const& _message = ""); - void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); + void optimizeYul(yul::Object& _object, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); /// Appends arbitrary data to the end of the bytecode. void appendToAuxiliaryData(bytes const& _data) { m_asm->appendToAuxiliaryData(_data); } /// Run optimisation step. - void optimise(OptimiserSettings const& _settings) { m_asm->optimise(evmasm::Assembly::OptimiserSettings::translateSettings(_settings, m_evmVersion)); } + void optimise(OptimiserSettings const& _settings) { m_asm->optimise(evmasm::Assembly::OptimiserSettings::translateSettings(_settings)); } /// @returns the runtime context if in creation mode and runtime context is set, nullptr otherwise. CompilerContext* runtimeContext() const { return m_runtimeContext; } @@ -366,7 +367,7 @@ class CompilerContext /// modifier is applied twice, the position of the variable needs to be restored /// after the nested modifier is left. std::map> m_localVariables; - /// The contract currently being compiled. Virtual function lookup starts from this contarct. + /// The contract currently being compiled. Virtual function lookup starts from this contract. ContractDefinition const* m_mostDerivedContract = nullptr; /// Whether to use checked arithmetic. Arithmetic m_arithmetic = Arithmetic::Checked; diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 8ff27f4ca574..4aef99aaae7a 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -577,7 +577,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete void ContractCompiler::registerStateVariables(ContractDefinition const& _contract) { for (auto const location: {DataLocation::Storage, DataLocation::Transient}) - for (auto const& var: ContractType(_contract).stateVariables(location)) + for (auto const& var: ContractType(_contract).linearizedStateVariables(location)) m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); } @@ -938,7 +938,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) // Only used in the scope below, but required to live outside to keep the // std::shared_ptr's alive - yul::Object object = {}; + yul::Object object; // The optimiser cannot handle external references if ( @@ -950,10 +950,10 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) solAssert(dialect, ""); // Create a modifiable copy of the code and analysis - object.setCode(std::make_shared(yul::ASTCopier().translate(code->root()))); - object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); + object.setCode(std::make_shared(_inlineAssembly.dialect(), yul::ASTCopier().translate(code->root()))); + object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(object)); - m_context.optimizeYul(object, *dialect, m_optimiserSettings); + m_context.optimizeYul(object, m_optimiserSettings); code = object.code().get(); analysisInfo = object.analysisInfo.get(); diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index ec6b04f6a5cb..abb2fdd100aa 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -285,7 +285,7 @@ std::string YulUtilFunctions::revertWithError( errorArgumentTypes.push_back(arg->annotation().type); } templ("argumentVars", joinHumanReadablePrefixed(errorArgumentVars)); - templ("encode", ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector).tupleEncoder(errorArgumentTypes, _parameterTypes)); + templ("encode", ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector).tupleEncoder(errorArgumentTypes, _parameterTypes)); return templ.render(); } @@ -2592,7 +2592,7 @@ std::string YulUtilFunctions::copyArrayFromStorageToMemoryFunction(ArrayType con if (_from.baseType()->isValueType()) { solAssert(*_from.baseType() == *_to.baseType(), ""); - ABIFunctions abi(m_evmVersion, m_revertStrings, m_functionCollector); + ABIFunctions abi(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector); return Whiskers(R"( function (slot) -> memPtr { memPtr := () @@ -2697,7 +2697,7 @@ std::string YulUtilFunctions::bytesOrStringConcatFunction( templ("finalizeAllocation", finalizeAllocationFunction()); templ( "encodePacked", - ABIFunctions{m_evmVersion, m_revertStrings, m_functionCollector}.tupleEncoderPacked( + ABIFunctions{m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector}.tupleEncoderPacked( _argumentTypes, targetTypes ) @@ -3578,7 +3578,7 @@ std::string YulUtilFunctions::conversionFunction(Type const& _from, Type const& )") ( "abiDecode", - ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector).abiDecodingFunctionStruct( + ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector).abiDecodingFunctionStruct( toStructType, false ) @@ -3907,6 +3907,7 @@ std::string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, Ar _from.dataStoredIn(DataLocation::CallData) ? ABIFunctions( m_evmVersion, + m_eofVersion, m_revertStrings, m_functionCollector ).abiDecodingFunctionArrayAvailableLength(_to, false) : @@ -4109,7 +4110,10 @@ std::string YulUtilFunctions::packedHashFunction( templ("variables", suffixedVariableNameList("var_", 1, 1 + sizeOnStack)); templ("comma", sizeOnStack > 0 ? "," : ""); templ("allocateUnbounded", allocateUnboundedFunction()); - templ("packedEncode", ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector).tupleEncoderPacked(_givenTypes, _targetTypes)); + templ( + "packedEncode", + ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector).tupleEncoderPacked(_givenTypes, _targetTypes) + ); return templ.render(); }); } @@ -4730,15 +4734,21 @@ std::string YulUtilFunctions::copyConstructorArgumentsToMemoryFunction( return m_functionCollector.createFunction(functionName, [&]() { std::string returnParams = suffixedVariableNameList("ret_param_",0, CompilerUtils::sizeOnStack(_contract.constructor()->parameters())); - ABIFunctions abiFunctions(m_evmVersion, m_revertStrings, m_functionCollector); + ABIFunctions abiFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector); return util::Whiskers(R"( function () -> { - let programSize := datasize("") - let argSize := sub(codesize(), programSize) - - let memoryDataOffset := (argSize) - codecopy(memoryDataOffset, programSize, argSize) + + let argSize := calldatasize() + let memoryDataOffset := (argSize) + calldatacopy(memoryDataOffset, 0, argSize) + + let programSize := datasize("") + let argSize := sub(codesize(), programSize) + + let memoryDataOffset := (argSize) + codecopy(memoryDataOffset, programSize, argSize) + := (memoryDataOffset, add(memoryDataOffset, argSize)) } @@ -4748,6 +4758,7 @@ std::string YulUtilFunctions::copyConstructorArgumentsToMemoryFunction( ("object", _creationObjectName) ("allocate", allocationFunction()) ("abiDecode", abiFunctions.tupleDecoder(FunctionType(*_contract.constructor()).parameterTypes(), true)) + ("eof", m_eofVersion.has_value()) .render(); }); } diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 6c06cdcc94e6..5ea99d603083 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -52,10 +52,12 @@ class YulUtilFunctions public: explicit YulUtilFunctions( langutil::EVMVersion _evmVersion, + std::optional _eofVersion, RevertStrings _revertStrings, MultiUseYulFunctionCollector& _functionCollector ): m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), m_revertStrings(_revertStrings), m_functionCollector(_functionCollector) {} @@ -640,6 +642,7 @@ class YulUtilFunctions std::string longByteArrayStorageIndexAccessNoCheckFunction(); langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; RevertStrings m_revertStrings; MultiUseYulFunctionCollector& m_functionCollector; }; diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index e087dc69a575..f33461b632a7 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -87,6 +87,7 @@ void IRGenerationContext::resetLocalVariables() void IRGenerationContext::registerImmutableVariable(VariableDeclaration const& _variable) { + solAssert(m_executionContext != ExecutionContext::Deployed); solAssert(_variable.immutable(), "Attempted to register a non-immutable variable as immutable."); solUnimplementedAssert( _variable.annotation().type->isValueType(), @@ -107,10 +108,64 @@ size_t IRGenerationContext::immutableMemoryOffset(VariableDeclaration const& _va return m_immutableVariables.at(&_variable); } +size_t IRGenerationContext::immutableMemoryOffsetRelative(VariableDeclaration const& _variable) const +{ + auto const absoluteOffset = immutableMemoryOffset(_variable); + solAssert(absoluteOffset >= CompilerUtils::generalPurposeMemoryStart); + return absoluteOffset - CompilerUtils::generalPurposeMemoryStart; +} + +size_t IRGenerationContext::reservedMemorySize() const +{ + solAssert(m_reservedMemory.has_value()); + return *m_reservedMemory; +} + +void IRGenerationContext::registerLibraryAddressImmutable() +{ + solAssert(m_executionContext != ExecutionContext::Deployed); + solAssert(m_reservedMemory.has_value(), "Reserved memory has already been reset."); + solAssert(!m_libraryAddressImmutableOffset.has_value()); + m_libraryAddressImmutableOffset = CompilerUtils::generalPurposeMemoryStart + *m_reservedMemory; + *m_reservedMemory += 32; +} + +size_t IRGenerationContext::libraryAddressImmutableOffset() const +{ + solAssert(m_libraryAddressImmutableOffset.has_value()); + return *m_libraryAddressImmutableOffset; +} + +size_t IRGenerationContext::libraryAddressImmutableOffsetRelative() const +{ + solAssert(m_libraryAddressImmutableOffset.has_value()); + solAssert(m_libraryAddressImmutableOffset >= CompilerUtils::generalPurposeMemoryStart); + return *m_libraryAddressImmutableOffset - CompilerUtils::generalPurposeMemoryStart; +} + size_t IRGenerationContext::reservedMemory() { solAssert(m_reservedMemory.has_value(), "Reserved memory was used before."); size_t reservedMemory = *m_reservedMemory; + + // We assume reserved memory contains only immutable variables. + // This memory is used i.e. by RETURNCONTRACT to create new EOF container with aux data. + size_t immutableVariablesSize = 0; + for (auto const* var: keys(m_immutableVariables)) + { + solUnimplementedAssert(var->type()->isValueType()); + solUnimplementedAssert(var->type()->sizeOnStack() == 1); + immutableVariablesSize += var->type()->sizeOnStack() * 32; + } + + // In Creation context check that only immutable variables or library address are stored in the reserved memory. + // In Deployed context (for EOF) m_immutableVariables contains offsets in EOF data section. + solAssert( + (m_executionContext == ExecutionContext::Creation && + reservedMemory == immutableVariablesSize + (m_libraryAddressImmutableOffset.has_value() ? 32 : 0)) || + (m_executionContext == ExecutionContext::Deployed && reservedMemory == 0) + ); + m_reservedMemory = std::nullopt; return reservedMemory; } @@ -169,10 +224,10 @@ void IRGenerationContext::internalFunctionCalledThroughDispatch(YulArity const& YulUtilFunctions IRGenerationContext::utils() { - return YulUtilFunctions(m_evmVersion, m_revertStrings, m_functions); + return YulUtilFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functions); } ABIFunctions IRGenerationContext::abiFunctions() { - return ABIFunctions(m_evmVersion, m_revertStrings, m_functions); + return ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functions); } diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 2bf837697b47..1a995734d28d 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -58,6 +58,7 @@ class IRGenerationContext IRGenerationContext( langutil::EVMVersion _evmVersion, + std::optional _eofVersion, ExecutionContext _executionContext, RevertStrings _revertStrings, std::map _sourceIndices, @@ -65,6 +66,7 @@ class IRGenerationContext langutil::CharStreamProvider const* _soliditySourceProvider ): m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), m_executionContext(_executionContext), m_revertStrings(_revertStrings), m_sourceIndices(std::move(_sourceIndices)), @@ -99,13 +101,18 @@ class IRGenerationContext /// Registers an immutable variable of the contract. /// Should only be called at construction time. void registerImmutableVariable(VariableDeclaration const& _varDecl); + void registerLibraryAddressImmutable(); + size_t libraryAddressImmutableOffset() const; + size_t libraryAddressImmutableOffsetRelative() const; /// @returns the reserved memory for storing the value of the /// immutable @a _variable during contract creation. size_t immutableMemoryOffset(VariableDeclaration const& _variable) const; + size_t immutableMemoryOffsetRelative(VariableDeclaration const& _variable) const; /// @returns the reserved memory and resets it to mark it as used. /// Intended to be used only once for initializing the free memory pointer /// to after the area used for immutables. size_t reservedMemory(); + size_t reservedMemorySize() const; void addStateVariable(VariableDeclaration const& _varDecl, u256 _storageOffset, unsigned _byteOffset); bool isStateVariable(VariableDeclaration const& _varDecl) const { return m_stateVariables.count(&_varDecl); } @@ -134,6 +141,7 @@ class IRGenerationContext YulUtilFunctions utils(); langutil::EVMVersion evmVersion() const { return m_evmVersion; } + std::optional eofVersion() const { return m_eofVersion; } ExecutionContext executionContext() const { return m_executionContext; } void setArithmetic(Arithmetic _value) { m_arithmetic = _value; } @@ -157,9 +165,23 @@ class IRGenerationContext langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; } langutil::CharStreamProvider const* soliditySourceProvider() const { return m_soliditySourceProvider; } + std::map const& immutableVariables() const { return m_immutableVariables; } + void setImmutableVariables(std::map _immutableVariables) + { + solAssert(m_eofVersion.has_value()); + solAssert(m_executionContext == ExecutionContext::Deployed); + m_immutableVariables = std::move(_immutableVariables); + } + void setLibraryAddressImmutableOffset(size_t _libraryAddressImmutableOffset) + { + solAssert(m_eofVersion.has_value()); + solAssert(m_executionContext == ExecutionContext::Deployed); + m_libraryAddressImmutableOffset = _libraryAddressImmutableOffset; + } private: langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; ExecutionContext m_executionContext; RevertStrings m_revertStrings; std::map m_sourceIndices; @@ -167,8 +189,9 @@ class IRGenerationContext ContractDefinition const* m_mostDerivedContract = nullptr; std::map m_localVariables; /// Memory offsets reserved for the values of immutable variables during contract creation. - /// This map is empty in the runtime context. + /// This map is empty in the legacy runtime context and may be not empty in EOF runtime context. std::map m_immutableVariables; + std::optional m_libraryAddressImmutableOffset; /// Total amount of reserved memory. Reserved memory is used to store /// immutable variables during contract creation. std::optional m_reservedMemory = {0}; diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 224a436338f7..9f2eedc5c18b 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -128,7 +128,7 @@ std::string IRGenerator::generate( ); }; - Whiskers t(R"( + Whiskers t(R"(/// ethdebug: enabled /// @use-src object "" { code { @@ -149,7 +149,11 @@ std::string IRGenerator::generate( - let called_via_delegatecall := iszero(eq(loadimmutable(""), address())) + + let called_via_delegatecall := iszero(eq(auxdataloadn(), address())) + + let called_via_delegatecall := iszero(eq(loadimmutable(""), address())) + @@ -162,9 +166,13 @@ std::string IRGenerator::generate( )"); resetContext(_contract, ExecutionContext::Creation); + auto const eof = m_context.eofVersion().has_value(); + if (eof && _contract.isLibrary()) + m_context.registerLibraryAddressImmutable(); for (VariableDeclaration const* var: ContractType(_contract).immutableVariables()) m_context.registerImmutableVariable(*var); + t("isEthdebugEnabled", m_context.debugInfoSelection().ethdebug); t("CreationObject", IRNames::creationObject(_contract)); t("sourceLocationCommentCreation", dispenseLocationComment(_contract)); t("library", _contract.isLibrary()); @@ -178,7 +186,10 @@ std::string IRGenerator::generate( constructorParams.emplace_back(m_context.newYulVariable()); t( "copyConstructorArguments", - m_utils.copyConstructorArgumentsToMemoryFunction(_contract, IRNames::creationObject(_contract)) + m_utils.copyConstructorArgumentsToMemoryFunction( + _contract, + IRNames::creationObject(_contract) + ) ); } t("constructorParams", joinHumanReadable(constructorParams)); @@ -198,8 +209,21 @@ std::string IRGenerator::generate( t("memoryInitCreation", memoryInit(!creationInvolvesMemoryUnsafeAssembly)); t("useSrcMapCreation", formatUseSrcMap(m_context)); + auto const immutableVariables = m_context.immutableVariables(); + auto const libraryAddressImmutableOffset = (_contract.isLibrary() && eof) ? + m_context.libraryAddressImmutableOffset() : 0; + resetContext(_contract, ExecutionContext::Deployed); + // When generating to EOF we have to initialize these two members, because they store offsets in EOF data section + // which is used during deployed container generation + if (m_eofVersion.has_value()) + { + m_context.setImmutableVariables(std::move(immutableVariables)); + if (_contract.isLibrary()) + m_context.setLibraryAddressImmutableOffset(libraryAddressImmutableOffset); + } + // NOTE: Function pointers can be passed from creation code via storage variables. We need to // get all the functions they could point to into the dispatch functions even if they're never // referenced by name in the deployed code. @@ -208,7 +232,15 @@ std::string IRGenerator::generate( // Do not register immutables to avoid assignment. t("DeployedObject", IRNames::deployedObject(_contract)); t("sourceLocationCommentDeployed", dispenseLocationComment(_contract)); - t("library_address", IRNames::libraryAddressImmutable()); + t("eof", eof); + if (_contract.isLibrary()) + { + if (!eof) + t("library_address", IRNames::libraryAddressImmutable()); + else + t("library_address_immutable_offset", std::to_string(m_context.libraryAddressImmutableOffsetRelative())); + } + t("dispatch", dispatchRoutine(_contract)); std::set deployedFunctionList = generateQueuedFunctions(); generateInternalDispatchFunctions(_contract); @@ -540,27 +572,39 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) { solAssert(paramTypes.empty(), ""); solUnimplementedAssert(type->sizeOnStack() == 1); - return Whiskers(R"( + + auto t = Whiskers(R"( function () -> rval { - rval := loadimmutable("") + + rval := auxdataloadn() + + rval := loadimmutable("") + } - )") - ( + )"); + t( "astIDComment", m_context.debugInfoSelection().astID ? "/// @ast-id " + std::to_string(_varDecl.id()) + "\n" : "" - ) - ("sourceLocationComment", dispenseLocationComment(_varDecl)) - ( + ); + t("sourceLocationComment", dispenseLocationComment(_varDecl)); + t( "contractSourceLocationComment", dispenseLocationComment(m_context.mostDerivedContract()) - ) - ("functionName", functionName) - ("id", std::to_string(_varDecl.id())) - .render(); + ); + t("functionName", functionName); + + auto const eof = m_context.eofVersion().has_value(); + t("eof", eof); + if (!eof) + t("id", std::to_string(_varDecl.id())); + else + t("immutableOffset", std::to_string(m_context.immutableMemoryOffsetRelative(_varDecl))); + + return t.render(); } else if (_varDecl.isConstant()) { @@ -736,7 +780,7 @@ std::string IRGenerator::generateExternalFunction(ContractDefinition const& _con unsigned paramVars = std::make_shared(_functionType.parameterTypes())->sizeOnStack(); unsigned retVars = std::make_shared(_functionType.returnParameterTypes())->sizeOnStack(); - ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector()); + ABIFunctions abiFunctions(m_evmVersion, m_eofVersion, m_context.revertStrings(), m_context.functionCollector()); t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes())); t("params", suffixedVariableNameList("param_", 0, paramVars)); t("retParams", suffixedVariableNameList("ret_", 0, retVars)); @@ -948,13 +992,22 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) std::string IRGenerator::deployCode(ContractDefinition const& _contract) { Whiskers t(R"X( - let := () - codecopy(, dataoffset(""), datasize("")) - <#immutables> - setimmutable(, "", ) - - return(, datasize("")) + + + mstore(, address()) + + returncontract("", , ) + + let := () + codecopy(, dataoffset(""), datasize("")) + <#immutables> + setimmutable(, "", ) + + return(, datasize("")) + )X"); + auto const eof = m_context.eofVersion().has_value(); + t("eof", eof); t("allocateUnbounded", m_utils.allocateUnboundedFunction()); t("codeOffset", m_context.newYulVariable()); t("object", IRNames::deployedObject(_contract)); @@ -963,23 +1016,38 @@ std::string IRGenerator::deployCode(ContractDefinition const& _contract) if (_contract.isLibrary()) { solAssert(ContractType(_contract).immutableVariables().empty(), ""); - immutables.emplace_back(std::map{ - {"immutableName"s, IRNames::libraryAddressImmutable()}, - {"value"s, "address()"} - }); - + if (!eof) + immutables.emplace_back(std::map{ + {"immutableName"s, IRNames::libraryAddressImmutable()}, + {"value"s, "address()"} + }); + else + t("libraryAddressImmutableOffset", std::to_string(m_context.libraryAddressImmutableOffset())); } else + { for (VariableDeclaration const* immutable: ContractType(_contract).immutableVariables()) { solUnimplementedAssert(immutable->type()->isValueType()); solUnimplementedAssert(immutable->type()->sizeOnStack() == 1); - immutables.emplace_back(std::map{ - {"immutableName"s, std::to_string(immutable->id())}, - {"value"s, "mload(" + std::to_string(m_context.immutableMemoryOffset(*immutable)) + ")"} - }); + if (!eof) + immutables.emplace_back(std::map{ + {"immutableName"s, std::to_string(immutable->id())}, + {"value"s, "mload(" + std::to_string(m_context.immutableMemoryOffset(*immutable)) + ")"} + }); } - t("immutables", std::move(immutables)); + } + + if (eof) + { + t("library", _contract.isLibrary()); + t("auxDataStart", std::to_string(CompilerUtils::generalPurposeMemoryStart)); + solAssert(m_context.reservedMemorySize() <= 0xFFFF, "Reserved memory size exceeded maximum allowed EOF data section size."); + t("auxDataSize", std::to_string(m_context.reservedMemorySize())); + } + else + t("immutables", std::move(immutables)); + return t.render(); } @@ -1106,17 +1174,19 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon ); IRGenerationContext newContext( m_evmVersion, + m_eofVersion, _context, m_context.revertStrings(), m_context.sourceIndices(), m_context.debugInfoSelection(), m_context.soliditySourceProvider() ); + m_context = std::move(newContext); m_context.setMostDerivedContract(_contract); for (auto const location: {DataLocation::Storage, DataLocation::Transient}) - for (auto const& var: ContractType(_contract).stateVariables(location)) + for (auto const& var: ContractType(_contract).linearizedStateVariables(location)) m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); } diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index 9f01b74fc246..60d5d25cd026 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -59,13 +59,14 @@ class IRGenerator m_eofVersion(_eofVersion), m_context( _evmVersion, + _eofVersion, ExecutionContext::Creation, _revertStrings, std::move(_sourceIndices), _debugInfoSelection, _soliditySourceProvider ), - m_utils(_evmVersion, m_context.revertStrings(), m_context.functionCollector()), + m_utils(_evmVersion, _eofVersion, m_context.revertStrings(), m_context.functionCollector()), m_optimiserSettings(_optimiserSettings) {} diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 887df6ab34a3..49f8989ef3ba 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -84,7 +84,7 @@ struct CopyTranslate: public yul::ASTCopier // from the Yul dialect we are compiling to. So we are assuming here that the builtin // functions are identical. This should not be a problem for now since everything // is EVM anyway. - if (m_dialect.builtin(_name)) + if (m_dialect.findBuiltin(_name.str())) return _name; else return yul::YulName{"usr$" + _name.str()}; @@ -1072,7 +1072,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) { auto const& event = dynamic_cast(functionType->declaration()); TypePointers paramTypes = functionType->parameterTypes(); - ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); + ABIFunctions abi(m_context.evmVersion(), m_context.eofVersion(), m_context.revertStrings(), m_context.functionCollector()); std::vector indexedArgs; std::vector nonIndexedArgs; @@ -1529,6 +1529,15 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) case FunctionType::Kind::BlockHash: case FunctionType::Kind::BlobHash: { + solAssert( + !m_context.eofVersion().has_value() || functionType->kind() != FunctionType::Kind::GasLeft, + "EOF does not support gasleft." + ); + solAssert( + !m_context.eofVersion().has_value() || functionType->kind() != FunctionType::Kind::Selfdestruct, + "EOF does not support selfdestruct." + ); + static std::map functions = { {FunctionType::Kind::GasLeft, "gas"}, {FunctionType::Kind::Selfdestruct, "selfdestruct"}, @@ -1563,22 +1572,30 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) &dynamic_cast(*functionType->returnParameterTypes().front()).contractDefinition(); m_context.addSubObject(contract); - Whiskers t(R"(let := () - let := add(, datasize("")) - if or(gt(, 0xffffffffffffffff), lt(, )) { () } - datacopy(, dataoffset(""), datasize("")) - := () - - let
:= create2(, , sub(, ), ) - - let
:= create(, , sub(, )) - + Whiskers t(R"( + + let := () + let := () + let
:= eofcreate("", , , , sub(, )) + + let := () + let := add(, datasize("")) + if or(gt(, 0xffffffffffffffff), lt(, )) { () } + datacopy(, dataoffset(""), datasize("")) + := () + + let
:= create2(, , sub(, ), ) + + let
:= create(, , sub(, )) + + let := iszero(iszero(
)) if iszero(
) { () } )"); + t("eof", m_context.eofVersion().has_value()); t("memPos", m_context.newYulVariable()); t("memEnd", m_context.newYulVariable()); t("allocateUnbounded", m_utils.allocateUnboundedFunction()); @@ -1592,6 +1609,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) t("saltSet", functionType->saltSet()); if (functionType->saltSet()) t("salt", IRVariable(_functionCall.expression()).part("salt").name()); + else if (m_context.eofVersion().has_value()) // Set salt to 0 if not defined. + t("salt", "0"); // TODO: We should reject non-salted creation during analysis and not set here solAssert(IRVariable(_functionCall).stackSlots().size() == 1); t("address", IRVariable(_functionCall).commaSeparatedList()); t("isTryCall", _functionCall.annotation().tryCall); @@ -1612,11 +1631,16 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) Whiskers templ(R"( let := 0 if iszero() { := } - let := call(,
, , 0, 0, 0, 0) + + let := iszero(extcall(
, 0, 0, )) + + let := call(,
, , 0, 0, 0, 0) + if iszero() { () } )"); + templ("eof", m_context.eofVersion().has_value()); templ("gas", m_context.newYulVariable()); templ("callStipend", toString(evmasm::GasCosts::callStipend)); templ("address", address); @@ -1701,17 +1725,30 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) mstore(0, 0) - let := (,
, 0, , sub(, ), 0, 32) + + // EOF always uses extstaticcall + let := iszero(extstaticcall(
, , sub(, ))) + + let := (,
, 0, , sub(, ), 0, 32) + if iszero() { () } + + if eq(returndatasize(), 32) { returndatacopy(0, 0, 32) } + let := (mload(0)) )"); - templ("call", m_context.evmVersion().hasStaticCall() ? "staticcall" : "call"); - templ("isCall", !m_context.evmVersion().hasStaticCall()); + auto const eof = m_context.eofVersion().has_value(); + if (!eof) + { + templ("call", m_context.evmVersion().hasStaticCall() ? "staticcall" : "call"); + templ("isCall", !m_context.evmVersion().hasStaticCall()); + } templ("shl", m_utils.shiftLeftFunction(offset * 8)); templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); templ("pos", m_context.newYulVariable()); templ("end", m_context.newYulVariable()); templ("isECRecover", FunctionType::Kind::ECRecover == functionType->kind()); + templ("eof", eof); if (FunctionType::Kind::ECRecover == functionType->kind()) templ("encodeArgs", m_context.abiFunctions().tupleEncoder(argumentTypes, parameterTypes)); else @@ -2155,6 +2192,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) ")\n"; else if (member == "code") { + solAssert(!m_context.eofVersion().has_value(), "EOF does not support address.code."); std::string externalCodeFunction = m_utils.externalCodeFunction(); define(_memberAccess) << externalCodeFunction << @@ -2163,10 +2201,13 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) ")\n"; } else if (member == "codehash") + { + solAssert(!m_context.eofVersion().has_value(), "EOF does not support address.codehash."); define(_memberAccess) << "extcodehash(" << expressionAsType(_memberAccess.expression(), *TypeProvider::address()) << ")\n"; + } else if (member == "isContract") define(_memberAccess) << "iscontract(" << @@ -2354,6 +2395,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) solAssert(false, "Blockhash has been removed."); else if (member == "creationCode" || member == "runtimeCode") { + solAssert(!m_context.eofVersion().has_value(), "EOF does not support \"" + member + "\"."); Type const* arg = dynamic_cast(*_memberAccess.expression().annotation().type).typeArgument(); auto const& contractType = dynamic_cast(*arg); solAssert(!contractType.isSuper()); @@ -2669,7 +2711,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) solAssert(std::holds_alternative(modified)); - appendCode() << yul::AsmPrinter()(std::get(modified)) << "\n"; + appendCode() << yul::AsmPrinter(_inlineAsm.dialect())(std::get(modified)) << "\n"; return false; } @@ -3031,7 +3073,6 @@ void IRGeneratorForStatements::appendExternalFunctionCall( argumentStrings += IRVariable(*arg).stackSlots(); } - if (!m_context.evmVersion().canOverchargeGasForCall()) { // Touch the end of the output area so that we do not pay for memory resize during the call @@ -3043,7 +3084,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } // 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(). + // When it's dynamic, we get zero from estimatedReturnSize() instead and then we need an explicit returndatacopy(). Whiskers templ(R"( if iszero(extcodesize(
)) { () } @@ -3053,7 +3094,11 @@ void IRGeneratorForStatements::appendExternalFunctionCall( mstore(, ()) let := (add(, 4) ) - let := (,
, , , sub(, ), , ) + + let := iszero((
, , sub(, ) , )) + + let := (,
, , , sub(, ), , ) + if iszero() { () } @@ -3068,6 +3113,9 @@ void IRGeneratorForStatements::appendExternalFunctionCall( if gt(, returndatasize()) { := returndatasize() } + + returndatacopy(, 0, ) + @@ -3079,6 +3127,9 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } )"); templ("revertNoCode", m_utils.revertReasonIfDebugFunction("Target contract does not contain code")); + auto const eof = m_context.eofVersion().has_value(); + solAssert(!eof || !funType.gasSet()); + templ("eof", eof); // We do not need to check extcodesize if we expect return data: If there is no // code, the call will return empty data and the ABI decoder will revert. @@ -3086,9 +3137,12 @@ void IRGeneratorForStatements::appendExternalFunctionCall( for (auto const& t: returnInfo.returnTypes) encodedHeadSize += t->decodingType()->calldataHeadSize(); bool const checkExtcodesize = - encodedHeadSize == 0 || - !m_context.evmVersion().supportsReturndata() || - m_context.revertStrings() >= RevertStrings::Debug; + !eof && + ( + encodedHeadSize == 0 || + !m_context.evmVersion().supportsReturndata() || + m_context.revertStrings() >= RevertStrings::Debug + ); templ("checkExtcodesize", checkExtcodesize); templ("pos", m_context.newYulVariable()); @@ -3149,11 +3203,11 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } // Order is important here, STATICCALL might overlap with DELEGATECALL. if (isDelegateCall) - templ("call", "delegatecall"); + templ("call", eof ? "extdelegatecall" : "delegatecall"); else if (useStaticCall) - templ("call", "staticcall"); + templ("call", eof ? "extstaticcall" : "staticcall"); else - templ("call", "call"); + templ("call", eof ? "extcall" : "call"); templ("forwardingRevert", m_utils.forwardingRevertFunction()); @@ -3192,13 +3246,20 @@ void IRGeneratorForStatements::appendBareCall( let := mload() - let := (,
, , , , 0, 0) + + let := iszero((
, , , )) + + let := (,
, , , , 0, 0) + + let := () )"); templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); templ("pos", m_context.newYulVariable()); templ("length", m_context.newYulVariable()); + auto const eof = m_context.eofVersion().has_value(); + templ("eof", eof); templ("arg", IRVariable(*_arguments.front()).commaSeparatedList()); Type const& argType = type(*_arguments.front()); @@ -3207,7 +3268,7 @@ void IRGeneratorForStatements::appendBareCall( else { templ("needsEncoding", true); - ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); + ABIFunctions abi(m_context.evmVersion(), m_context.eofVersion(), m_context.revertStrings(), m_context.functionCollector()); templ("encode", abi.tupleEncoderPacked({&argType}, {TypeProvider::bytesMemory()})); } @@ -3220,18 +3281,19 @@ void IRGeneratorForStatements::appendBareCall( if (funKind == FunctionType::Kind::BareCall) { templ("value", funType.valueSet() ? IRVariable(_functionCall.expression()).part("value").name() : "0"); - templ("call", "call"); + templ("call", eof ? "extcall" : "call"); } else { solAssert(!funType.valueSet(), "Value set for delegatecall or staticcall."); templ("value", ""); if (funKind == FunctionType::Kind::BareStaticCall) - templ("call", "staticcall"); + templ("call", eof ? "extstaticcall" : "staticcall"); else - templ("call", "delegatecall"); + templ("call", eof ? "extdelegatecall" : "delegatecall"); } + solAssert(!eof || !funType.gasSet()); if (funType.gasSet()) templ("gas", IRVariable(_functionCall.expression()).part("gas").name()); else if (m_context.evmVersion().canOverchargeGasForCall()) @@ -3656,7 +3718,12 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue) ")\n"; } else - define(result) << "loadimmutable(\"" << std::to_string(_immutable.variable->id()) << "\")\n"; + { + if (!m_context.eofVersion().has_value()) + define(result) << "loadimmutable(\"" << std::to_string(_immutable.variable->id()) << "\")\n"; + else + define(result) << "auxdataloadn(" << std::to_string(m_context.immutableMemoryOffsetRelative(*_immutable.variable)) << ")\n"; + } }, [&](IRLValue::Tuple const&) { solAssert(false, "Attempted to read from tuple lvalue."); diff --git a/libsolidity/experimental/ast/TypeSystem.cpp b/libsolidity/experimental/ast/TypeSystem.cpp index 059054dcdbce..5198743ed67f 100644 --- a/libsolidity/experimental/ast/TypeSystem.cpp +++ b/libsolidity/experimental/ast/TypeSystem.cpp @@ -24,7 +24,8 @@ #include -#include +#include + #include #include #include diff --git a/libsolidity/experimental/ast/TypeSystemHelper.cpp b/libsolidity/experimental/ast/TypeSystemHelper.cpp index 9ad18e1608bc..b01bc0529414 100644 --- a/libsolidity/experimental/ast/TypeSystemHelper.cpp +++ b/libsolidity/experimental/ast/TypeSystemHelper.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include diff --git a/libsolidity/experimental/codegen/IRGenerator.cpp b/libsolidity/experimental/codegen/IRGenerator.cpp index 60a93bbf01d9..457b28e37396 100644 --- a/libsolidity/experimental/codegen/IRGenerator.cpp +++ b/libsolidity/experimental/codegen/IRGenerator.cpp @@ -67,6 +67,7 @@ std::string IRGenerator::run( std::map const& /*_otherYulSources*/ ) { + solUnimplementedAssert(!m_eofVersion.has_value(), "Experimental IRGenerator not implemented for EOF"); Whiskers t(R"( object "" { diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 772e8575dbfd..80c442b88146 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -72,7 +72,7 @@ struct CopyTranslate: public yul::ASTCopier yul::YulName translateIdentifier(yul::YulName _name) override { - if (m_dialect.builtin(_name)) + if (m_dialect.findBuiltin(_name.str())) return _name; else return yul::YulName{"usr$" + _name.str()}; @@ -132,7 +132,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) CopyTranslate bodyCopier{m_context, _assembly.dialect(), _assembly.annotation().externalReferences}; yul::Statement modified = bodyCopier(_assembly.operations().root()); solAssert(std::holds_alternative(modified)); - m_code << yul::AsmPrinter()(std::get(modified)) << "\n"; + m_code << yul::AsmPrinter(_assembly.dialect())(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index fda573d3d4cf..e5521b816582 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -20,22 +20,16 @@ #include #include +#include #include #include -#ifdef HAVE_Z3 -#include -#endif #include #include #include -#ifdef HAVE_Z3_DLOPEN -#include -#endif - using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; @@ -55,28 +49,14 @@ BMC::BMC( ): SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _provedSafeReporter, _charStreamProvider) { - solAssert(!_settings.printQuery || _settings.solvers == SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); std::vector> solvers; if (_settings.solvers.smtlib2) solvers.emplace_back(std::make_unique(_smtlib2Responses, _smtCallback, _settings.timeout)); if (_settings.solvers.cvc5) solvers.emplace_back(std::make_unique(_smtCallback, _settings.timeout)); -#ifdef HAVE_Z3 - if (_settings.solvers.z3 && Z3Interface::available()) - solvers.emplace_back(std::make_unique(_settings.timeout)); -#endif + if (_settings.solvers.z3 ) + solvers.emplace_back(std::make_unique(_smtCallback, _settings.timeout)); m_interface = std::make_unique(std::move(solvers), _settings.timeout); -#if defined (HAVE_Z3) - if (m_settings.solvers.z3) - if (!_smtlib2Responses.empty()) - m_errorReporter.warning( - 5622_error, - "SMT-LIB2 query responses were given in the auxiliary input, " - "but this Solidity binary uses an SMT solver Z3 directly." - "These responses will be ignored." - "Consider disabling Z3 at compilation time in order to use SMT-LIB2 responses." - ); -#endif } void BMC::analyze(SourceUnit const& _source, std::map, smt::EncodingContext::IdCompare> _solvedTargets) @@ -101,7 +81,9 @@ void BMC::analyze(SourceUnit const& _source, std::mapaccept(*this); forCondition = expr(*_node.condition()); } - // asseert that the loop is complete + // assert that the loop is complete m_context.addAssertion(!forCondition || broke || !forConditionOnPreviousIterations); mergeVariables( broke || !forConditionOnPreviousIterations, @@ -673,6 +652,7 @@ void BMC::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::ECRecover: case FunctionType::Kind::SHA256: case FunctionType::Kind::RIPEMD160: + case FunctionType::Kind::BlobHash: case FunctionType::Kind::BlockHash: case FunctionType::Kind::AddMod: case FunctionType::Kind::MulMod: @@ -1201,7 +1181,7 @@ void BMC::checkCondition( m_errorReporter.warning(1584_error, _location, "BMC: At least two SMT solvers provided conflicting answers. Results might not be sound."); break; case smtutil::CheckResult::ERROR: - m_errorReporter.warning(1823_error, _location, "BMC: Error trying to invoke SMT solver."); + m_errorReporter.warning(1823_error, _location, "BMC: Error during interaction with the SMT solver."); break; } @@ -1281,8 +1261,10 @@ BMC::checkSatisfiableAndGenerateModel(std::vector const& _e 6240_error, "BMC: Requested query:\n" + smtlibCode ); + result = CheckResult::UNKNOWN; } - tie(result, values) = m_interface->check(_expressionsToEvaluate); + else + tie(result, values) = m_interface->check(_expressionsToEvaluate); } catch (smtutil::SolverError const& _e) { diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index c52a83a26183..c313ae54e1ae 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -18,18 +18,14 @@ #include -#include - -#ifdef HAVE_Z3 -#include -#endif - #include #include #include +#include #include #include #include +#include #include @@ -38,10 +34,6 @@ #include #include -#ifdef HAVE_Z3_DLOPEN -#include -#endif - #include #include @@ -72,9 +64,7 @@ CHC::CHC( SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _provedSafeReporter, _charStreamProvider), m_smtlib2Responses(_smtlib2Responses), m_smtCallback(_smtCallback) -{ - solAssert(!_settings.printQuery || _settings.solvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); -} +{} void CHC::analyze(SourceUnit const& _source) { @@ -649,6 +639,7 @@ void CHC::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::ECRecover: case FunctionType::Kind::SHA256: case FunctionType::Kind::RIPEMD160: + case FunctionType::Kind::BlobHash: case FunctionType::Kind::BlockHash: case FunctionType::Kind::AddMod: case FunctionType::Kind::MulMod: @@ -861,7 +852,7 @@ void CHC::visitDeployment(FunctionCall const& _funCall) auto const& params = constructor->parameters(); solAssert(args.size() == params.size(), ""); for (auto [arg, param]: ranges::zip_view(args, params)) - m_context.addAssertion(expr(*arg) == m_context.variable(*param)->currentValue()); + m_context.addAssertion(expr(*arg, param->type()) == m_context.variable(*param)->currentValue()); } for (auto var: stateVariablesIncludingInheritedAndPrivate(*contract)) m_context.variable(*var)->increaseIndex(); @@ -934,17 +925,6 @@ void CHC::internalFunctionCall(FunctionCall const& _funCall) Expression const* calledExpr = &_funCall.expression(); auto funType = dynamic_cast(calledExpr->annotation().type); - auto contractAddressValue = [this](FunctionCall const& _f) { - auto [callExpr, callOptions] = functionCallExpression(_f); - - FunctionType const& funType = dynamic_cast(*callExpr->annotation().type); - if (funType.kind() == FunctionType::Kind::Internal) - return state().thisAddress(); - if (MemberAccess const* callBase = dynamic_cast(callExpr)) - return expr(callBase->expression()); - solAssert(false, "Unreachable!"); - }; - std::vector arguments; for (auto& arg: _funCall.sortedArguments()) arguments.push_back(&(*arg)); @@ -1279,41 +1259,29 @@ void CHC::resetSourceAnalysis() ArraySlicePredicate::reset(); m_blockCounter = 0; - // At this point every enabled solver is available. - // If more than one Horn solver is selected we go with z3. - // We still need the ifdef because of Z3CHCInterface. - if (m_settings.solvers.z3) + solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld || m_settings.solvers.z3); + if (!m_interface) { -#ifdef HAVE_Z3 - // z3::fixedpoint does not have a reset mechanism, so we need to create another. - m_interface = std::make_unique(m_settings.timeout); - auto z3Interface = dynamic_cast(m_interface.get()); - solAssert(z3Interface, ""); - m_context.setSolver(z3Interface->z3Interface()); -#else - solAssert(false); -#endif + if (m_settings.solvers.z3) + m_interface = std::make_unique( + m_smtCallback, + m_settings.timeout, + m_settings.invariants != ModelCheckerInvariants::None() + ); + else if (m_settings.solvers.eld) + m_interface = std::make_unique( + m_smtCallback, + m_settings.timeout, + m_settings.invariants != ModelCheckerInvariants::None() + ); + else + m_interface = std::make_unique(m_smtlib2Responses, m_smtCallback, m_settings.timeout); } - else - { - solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld); - if (!m_interface) - { - if (m_settings.solvers.eld) - m_interface = std::make_unique( - m_smtCallback, - m_settings.timeout, - m_settings.invariants != ModelCheckerInvariants::None() - ); - else - m_interface = std::make_unique(m_smtlib2Responses, m_smtCallback, m_settings.timeout); - } - auto smtlib2Interface = dynamic_cast(m_interface.get()); - solAssert(smtlib2Interface); - smtlib2Interface->reset(); - m_context.setSolver(smtlib2Interface); - } + auto smtlib2Interface = dynamic_cast(m_interface.get()); + solAssert(smtlib2Interface); + smtlib2Interface->reset(); + m_context.setSolver(smtlib2Interface); m_context.reset(); m_context.resetUniqueId(); @@ -1356,7 +1324,7 @@ void CHC::clearIndices(ContractDefinition const* _contract, FunctionDefinition c void CHC::setCurrentBlock(Predicate const& _block) { - if (m_context.solverStackHeigh() > 0) + if (m_context.solverStackHeight() > 0) m_context.popSolver(); solAssert(m_currentContract, ""); clearIndices(m_currentContract, m_currentFunction); @@ -1927,34 +1895,12 @@ CHCSolverInterface::QueryResult CHC::query(smtutil::Expression const& _query, la 2339_error, "CHC: Requested query:\n" + smtLibCode ); + return {.answer = CheckResult::UNKNOWN, .invariant = smtutil::Expression(true), .cex = {}}; } auto result = m_interface->query(_query); switch (result.answer) { case CheckResult::SATISFIABLE: - { - // We still need the ifdef because of Z3CHCInterface. - if (m_settings.solvers.z3) - { -#ifdef HAVE_Z3 - // Even though the problem is SAT, Spacer's pre processing makes counterexamples incomplete. - // We now disable those optimizations and check whether we can still solve the problem. - auto* spacer = dynamic_cast(m_interface.get()); - solAssert(spacer, ""); - spacer->setSpacerOptions(false); - - auto resultNoOpt = m_interface->query(_query); - - if (resultNoOpt.answer == CheckResult::SATISFIABLE) - result.cex = std::move(resultNoOpt.cex); - - spacer->setSpacerOptions(true); -#else - solAssert(false); -#endif - } - break; - } case CheckResult::UNSATISFIABLE: case CheckResult::UNKNOWN: break; @@ -1962,7 +1908,7 @@ CHCSolverInterface::QueryResult CHC::query(smtutil::Expression const& _query, la m_errorReporter.warning(1988_error, _location, "CHC: At least two SMT solvers provided conflicting answers. Results might not be sound."); break; case CheckResult::ERROR: - m_errorReporter.warning(1218_error, _location, "CHC: Error trying to invoke SMT solver."); + m_errorReporter.warning(1218_error, _location, "CHC: Error during interaction with the solver."); break; } return result; @@ -2222,7 +2168,13 @@ void CHC::checkAndReportTarget( } else if (result == CheckResult::SATISFIABLE) { - solAssert(!_satMsg.empty(), ""); + solAssert(!_satMsg.empty()); + if (auto it = m_safeTargets.find(_target.errorNode); it != m_safeTargets.end()) + { + std::erase_if(it->second, [&](auto const& target) { return target.type == _target.type; }); + if (it->second.empty()) + m_safeTargets.erase(it); + } auto cex = generateCounterexample(model, error().name); if (cex) m_unsafeTargets[_target.errorNode][_target.type] = { diff --git a/libsolidity/formal/EncodingContext.h b/libsolidity/formal/EncodingContext.h index 35e54ed76bc9..5387184ee0c9 100644 --- a/libsolidity/formal/EncodingContext.h +++ b/libsolidity/formal/EncodingContext.h @@ -142,7 +142,7 @@ class EncodingContext void pushSolver(); void popSolver(); void addAssertion(smtutil::Expression const& _e); - size_t solverStackHeigh() { return m_assertions.size(); } const + size_t solverStackHeight() { return m_assertions.size(); } const smtutil::SolverInterface* solver() { solAssert(m_solver, ""); diff --git a/libsolidity/formal/ExpressionFormatter.cpp b/libsolidity/formal/ExpressionFormatter.cpp index 6571cf6dd7a2..865a568f62da 100644 --- a/libsolidity/formal/ExpressionFormatter.cpp +++ b/libsolidity/formal/ExpressionFormatter.cpp @@ -245,7 +245,14 @@ std::optional expressionToString(smtutil::Expression const& _expr, if (smt::isNumber(*_type)) { solAssert(_expr.sort->kind == Kind::Int); - solAssert(_expr.arguments.empty()); + solAssert(_expr.arguments.empty() || _expr.name == "-"); + if (_expr.name == "-") + { + solAssert(_expr.arguments.size() == 1); + smtutil::Expression const& val = _expr.arguments[0]; + solAssert(val.sort->kind == Kind::Int && val.arguments.empty()); + return "(- " + val.name + ")"; + } if ( _type->category() == frontend::Type::Category::Address || diff --git a/libsolidity/formal/ModelChecker.cpp b/libsolidity/formal/ModelChecker.cpp index 91b88cb9c842..04d96f06746c 100644 --- a/libsolidity/formal/ModelChecker.cpp +++ b/libsolidity/formal/ModelChecker.cpp @@ -17,12 +17,6 @@ // SPDX-License-Identifier: GPL-3.0 #include -#ifdef HAVE_Z3 -#include -#endif -#ifdef HAVE_Z3_DLOPEN -#include -#endif #include @@ -170,8 +164,10 @@ SMTSolverChoice ModelChecker::availableSolvers() smtutil::SMTSolverChoice available = smtutil::SMTSolverChoice::SMTLIB2(); available.eld = !boost::process::search_path("eld").empty(); available.cvc5 = !boost::process::search_path("cvc5").empty(); -#ifdef HAVE_Z3 - available.z3 = solidity::smtutil::Z3Interface::available(); +#ifdef EMSCRIPTEN_BUILD + available.z3 = true; +#else + available.z3 = !boost::process::search_path("z3").empty(); #endif return available; } @@ -211,9 +207,6 @@ SMTSolverChoice ModelChecker::checkRequestedSolvers(SMTSolverChoice _enabled, Er 8158_error, SourceLocation(), "Solver z3 was selected for SMTChecker but it is not available." -#ifdef HAVE_Z3_DLOPEN - " libz3.so." + std::to_string(Z3_MAJOR_VERSION) + "." + std::to_string(Z3_MINOR_VERSION) + " was not found." -#endif ); } diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index 5cac3a6a9230..4b7ca8edb324 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -247,24 +247,17 @@ std::string Predicate::formatSummaryCall( { bool visit(MemberAccess const& _memberAccess) { - Expression const* memberExpr = SMTEncoder::innermostTuple(_memberAccess.expression()); - - Type const* exprType = memberExpr->annotation().type; - solAssert(exprType, ""); - if (exprType->category() == Type::Category::Magic) - if (auto const* identifier = dynamic_cast(memberExpr)) - { - ASTString const& name = identifier->name(); - auto memberName = _memberAccess.memberName(); - - // TODO remove this for 0.9.0 - if (name == "block" && memberName == "difficulty") - memberName = "prevrandao"; - - if (name == "block" || name == "msg" || name == "tx") - txVars.insert(name + "." + memberName); - } - + if (auto magicType = dynamic_cast(_memberAccess.expression().annotation().type)) + { + auto memberName = _memberAccess.memberName(); + auto magicKind = magicType->kind(); + // TODO remove this for 0.9.0 + if (magicKind == MagicType::Kind::Block && memberName == "difficulty") + memberName = "prevrandao"; + + if (magicKind == MagicType::Kind::Block || magicKind == MagicType::Kind::Message || magicKind == MagicType::Kind::Transaction) + txVars.insert(magicType->toString(true) + "." + memberName); + } return true; } @@ -489,22 +482,7 @@ std::map Predicate::expressionSubstitution(smtutil::Ex std::map> Predicate::readTxVars(smtutil::Expression const& _tx) const { - std::map const txVars{ - {"block.basefee", TypeProvider::uint256()}, - {"block.chainid", TypeProvider::uint256()}, - {"block.coinbase", TypeProvider::address()}, - {"block.prevrandao", TypeProvider::uint256()}, - {"block.gaslimit", TypeProvider::uint256()}, - {"block.number", TypeProvider::uint256()}, - {"block.timestamp", TypeProvider::uint256()}, - {"blockhash", TypeProvider::array(DataLocation::Memory, TypeProvider::uint256())}, - {"msg.data", TypeProvider::array(DataLocation::CallData)}, - {"msg.sender", TypeProvider::address()}, - {"msg.sig", TypeProvider::fixedBytes(4)}, - {"msg.value", TypeProvider::uint256()}, - {"tx.gasprice", TypeProvider::uint256()}, - {"tx.origin", TypeProvider::address()} - }; + std::map const txVars = transactionMemberTypes(); std::map> vars; for (auto&& [i, v]: txVars | ranges::views::enumerate) vars.emplace(v.first, expressionToString(_tx.arguments.at(i), v.second)); diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 1c0808cc017b..801ad05a2056 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -428,9 +428,11 @@ void SMTEncoder::endVisit(TupleExpression const& _tuple) { // Add constraints for the length and values as it is known. auto symbArray = std::dynamic_pointer_cast(m_context.expression(_tuple)); - solAssert(symbArray, ""); - - addArrayLiteralAssertions(*symbArray, applyMap(_tuple.components(), [&](auto const& c) { return expr(*c); })); + smtAssert(symbArray, "Inline array must be represented with SymbolicArrayVariable"); + auto originalType = symbArray->originalType(); + auto arrayType = dynamic_cast(originalType); + smtAssert(arrayType, "Type of inline array must be ArrayType"); + addArrayLiteralAssertions(*symbArray, applyMap(_tuple.components(), [&](auto const& c) { return expr(*c, arrayType->baseType()); })); } else { @@ -463,22 +465,22 @@ void SMTEncoder::endVisit(UnaryOperation const& _op) if (*_op.annotation().userDefinedFunction) return; - auto const* subExpr = innermostTuple(_op.subExpression()); + auto const& subExpr = innermostTuple(_op.subExpression()); auto type = _op.annotation().type; switch (_op.getOperator()) { case Token::Not: // ! { solAssert(smt::isBool(*type), ""); - defineExpr(_op, !expr(*subExpr)); + defineExpr(_op, !expr(subExpr)); break; } case Token::Inc: // ++ (pre- or postfix) case Token::Dec: // -- (pre- or postfix) { solAssert(smt::isInteger(*type) || smt::isFixedPoint(*type), ""); - solAssert(subExpr->annotation().willBeWrittenTo, ""); - auto innerValue = expr(*subExpr); + solAssert(subExpr.annotation().willBeWrittenTo, ""); + auto innerValue = expr(subExpr); auto newValue = arithmeticOperation( _op.getOperator() == Token::Inc ? Token::Add : Token::Sub, innerValue, @@ -487,34 +489,34 @@ void SMTEncoder::endVisit(UnaryOperation const& _op) _op ).first; defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue); - assignment(*subExpr, newValue); + assignment(subExpr, newValue); break; } case Token::Sub: // - { - defineExpr(_op, 0 - expr(*subExpr)); + defineExpr(_op, 0 - expr(subExpr)); break; } case Token::Delete: { - if (auto decl = identifierToVariable(*subExpr)) + if (auto decl = identifierToVariable(subExpr)) { m_context.newValue(*decl); m_context.setZeroValue(*decl); } else { - solAssert(m_context.knownExpression(*subExpr), ""); - auto const& symbVar = m_context.expression(*subExpr); + solAssert(m_context.knownExpression(subExpr), ""); + auto const& symbVar = m_context.expression(subExpr); symbVar->increaseIndex(); m_context.setZeroValue(*symbVar); if ( - dynamic_cast(subExpr) || - dynamic_cast(subExpr) + dynamic_cast(&subExpr) || + dynamic_cast(&subExpr) ) - indexOrMemberAssignment(*subExpr, symbVar->currentValue()); + indexOrMemberAssignment(subExpr, symbVar->currentValue()); // Empty push added a zero value anyway, so no need to delete extra. - else if (!isEmptyPush(*subExpr)) + else if (!isEmptyPush(subExpr)) solAssert(false, ""); } break; @@ -677,6 +679,9 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::BlockHash: defineExpr(_funCall, state().blockhash(expr(*_funCall.arguments().at(0)))); break; + case FunctionType::Kind::BlobHash: + visitBlobHash(_funCall); + break; case FunctionType::Kind::AddMod: case FunctionType::Kind::MulMod: visitAddMulMod(_funCall); @@ -855,7 +860,7 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall) { auto const& funType = dynamic_cast(*_funCall.expression().annotation().type); auto kind = funType.kind(); - auto arg0 = expr(*_funCall.arguments().at(0)); + auto arg0 = expr(*_funCall.arguments().at(0), TypeProvider::bytesStorage()); std::optional result; if (kind == FunctionType::Kind::KECCAK256) result = smtutil::Expression::select(state().cryptoFunction("keccak256"), arg0); @@ -866,10 +871,10 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall) else if (kind == FunctionType::Kind::ECRecover) { auto e = state().cryptoFunction("ecrecover"); - auto arg0 = expr(*_funCall.arguments().at(0)); - auto arg1 = expr(*_funCall.arguments().at(1)); - auto arg2 = expr(*_funCall.arguments().at(2)); - auto arg3 = expr(*_funCall.arguments().at(3)); + auto arg0 = expr(*_funCall.arguments().at(0), TypeProvider::fixedBytes(32)); + auto arg1 = expr(*_funCall.arguments().at(1), TypeProvider::uint(8)); + auto arg2 = expr(*_funCall.arguments().at(2), TypeProvider::fixedBytes(32)); + auto arg3 = expr(*_funCall.arguments().at(3), TypeProvider::fixedBytes(32)); auto inputSort = dynamic_cast(*e.sort).domain; auto ecrecoverInput = smtutil::Expression::tuple_constructor( smtutil::Expression(std::make_shared(inputSort), ""), @@ -897,6 +902,18 @@ void SMTEncoder::visitGasLeft(FunctionCall const& _funCall) m_context.addAssertion(symbolicVar->currentValue() <= symbolicVar->valueAtIndex(index - 1)); } +void SMTEncoder::visitBlobHash(FunctionCall const& _funCall) +{ + constexpr unsigned BLOB_TRANSACTION_LIMIT = 9; // Since pectra + auto indexExpr = expr(*_funCall.arguments().at(0)); + auto valueExpr = smtutil::Expression::ite( + indexExpr >= BLOB_TRANSACTION_LIMIT, + smtutil::Expression(u256(0)), + state().blobhash(indexExpr) + ); + defineExpr(_funCall, std::move(valueExpr)); +} + void SMTEncoder::visitAddMulMod(FunctionCall const& _funCall) { auto const& funType = dynamic_cast(*_funCall.expression().annotation().type); @@ -1387,14 +1404,14 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) return true; } - Expression const* memberExpr = innermostTuple(_memberAccess.expression()); + Expression const& memberExpr = innermostTuple(_memberAccess.expression()); - auto const& exprType = memberExpr->annotation().type; + auto const& exprType = memberExpr.annotation().type; solAssert(exprType, ""); if (exprType->category() == Type::Category::Magic) { - if (auto const* identifier = dynamic_cast(memberExpr)) + if (auto const* identifier = dynamic_cast(&memberExpr)) { auto const& name = identifier->name(); solAssert(name == "block" || name == "msg" || name == "tx", ""); @@ -1447,14 +1464,14 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) } else if (smt::isNonRecursiveStruct(*exprType)) { - memberExpr->accept(*this); - auto const& symbStruct = std::dynamic_pointer_cast(m_context.expression(*memberExpr)); + memberExpr.accept(*this); + auto const& symbStruct = std::dynamic_pointer_cast(m_context.expression(memberExpr)); defineExpr(_memberAccess, symbStruct->member(_memberAccess.memberName())); return false; } else if (exprType->category() == Type::Category::TypeType) { - auto const* decl = expressionToDeclaration(*memberExpr); + auto const* decl = expressionToDeclaration(memberExpr); if (dynamic_cast(decl)) { auto enumType = dynamic_cast(accessType); @@ -1477,10 +1494,10 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) } else if (exprType->category() == Type::Category::Address) { - memberExpr->accept(*this); + memberExpr.accept(*this); if (_memberAccess.memberName() == "balance") { - defineExpr(_memberAccess, state().balance(expr(*memberExpr))); + defineExpr(_memberAccess, state().balance(expr(memberExpr))); setSymbolicUnknownValue(*m_context.expression(_memberAccess), m_context); m_uninterpretedTerms.insert(&_memberAccess); return false; @@ -1488,10 +1505,10 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) } else if (exprType->category() == Type::Category::Array) { - memberExpr->accept(*this); + memberExpr.accept(*this); if (_memberAccess.memberName() == "length") { - auto symbArray = std::dynamic_pointer_cast(m_context.expression(*memberExpr)); + auto symbArray = std::dynamic_pointer_cast(m_context.expression(memberExpr)); solAssert(symbArray, ""); defineExpr(_memberAccess, symbArray->length()); m_uninterpretedTerms.insert(&_memberAccess); @@ -2163,16 +2180,16 @@ void SMTEncoder::assignment( void SMTEncoder::tupleAssignment(Expression const& _left, Expression const& _right) { - auto lTuple = dynamic_cast(innermostTuple(_left)); + auto lTuple = dynamic_cast(&innermostTuple(_left)); solAssert(lTuple, ""); - Expression const* right = innermostTuple(_right); + Expression const& right = innermostTuple(_right); auto const& lComponents = lTuple->components(); // If both sides are tuple expressions, we individually and potentially // recursively assign each pair of components. // This is because of potential type conversion. - if (auto rTuple = dynamic_cast(right)) + if (auto rTuple = dynamic_cast(&right)) { auto const& rComponents = rTuple->components(); solAssert(lComponents.size() == rComponents.size(), ""); @@ -2193,13 +2210,13 @@ void SMTEncoder::tupleAssignment(Expression const& _left, Expression const& _rig } else { - auto rType = dynamic_cast(right->annotation().type); + auto rType = dynamic_cast(right.annotation().type); solAssert(rType, ""); auto const& rComponents = rType->components(); solAssert(lComponents.size() == rComponents.size(), ""); - auto symbRight = expr(*right); + auto symbRight = expr(right); solAssert(symbRight.sort->kind == smtutil::Kind::Tuple, ""); for (unsigned i = 0; i < lComponents.size(); ++i) @@ -2726,11 +2743,11 @@ Type const* SMTEncoder::keyType(Type const* _type) solAssert(false, ""); } -Expression const* SMTEncoder::innermostTuple(Expression const& _expr) +Expression const& SMTEncoder::innermostTuple(Expression const& _expr) { auto const* tuple = dynamic_cast(&_expr); if (!tuple || tuple->isInlineArray()) - return &_expr; + return _expr; Expression const* expr = tuple; while (tuple && !tuple->isInlineArray() && tuple->components().size() == 1) @@ -2739,7 +2756,7 @@ Expression const* SMTEncoder::innermostTuple(Expression const& _expr) tuple = dynamic_cast(expr); } solAssert(expr, ""); - return expr; + return *expr; } Type const* SMTEncoder::underlyingType(Type const* _type) @@ -2760,7 +2777,7 @@ TypePointers SMTEncoder::replaceUserTypes(TypePointers const& _types) std::pair SMTEncoder::functionCallExpression(FunctionCall const& _funCall) { - Expression const* callExpr = &_funCall.expression(); + Expression const* callExpr = &innermostTuple(_funCall.expression()); auto const* callOptions = dynamic_cast(callExpr); if (callOptions) callExpr = &callOptions->expression(); @@ -2772,7 +2789,7 @@ Expression const* SMTEncoder::cleanExpression(Expression const& _expr) { auto const* expr = &_expr; if (auto const* tuple = dynamic_cast(expr)) - return cleanExpression(*innermostTuple(*tuple)); + return cleanExpression(innermostTuple(*tuple)); if (auto const* functionCall = dynamic_cast(expr)) if (*functionCall->annotation().kind == FunctionCallKind::TypeConversion) { @@ -2858,7 +2875,7 @@ smtutil::Expression SMTEncoder::contractAddressValue(FunctionCall const& _f) auto [funExpr, funOptions] = functionCallExpression(_f); if (MemberAccess const* callBase = dynamic_cast(funExpr)) return expr(callBase->expression()); - solAssert(false, "Unreachable!"); + smtAssert(false, "Unexpected function call type encountered while getting contract address!"); } VariableDeclaration const* SMTEncoder::publicGetter(Expression const& _expr) const { @@ -2907,7 +2924,7 @@ FunctionDefinition const* SMTEncoder::functionCallToDefinition( if (TupleExpression const* fun = dynamic_cast(calledExpr)) { solAssert(fun->components().size() == 1, ""); - calledExpr = innermostTuple(*calledExpr); + calledExpr = &innermostTuple(*calledExpr); } auto resolveVirtual = [&](auto const* _ref) -> FunctionDefinition const* { @@ -3113,13 +3130,8 @@ RationalNumberType const* SMTEncoder::isConstant(Expression const& _expr) if (auto type = dynamic_cast(_expr.annotation().type)) return type; - // _expr may not be constant evaluable. - // In that case we ignore any warnings emitted by the constant evaluator, - // as it will return nullptr in case of failure. - ErrorList l; - ErrorReporter e(l); - if (auto t = ConstantEvaluator::evaluate(e, _expr)) - return TypeProvider::rationalNumber(t->value); + if (auto typedRational = ConstantEvaluator::tryEvaluate(_expr)) + return TypeProvider::rationalNumber(typedRational->value); return nullptr; } @@ -3209,8 +3221,8 @@ std::vector SMTEncoder::symbolicArguments( unsigned firstParam = 0; if (_boundArgumentCall) { - Expression const* calledExpr = innermostTuple(*_boundArgumentCall.value()); - auto const& attachedFunction = dynamic_cast(calledExpr); + Expression const& calledExpr = innermostTuple(*_boundArgumentCall.value()); + auto const& attachedFunction = dynamic_cast(&calledExpr); solAssert(attachedFunction, ""); args.push_back(expr(attachedFunction->expression(), _funParameters.front()->type())); firstParam = 1; @@ -3275,6 +3287,14 @@ void SMTEncoder::createFreeConstants(std::set const& _sources) +{ + for (auto const& source: _sources) + for (auto const& node: source->nodes()) + if (auto contract = dynamic_cast(node.get())) + createStateVariables(*contract); +} + smt::SymbolicState& SMTEncoder::state() { return m_context.state(); diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index 3248f1390f64..f926a0d0fc80 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -71,7 +71,7 @@ class SMTEncoder: public ASTConstVisitor /// @returns the innermost element in a chain of 1-tuples if applicable, /// otherwise _expr. - static Expression const* innermostTuple(Expression const& _expr); + static Expression const& innermostTuple(Expression const& _expr); /// @returns the underlying type if _type is UserDefinedValueType, /// and _type otherwise. @@ -229,6 +229,7 @@ class SMTEncoder: public ASTConstVisitor void visitBytesConcat(FunctionCall const& _funCall); void visitCryptoFunction(FunctionCall const& _funCall); void visitGasLeft(FunctionCall const& _funCall); + void visitBlobHash(FunctionCall const& _funCall); virtual void visitAddMulMod(FunctionCall const& _funCall); void visitWrapUnwrap(FunctionCall const& _funCall); void visitObjectCreation(FunctionCall const& _funCall); @@ -439,6 +440,9 @@ class SMTEncoder: public ASTConstVisitor /// Create symbolic variables for the free constants in all @param _sources. void createFreeConstants(std::set const& _sources); + /// Create symbolic variables for all state variables for all contracts in all @param _sources. + void createStateVariables(std::set const& _sources); + /// @returns a note to be added to warnings. std::string extraComment(); @@ -504,7 +508,7 @@ class SMTEncoder: public ASTConstVisitor ContractDefinition const* m_currentContract = nullptr; /// Stores the free functions and internal library functions. - /// Those need to be encoded repeatedely for every analyzed contract. + /// Those need to be encoded repeatedly for every analyzed contract. std::set m_freeFunctions; /// Stores the context of the encoding. diff --git a/libsolidity/formal/SymbolicState.cpp b/libsolidity/formal/SymbolicState.cpp index bf835b801d21..492e0055b008 100644 --- a/libsolidity/formal/SymbolicState.cpp +++ b/libsolidity/formal/SymbolicState.cpp @@ -96,6 +96,11 @@ smtutil::Expression SymbolicState::balance(smtutil::Expression _address) const return smtutil::Expression::select(balances(), std::move(_address)); } +smtutil::Expression SymbolicState::blobhash(smtutil::Expression _blobIndex) const +{ + return smtutil::Expression::select(m_tx.member("blobhash"), std::move(_blobIndex)); +} + smtutil::Expression SymbolicState::blockhash(smtutil::Expression _blockNumber) const { return smtutil::Expression::select(m_tx.member("blockhash"), std::move(_blockNumber)); @@ -222,6 +227,7 @@ smtutil::Expression SymbolicState::txTypeConstraints() const return evmParisConstraints() && smt::symbolicUnknownConstraints(m_tx.member("block.basefee"), TypeProvider::uint256()) && + smt::symbolicUnknownConstraints(m_tx.member("block.blobbasefee"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.chainid"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.coinbase"), TypeProvider::address()) && smt::symbolicUnknownConstraints(m_tx.member("block.prevrandao"), TypeProvider::uint256()) && diff --git a/libsolidity/formal/SymbolicState.h b/libsolidity/formal/SymbolicState.h index ac018df1acf8..ca40e695d521 100644 --- a/libsolidity/formal/SymbolicState.h +++ b/libsolidity/formal/SymbolicState.h @@ -65,8 +65,10 @@ class BlockchainVariable * - array of address => bool representing whether an address is used by a contract * - storage of contracts * - block and transaction properties, represented as a tuple of: + * - blobhash * - blockhash * - block basefee + * - block blobbasefee * - block chainid * - block coinbase * - block gaslimit @@ -148,6 +150,7 @@ class SymbolicState smtutil::Expression txFunctionConstraints(FunctionDefinition const& _function) const; smtutil::Expression txTypeConstraints() const; smtutil::Expression txNonPayableConstraint() const; + smtutil::Expression blobhash(smtutil::Expression _blobIndex) const; smtutil::Expression blockhash(smtutil::Expression _blockNumber) const; smtutil::Expression evmParisConstraints() const; //@} @@ -236,27 +239,7 @@ class SymbolicState /// and the element is a tuple containing the state variables of that contract. std::unique_ptr m_state; - BlockchainVariable m_tx{ - "tx", - { - {"block.basefee", smtutil::SortProvider::uintSort}, - {"block.chainid", smtutil::SortProvider::uintSort}, - {"block.coinbase", smt::smtSort(*TypeProvider::address())}, - {"block.prevrandao", smtutil::SortProvider::uintSort}, - {"block.gaslimit", smtutil::SortProvider::uintSort}, - {"block.number", smtutil::SortProvider::uintSort}, - {"block.timestamp", smtutil::SortProvider::uintSort}, - {"blockhash", std::make_shared(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort)}, - // TODO gasleft - {"msg.data", smt::smtSort(*TypeProvider::bytesMemory())}, - {"msg.sender", smt::smtSort(*TypeProvider::address())}, - {"msg.sig", smtutil::SortProvider::uintSort}, - {"msg.value", smtutil::SortProvider::uintSort}, - {"tx.gasprice", smtutil::SortProvider::uintSort}, - {"tx.origin", smt::smtSort(*TypeProvider::address())} - }, - m_context - }; + BlockchainVariable m_tx{"tx", transactionMemberSorts(), m_context}; BlockchainVariable m_crypto{ "crypto", diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index f9ec9b0110ed..738a48f706c3 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -29,6 +29,20 @@ using namespace solidity::util; using namespace solidity::smtutil; + +namespace +{ + // HACK to get around Z3 bug in printing type names with spaces (https://github.com/Z3Prover/z3/issues/6850) + // Should be fixed in Z3 4.13.0 + // TODO: Remove this afterwards + void sanitizeTypeName(std::string& name) + { + std::replace(name.begin(), name.end(), ' ', '_'); + std::replace(name.begin(), name.end(), '(', '['); + std::replace(name.begin(), name.end(), ')', ']'); + } +} + namespace solidity::frontend::smt { @@ -112,15 +126,15 @@ SortPointer smtSort(frontend::Type const& _type) tupleName = tupleSort->name; else if (isContract(*baseType)) // use a common sort for contracts so inheriting contracts do not cause conflicting SMT types - // solc handles types mismtach + // solc handles types mismatch tupleName = "contract"; else if (isFunction(*baseType)) // use a common sort for functions so pure and view modifier do not cause conflicting SMT types - // solc handles types mismtach + // solc handles types mismatch tupleName = "function"; else if (isAddress(*baseType)) // use a common sort for address and address payable so it does not cause conflicting SMT types - // solc handles types mismtach + // solc handles types mismatch tupleName = "address"; else if ( baseType->category() == frontend::Type::Category::Integer || @@ -137,6 +151,7 @@ SortPointer smtSort(frontend::Type const& _type) else tupleName = _type.toString(true); + sanitizeTypeName(tupleName); tupleName += "_tuple"; return std::make_shared( @@ -148,7 +163,8 @@ SortPointer smtSort(frontend::Type const& _type) case Kind::Tuple: { std::vector members; - auto const& tupleName = _type.toString(true); + auto tupleName = _type.toString(true); + sanitizeTypeName(tupleName); std::vector sorts; if (auto const* tupleType = dynamic_cast(&_type)) @@ -651,4 +667,41 @@ smtutil::Expression assignMember(smtutil::Expression const _tuple, std::map transactionMemberTypes() +{ + // TODO: gasleft + return { + {"block.basefee", TypeProvider::uint256()}, + {"block.blobbasefee", TypeProvider::uint256()}, + {"block.chainid", TypeProvider::uint256()}, + {"block.coinbase", TypeProvider::address()}, + {"block.prevrandao", TypeProvider::uint256()}, + {"block.gaslimit", TypeProvider::uint256()}, + {"block.number", TypeProvider::uint256()}, + {"block.timestamp", TypeProvider::uint256()}, + {"blobhash", TypeProvider::array(DataLocation::Memory, TypeProvider::uint256())}, + {"blockhash", TypeProvider::array(DataLocation::Memory, TypeProvider::uint256())}, + {"msg.data", TypeProvider::bytesCalldata()}, + {"msg.sender", TypeProvider::address()}, + {"msg.sig", TypeProvider::fixedBytes(4)}, + {"msg.value", TypeProvider::uint256()}, + {"tx.gasprice", TypeProvider::uint256()}, + {"tx.origin", TypeProvider::address()} + }; +} + +std::map transactionMemberSorts() +{ + // NOTE: `blockhash` and `blobhash` need proper `ArraySort`, `smtSort()` wraps array types into array+length pair + auto toSort = [&](auto const& entry) -> SortPointer + { + if (entry.first == "blockhash" || entry.first == "blobhash") + return std::make_shared(SortProvider::uintSort, SortProvider::uintSort); + return smtSort(*entry.second); + }; + auto types = transactionMemberTypes(); + return types + | ranges::views::transform([&](auto const& entry) { return std::make_pair(entry.first, toSort(entry)); }) + | ranges::to>(); +} } diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index 747e27b7e372..d38dcc04514a 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -86,4 +86,6 @@ std::optional symbolicTypeConversion(frontend::Type const* smtutil::Expression member(smtutil::Expression const& _tuple, std::string const& _member); smtutil::Expression assignMember(smtutil::Expression const _tuple, std::map const& _values); +std::map transactionMemberTypes(); +std::map transactionMemberSorts(); } diff --git a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp index d8448fc0beca..2ceecfcf9088 100644 --- a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp +++ b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp @@ -26,6 +26,10 @@ #include +#ifdef EMSCRIPTEN_BUILD +#include +#endif + using namespace solidity::frontend::smt; using namespace solidity::smtutil; @@ -35,6 +39,17 @@ Z3CHCSmtLib2Interface::Z3CHCSmtLib2Interface( bool _computeInvariants ): CHCSmtLib2Interface({}, std::move(_smtCallback), _queryTimeout), m_computeInvariants(_computeInvariants) { +#ifdef EMSCRIPTEN_BUILD + constexpr int resourceLimit = 2000000; + if (m_queryTimeout) + z3::set_param("timeout", int(*m_queryTimeout)); + else + z3::set_param("rlimit", resourceLimit); + z3::set_param("rewriter.pull_cheap_ite", true); + z3::set_param("fp.spacer.q3.use_qgen", true); + z3::set_param("fp.spacer.mbqi", false); + z3::set_param("fp.spacer.ground_pobs", false); +#endif } void Z3CHCSmtLib2Interface::setupSmtCallback(bool _enablePreprocessing) @@ -47,34 +62,55 @@ CHCSolverInterface::QueryResult Z3CHCSmtLib2Interface::query(smtutil::Expression { setupSmtCallback(true); std::string query = dumpQuery(_block); - std::string response = querySolver(query); - // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking - // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. - // So we have to flip the answer. - if (boost::starts_with(response, "unsat")) + try { - // Repeat the query with preprocessing disabled, to get the full proof - setupSmtCallback(false); - query = "(set-option :produce-proofs true)" + query + "\n(get-proof)"; - response = querySolver(query); - setupSmtCallback(true); - if (!boost::starts_with(response, "unsat")) - return {CheckResult::SATISFIABLE, Expression(true), {}}; - return {CheckResult::SATISFIABLE, Expression(true), graphFromZ3Answer(response)}; - } +#ifdef EMSCRIPTEN_BUILD + z3::set_param("fp.xform.slice", true); + z3::set_param("fp.xform.inline_linear", true); + z3::set_param("fp.xform.inline_eager", true); + std::string response = Z3_eval_smtlib2_string(z3::context{}, query.c_str()); +#else + std::string response = querySolver(query); +#endif + // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking + // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. + // So we have to flip the answer. + if (boost::starts_with(response, "unsat")) + { + // Repeat the query with preprocessing disabled, to get the full proof + setupSmtCallback(false); + query = "(set-option :produce-proofs true)" + query + "\n(get-proof)"; +#ifdef EMSCRIPTEN_BUILD + z3::set_param("fp.xform.slice", false); + z3::set_param("fp.xform.inline_linear", false); + z3::set_param("fp.xform.inline_eager", false); + response = Z3_eval_smtlib2_string(z3::context{}, query.c_str()); +#else + response = querySolver(query); +#endif + setupSmtCallback(true); + if (!boost::starts_with(response, "unsat")) + return {CheckResult::SATISFIABLE, Expression(true), {}}; + return {CheckResult::SATISFIABLE, Expression(true), graphFromZ3Answer(response)}; + } - CheckResult result; - if (boost::starts_with(response, "sat")) + CheckResult result; + if (boost::starts_with(response, "sat")) + { + auto maybeInvariants = invariantsFromSolverResponse(response); + return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + } + else if (boost::starts_with(response, "unknown")) + result = CheckResult::UNKNOWN; + else + result = CheckResult::ERROR; + + return {result, Expression(true), {}}; + } + catch(smtutil::SMTSolverInteractionError const&) { - auto maybeInvariants = invariantsFromSolverResponse(response); - return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + return {CheckResult::ERROR, Expression(true), {}}; } - else if (boost::starts_with(response, "unknown")) - result = CheckResult::UNKNOWN; - else - result = CheckResult::ERROR; - - return {result, Expression(true), {}}; } @@ -83,7 +119,7 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::strin std::stringstream ss(_proof); std::string answer; ss >> answer; - smtAssert(answer == "unsat"); + smtSolverInteractionRequire(answer == "unsat", "Proof must follow an unsat answer"); SMTLib2Parser parser(ss); if (parser.isEOF()) // No proof from Z3 @@ -96,10 +132,10 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::strin } catch (SMTLib2Parser::ParsingException&) { - return {}; + smtSolverInteractionRequire(false, "Error during parsing Z3's proof"); } - solAssert(parser.isEOF()); - solAssert(!isAtom(parsedOutput)); + smtSolverInteractionRequire(parser.isEOF(), "Error during parsing Z3's proof"); + smtSolverInteractionRequire(!isAtom(parsedOutput), "Encountered unexpected format of Z3's proof"); auto& commands = asSubExpressions(parsedOutput); ScopedParser expressionParser(m_context); for (auto& command: commands) @@ -108,7 +144,7 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::strin continue; auto const& args = asSubExpressions(command); - solAssert(args.size() > 0); + smtSolverInteractionRequire(args.size() > 0, "Encountered unexpected format of Z3's proof"); auto const& head = args[0]; if (!isAtom(head)) continue; @@ -117,12 +153,12 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::strin // e.g., "(declare-fun query!0 (Bool Bool Bool Int Int Bool Bool Bool Bool Bool Bool Bool Int) Bool)" if (asAtom(head) == "declare-fun") { - solAssert(args.size() == 4); + smtSolverInteractionRequire(args.size() == 4, "Encountered unexpected format of Z3's proof"); auto const& name = args[1]; auto const& domainSorts = args[2]; auto const& codomainSort = args[3]; - solAssert(isAtom(name)); - solAssert(!isAtom(domainSorts)); + smtSolverInteractionRequire(isAtom(name), "Encountered unexpected format of Z3's proof"); + smtSolverInteractionRequire(!isAtom(domainSorts), "Encountered unexpected format of Z3's proof"); expressionParser.addVariableDeclaration(asAtom(name), expressionParser.toSort(codomainSort)); } // The subexpression starting with "proof" contains the whole proof, which we need to transform to our internal @@ -144,13 +180,13 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromSMTLib2Expression( auto fact = [](SMTLib2Expression const& _node) -> SMTLib2Expression const& { if (isAtom(_node)) return _node; - smtAssert(!asSubExpressions(_node).empty()); + smtSolverInteractionRequire(!asSubExpressions(_node).empty(), "Encountered unexpected format of Z3's proof"); return asSubExpressions(_node).back(); }; - smtAssert(!isAtom(_proof)); + smtSolverInteractionRequire(!isAtom(_proof), "Encountered unexpected format of Z3's proof"); auto const& proofArgs = asSubExpressions(_proof); - smtAssert(proofArgs.size() == 2); - smtAssert(isAtom(proofArgs.at(0)) && asAtom(proofArgs.at(0)) == "proof"); + smtSolverInteractionRequire(proofArgs.size() == 2, "Encountered unexpected format of Z3's proof"); + smtSolverInteractionRequire(isAtom(proofArgs.at(0)) && asAtom(proofArgs.at(0)) == "proof", "Encountered unexpected format of Z3's proof"); auto const& proofNode = proofArgs.at(1); auto const& derivedFact = fact(proofNode); if (isAtom(proofNode) || !isAtom(derivedFact) || asAtom(derivedFact) != "false") @@ -172,7 +208,7 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromSMTLib2Expression( auto isHyperRes = [](SMTLib2Expression const& expr) { if (isAtom(expr)) return false; auto const& subExprs = asSubExpressions(expr); - smtAssert(!subExprs.empty()); + smtSolverInteractionRequire(!subExprs.empty(), "Encountered unexpected format of Z3's proof"); auto const& op = subExprs.at(0); if (isAtom(op)) return false; auto const& opExprs = asSubExpressions(op); @@ -184,15 +220,15 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromSMTLib2Expression( while (!proofStack.empty()) { auto const* currentNode = proofStack.top(); - smtAssert(visitedIds.find(currentNode) != visitedIds.end()); + smtSolverInteractionRequire(visitedIds.find(currentNode) != visitedIds.end(), "Error in processing Z3's proof"); auto id = visitedIds.at(currentNode); - smtAssert(graph.nodes.count(id)); + smtSolverInteractionRequire(graph.nodes.count(id), "Error in processing Z3's proof"); proofStack.pop(); if (isHyperRes(*currentNode)) { auto const& args = asSubExpressions(*currentNode); - smtAssert(args.size() > 1); + smtSolverInteractionRequire(args.size() > 1, "Unexpected format of hyper-resolution rule in Z3's proof"); // args[0] is the name of the rule // args[1] is the clause used // last argument is the derived fact diff --git a/libsolidity/formal/Z3SMTLib2Interface.cpp b/libsolidity/formal/Z3SMTLib2Interface.cpp index b76cdd252281..2ecb8cbcc45c 100644 --- a/libsolidity/formal/Z3SMTLib2Interface.cpp +++ b/libsolidity/formal/Z3SMTLib2Interface.cpp @@ -20,6 +20,10 @@ #include +#ifdef EMSCRIPTEN_BUILD +#include +#endif + using namespace solidity::frontend::smt; Z3SMTLib2Interface::Z3SMTLib2Interface( @@ -27,9 +31,30 @@ Z3SMTLib2Interface::Z3SMTLib2Interface( std::optional _queryTimeout ): SMTLib2Interface({}, std::move(_smtCallback), _queryTimeout) { +#ifdef EMSCRIPTEN_BUILD + constexpr int resourceLimit = 2000000; + if (m_queryTimeout) + z3::set_param("timeout", int(*m_queryTimeout)); + else + z3::set_param("rlimit", resourceLimit); + z3::set_param("rewriter.pull_cheap_ite", true); + z3::set_param("fp.spacer.q3.use_qgen", true); + z3::set_param("fp.spacer.mbqi", false); + z3::set_param("fp.spacer.ground_pobs", false); +#endif } void Z3SMTLib2Interface::setupSmtCallback() { if (auto* universalCallback = m_smtCallback.target()) universalCallback->smtCommand().setZ3(m_queryTimeout, true, false); } + +std::string Z3SMTLib2Interface::querySolver(std::string const& _query) +{ +#ifdef EMSCRIPTEN_BUILD + z3::context context; + return Z3_eval_smtlib2_string(context, _query.c_str()); +#else + return SMTLib2Interface::querySolver(_query); +#endif +} diff --git a/libsolidity/formal/Z3SMTLib2Interface.h b/libsolidity/formal/Z3SMTLib2Interface.h index 07e138710624..7ab087bbdb99 100644 --- a/libsolidity/formal/Z3SMTLib2Interface.h +++ b/libsolidity/formal/Z3SMTLib2Interface.h @@ -32,6 +32,7 @@ class Z3SMTLib2Interface: public smtutil::SMTLib2Interface ); private: void setupSmtCallback() override; + std::string querySolver(std::string const& _query) override; }; } diff --git a/libsolidity/interface/ABI.h b/libsolidity/interface/ABI.h index 22e306c4322b..65f130247147 100644 --- a/libsolidity/interface/ABI.h +++ b/libsolidity/interface/ABI.h @@ -37,7 +37,7 @@ class ABI public: /// Get the ABI Interface of the contract /// @param _contractDef The contract definition - /// @return A JSONrepresentation of the contract's ABI Interface + /// @return A JSON representation of the contract's ABI Interface static Json generate(ContractDefinition const& _contractDef); private: /// @returns a json value suitable for a list of types in function input or output diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 784a2b395e3a..43303de5eb83 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -78,13 +78,14 @@ #include #include - #include #include #include #include #include +#include + #include #include @@ -419,6 +420,7 @@ bool CompilerStack::parse() catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); + return false; } return true; @@ -506,9 +508,14 @@ bool CompilerStack::analyze() else if (!analyzeLegacy(noErrors)) noErrors = false; } - catch (FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } noErrors = false; } catch (UnimplementedFeatureError const& _error) @@ -557,7 +564,7 @@ bool CompilerStack::analyzeLegacy(bool _noErrorsSoFar) // // Note: this does not resolve overloaded functions. In order to do that, types of arguments are needed, // which is only done one step later. - TypeChecker typeChecker(m_evmVersion, m_errorReporter); + TypeChecker typeChecker(m_evmVersion, m_eofVersion, m_errorReporter); for (Source const* source: m_sourceOrder) if (source->ast && !typeChecker.checkTypeRequirements(*source->ast)) noErrors = false; @@ -778,19 +785,18 @@ bool CompilerStack::compile(State _stopAfter) } catch (Error const& _error) { - // Since codegen has no access to the error reporter, the only way for it to - // report an error is to throw. In most cases it uses dedicated exceptions, - // but CodeGenerationError is one case where someone decided to just throw Error. - solAssert(_error.type() == Error::Type::CodeGenerationError); - m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); - return false; + reportCodeGenerationError(_error, contract); } catch (UnimplementedFeatureError const& _error) { - reportUnimplementedFeatureError(_error); - return false; + reportUnimplementedFeatureError(_error, contract); } + + if (m_errorReporter.hasErrors()) + return false; } + + solAssert(!m_errorReporter.hasErrors()); m_stackState = CompilationSuccessful; this->link(); return true; @@ -822,7 +828,12 @@ YulStack CompilerStack::loadGeneratedIR(std::string const& _ir) const yulAnalysisSuccessful, _ir + "\n\n" "Invalid IR generated:\n" + - SourceReferenceFormatter::formatErrorInformation(stack.errors(), stack) + "\n" + SourceReferenceFormatter::formatErrorInformation( + stack.errors(), + stack, // _charStreamProvider + false, // _colored + true // _withErrorIds + ) + "\n" ); return stack; @@ -900,7 +911,7 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, m_eofVersion); std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); solAssert(parserResult); - sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(parserResult->root()); + sources[0]["ast"] = yul::AsmJsonConverter{dialect, sourceIndex}(parserResult->root()); sources[0]["name"] = sourceName; sources[0]["id"] = sourceIndex; sources[0]["language"] = "Yul"; @@ -969,46 +980,61 @@ std::string const CompilerStack::filesystemFriendlyName(std::string const& _cont return matchContract.contract->name(); } -std::string const& CompilerStack::yulIR(std::string const& _contractName) const +std::optional const& CompilerStack::yulIR(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); return contract(_contractName).yulIR; } -Json CompilerStack::yulIRAst(std::string const& _contractName) const +std::optional CompilerStack::yulIRAst(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - return loadGeneratedIR(contract(_contractName).yulIR).astJson(); + Contract const& currentContract = contract(_contractName); + yulAssert(currentContract.contract); + yulAssert(currentContract.yulIR.has_value() == currentContract.contract->canBeDeployed()); + if (!currentContract.yulIR) + return std::nullopt; + return loadGeneratedIR(*currentContract.yulIR).astJson(); } -Json CompilerStack::yulCFGJson(std::string const& _contractName) const +std::optional CompilerStack::yulCFGJson(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - return loadGeneratedIR(contract(_contractName).yulIR).cfgJson(); + Contract const& currentContract = contract(_contractName); + yulAssert(currentContract.contract); + yulAssert(currentContract.yulIROptimized.has_value() == currentContract.contract->canBeDeployed()); + if (!currentContract.yulIROptimized) + return std::nullopt; + return loadGeneratedIR(*currentContract.yulIROptimized).cfgJson(); } -std::string const& CompilerStack::yulIROptimized(std::string const& _contractName) const +std::optional const& CompilerStack::yulIROptimized(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); return contract(_contractName).yulIROptimized; } -Json CompilerStack::yulIROptimizedAst(std::string const& _contractName) const +std::optional CompilerStack::yulIROptimizedAst(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - return loadGeneratedIR(contract(_contractName).yulIROptimized).astJson(); + Contract const& currentContract = contract(_contractName); + yulAssert(currentContract.contract); + yulAssert(currentContract.yulIROptimized.has_value() == currentContract.contract->canBeDeployed()); + if (!currentContract.yulIROptimized) + return std::nullopt; + return loadGeneratedIR(*currentContract.yulIROptimized).astJson(); } evmasm::LinkerObject const& CompilerStack::object(std::string const& _contractName) const @@ -1166,6 +1192,34 @@ Json CompilerStack::interfaceSymbols(std::string const& _contractName) const return interfaceSymbols; } +Json CompilerStack::ethdebug() const +{ + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(!m_contracts.empty()); + return evmasm::ethdebug::resources(sourceNames(), VersionString); +} + +Json CompilerStack::ethdebug(std::string const& _contractName) const +{ + return ethdebug(contract(_contractName), /* runtime */ false); +} + +Json CompilerStack::ethdebugRuntime(std::string const& _contractName) const +{ + return ethdebug(contract(_contractName), /* runtime */ true); +} + +Json CompilerStack::ethdebug(Contract const& _contract, bool _runtime) const +{ + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); + solUnimplementedAssert(!isExperimentalSolidity()); + evmasm::LinkerObject const& object = _runtime ? _contract.runtimeObject : _contract.object; + std::shared_ptr const& assembly = _runtime ? _contract.evmRuntimeAssembly : _contract.evmAssembly; + solAssert(sourceIndices().contains(_contract.contract->sourceUnitName())); + return evmasm::ethdebug::program(_contract.contract->name(), sourceIndices()[_contract.contract->sourceUnitName()], assembly.get(), object); +} + bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR) const { solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); @@ -1268,9 +1322,14 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast) } } } - catch (FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } } return newSources; } @@ -1487,7 +1546,12 @@ void CompilerStack::compileContract( Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); - std::shared_ptr compiler = std::make_shared(m_evmVersion, m_revertStrings, m_optimiserSettings); + std::shared_ptr compiler = std::make_shared( + m_evmVersion, + m_eofVersion, + m_revertStrings, + m_optimiserSettings + ); solAssert(!m_viaIR, ""); bytes cborEncodedMetadata = createCBORMetadata(compiledContract, /* _forIR */ false); @@ -1505,10 +1569,12 @@ void CompilerStack::compileContract( void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unoptimizedOnly) { solAssert(m_stackState >= AnalysisSuccessful, ""); - Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); - if (!compiledContract.yulIR.empty()) + if (compiledContract.yulIR) + { + solAssert(!compiledContract.yulIR->empty()); return; + } if (!*_contract.sourceUnit().annotation().useABICoderV2) m_errorReporter.warning( @@ -1527,7 +1593,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti std::map otherYulSources; for (auto const& pair: m_contracts) - otherYulSources.emplace(pair.second.contract, pair.second.yulIR); + otherYulSources.emplace(pair.second.contract, pair.second.yulIR ? *pair.second.yulIR : std::string_view{}); if (m_experimentalAnalysis) { @@ -1564,7 +1630,8 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti ); } - YulStack stack = loadGeneratedIR(compiledContract.yulIR); + yulAssert(compiledContract.yulIR); + YulStack stack = loadGeneratedIR(*compiledContract.yulIR); if (!_unoptimizedOnly) { stack.optimize(); @@ -1580,18 +1647,25 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) return; Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); - solAssert(!compiledContract.yulIROptimized.empty(), ""); + solAssert(compiledContract.yulIROptimized); + solAssert(!compiledContract.yulIROptimized->empty()); if (!compiledContract.object.bytecode.empty()) return; // Re-parse the Yul IR in EVM dialect - YulStack stack = loadGeneratedIR(compiledContract.yulIROptimized); - - //cout << yul::AsmPrinter{}(*stack.parserResult()->code) << endl; + YulStack stack = loadGeneratedIR(*compiledContract.yulIROptimized); std::string deployedName = IRNames::deployedObject(_contract); solAssert(!deployedName.empty(), ""); tie(compiledContract.evmAssembly, compiledContract.evmRuntimeAssembly) = stack.assembleEVMWithDeployed(deployedName); + + if (stack.hasErrors()) + { + for (std::shared_ptr const& error: stack.errors()) + reportIRPostAnalysisError(error.get(), compiledContract.contract); + return; + } + assembleYul(_contract, compiledContract.evmAssembly, compiledContract.evmRuntimeAssembly); } @@ -1984,8 +2058,58 @@ experimental::Analysis const& CompilerStack::experimentalAnalysis() const return *m_experimentalAnalysis; } -void CompilerStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) +void CompilerStack::reportUnimplementedFeatureError( + UnimplementedFeatureError const& _error, + ContractDefinition const* _contractDefinition +) { - solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); - m_errorReporter.unimplementedFeatureError(1834_error, _error.sourceLocation(), *_error.comment()); + solAssert(_error.comment(), "Errors must include a message for the user."); + if (_error.sourceLocation().sourceName) + solAssert(m_sources.count(*_error.sourceLocation().sourceName) != 0); + + m_errorReporter.unimplementedFeatureError( + 1834_error, + (_error.sourceLocation().sourceName || !_contractDefinition) ? + _error.sourceLocation() : + _contractDefinition->location(), + *_error.comment() + ); +} + +void CompilerStack::reportCodeGenerationError(Error const& _error, ContractDefinition const* _contractDefinition) +{ + solAssert(_error.type() == Error::Type::CodeGenerationError); + solAssert(_error.comment(), "Errors must include a message for the user."); + if (_error.sourceLocation() && _error.sourceLocation()->sourceName) + solAssert(m_sources.count(*_error.sourceLocation()->sourceName) != 0); + solAssert(_contractDefinition); + + m_errorReporter.codeGenerationError( + _error.errorId(), + (_error.sourceLocation() && _error.sourceLocation()->sourceName) ? + *_error.sourceLocation() : + _contractDefinition->location(), + *_error.comment() + ); +} + +void CompilerStack::reportIRPostAnalysisError(Error const* _error, ContractDefinition const* _contractDefinition) +{ + solAssert(_error); + solAssert(_error->comment(), "Errors must include a message for the user."); + solAssert(!_error->secondarySourceLocation()); + solAssert(_contractDefinition); + + // Do not report Yul warnings and infos. These are only reported in pure Yul compilation. + if (!Error::isError(_error->severity())) + return; + + m_errorReporter.error( + _error->errorId(), + _error->type(), + // Ignore the original location. It's likely missing, but even if not, it points at Yul source. + // CompilerStack can only point at locations in Solidity sources. + _contractDefinition->location(), + *_error->comment() + ); } diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 8ce2c5d62dfe..2731787a4b88 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -321,18 +321,18 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override; /// @returns the IR representation of a contract. - std::string const& yulIR(std::string const& _contractName) const; + std::optional const& yulIR(std::string const& _contractName) const; /// @returns the IR representation of a contract AST in format. - Json yulIRAst(std::string const& _contractName) const; + std::optional yulIRAst(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract. - std::string const& yulIROptimized(std::string const& _contractName) const; + std::optional const& yulIROptimized(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract AST in JSON format. - Json yulIROptimizedAst(std::string const& _contractName) const; + std::optional yulIROptimizedAst(std::string const& _contractName) const; - Json yulCFGJson(std::string const& _contractName) const; + std::optional yulCFGJson(std::string const& _contractName) const; /// @returns the assembled object for a contract. virtual evmasm::LinkerObject const& object(std::string const& _contractName) const override; @@ -391,6 +391,18 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names. Json interfaceSymbols(std::string const& _contractName) const; + /// @returns a JSON representing the ethdebug data of the specified contract. + /// Prerequisite: Successful call to parse or compile. + Json ethdebug(std::string const& _contractName) const override; + + /// @returns a JSON representing the ethdebug data of the specified contract. + /// Prerequisite: Successful call to parse or compile. + Json ethdebugRuntime(std::string const& _contractName) const override; + + /// @returns a JSON representing the top-level ethdebug data (types, etc.). + /// Prerequisite: Successful call to parse or compile. + Json ethdebug() const override; + /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); } @@ -445,8 +457,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac std::optional runtimeGeneratedYulUtilityCode; ///< Extra Yul utility code that was used when compiling the deployed assembly evmasm::LinkerObject object; ///< Deployment object (includes the runtime sub-object). evmasm::LinkerObject runtimeObject; ///< Runtime object. - std::string yulIR; ///< Yul IR code straight from the code generator. - std::string yulIROptimized; ///< Reparsed and possibly optimized Yul IR code. + std::optional yulIR; ///< Yul IR code straight from the code generator. + std::optional yulIROptimized; ///< Reparsed and possibly optimized Yul IR code. util::LazyInit metadata; ///< The metadata json that will be hashed into the chain. util::LazyInit abi; util::LazyInit storageLayout; @@ -571,6 +583,11 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// This will generate the metadata and store it in the Contract object if it is not present yet. std::string const& metadata(Contract const& _contract) const; + /// @returns the Contract ethdebug data. + /// This will generate the JSON object and store it in the Contract object if it is not present yet. + /// Prerequisite: Successful call to parse or compile. + Json ethdebug(Contract const& _contract, bool _runtime) const; + /// @returns the offset of the entry point of the given function into the list of assembly items /// or zero if it is not found or does not exist. size_t functionEntryPoint( @@ -578,7 +595,12 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac FunctionDefinition const& _function ) const; - void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); + void reportUnimplementedFeatureError( + langutil::UnimplementedFeatureError const& _error, + ContractDefinition const* _contractDefinition = nullptr + ); + void reportCodeGenerationError(langutil::Error const& _error, ContractDefinition const* _contractDefinition); + void reportIRPostAnalysisError(langutil::Error const* _error, ContractDefinition const* _contractDefinition); ReadCallback::Callback m_readFile; OptimiserSettings m_optimiserSettings; diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index fd3fbbc02c45..4313fad7fd66 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -109,7 +109,7 @@ std::set GasEstimator::finestNodesAtLocation( { std::map locations; std::set nodes; - SimpleASTVisitor visitor(std::function(), [&](ASTNode const& _n) + SimpleASTVisitor visitor([](ASTNode const&) { return false; }, [&](ASTNode const& _n) { if (!locations.count(_n.location())) { diff --git a/libsolidity/interface/OptimiserSettings.h b/libsolidity/interface/OptimiserSettings.h index 1ca46ccbc260..d282e139d22a 100644 --- a/libsolidity/interface/OptimiserSettings.h +++ b/libsolidity/interface/OptimiserSettings.h @@ -111,27 +111,8 @@ struct OptimiserSettings util::unreachable(); } - bool operator==(OptimiserSettings const& _other) const - { - return - runOrderLiterals == _other.runOrderLiterals && - runInliner == _other.runInliner && - runJumpdestRemover == _other.runJumpdestRemover && - runPeephole == _other.runPeephole && - runDeduplicate == _other.runDeduplicate && - runCSE == _other.runCSE && - runConstantOptimiser == _other.runConstantOptimiser && - simpleCounterForLoopUncheckedIncrement == _other.simpleCounterForLoopUncheckedIncrement && - optimizeStackAllocation == _other.optimizeStackAllocation && - runYulOptimiser == _other.runYulOptimiser && - yulOptimiserSteps == _other.yulOptimiserSteps && - expectedExecutionsPerDeployment == _other.expectedExecutionsPerDeployment; - } - - bool operator!=(OptimiserSettings const& _other) const - { - return !(*this == _other); - } + bool operator==(OptimiserSettings const& _other) const = default; + bool operator!=(OptimiserSettings const& _other) const = default; /// Move literals to the right of commutative binary operators during code generation. /// This helps exploiting associativity. @@ -149,11 +130,11 @@ struct OptimiserSettings /// Constant optimizer, which tries to find better representations that satisfy the given /// size/cost-trade-off. bool runConstantOptimiser = false; - /// Perform more efficient stack allocation for variables during code generation from Yul to bytecode. + /// Allow unchecked arithmetic when incrementing the counter of certain kinds of 'for' loop bool simpleCounterForLoopUncheckedIncrement = false; - /// Yul optimiser with default settings. Will only run on certain parts of the code for now. + /// Perform more efficient stack allocation for variables during code generation from Yul to bytecode. bool optimizeStackAllocation = false; - /// Allow unchecked arithmetic when incrementing the counter of certain kinds of 'for' loop + /// Yul optimiser with default settings. Will only run on certain parts of the code for now. bool runYulOptimiser = false; /// Sequence of optimisation steps to be performed by Yul optimiser. /// Note that there are some hard-coded steps in the optimiser and you cannot disable diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index d8ce4f2d0c7a..d5502228bda4 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -131,7 +132,7 @@ Json formatErrorWithException( ); if (std::string const* description = _exception.comment()) - message = ((_message.length() > 0) ? (_message + ":") : "") + *description; + message = ((_message.length() > 0) ? (_message + ": ") : "") + *description; else message = _message; @@ -165,7 +166,7 @@ bool hashMatchesContent(std::string const& _hash, std::string const& _content) bool isArtifactRequested(Json const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental) { - static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson"}; + static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson", "ethdebug"}; for (auto const& selectedArtifactJson: _outputSelection) { std::string const& selectedArtifact = selectedArtifactJson.get(); @@ -173,12 +174,20 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _artif _artifact == selectedArtifact || boost::algorithm::starts_with(_artifact, selectedArtifact + ".") ) + { + if (_artifact.find("ethdebug") != std::string::npos) + // only accept exact matches for ethdebug, e.g. evm.bytecode.ethdebug + return selectedArtifact == _artifact; return true; + } else if (selectedArtifact == "*") { // TODO: yulCFGJson is only experimental now, so it should not be matched by "*". if (_artifact == "yulCFGJson") return false; + // TODO: everything ethdebug related is only experimental for now, so it should not be matched by "*". + if (_artifact.find("ethdebug") != std::string::npos) + return false; // "ir", "irOptimized" can only be matched by "*" if activated. if (experimental.count(_artifact) == 0 || _wildcardMatchesExperimental) return true; @@ -237,7 +246,7 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _file, std::vector evmObjectComponents(std::string const& _objectKind) { solAssert(_objectKind == "bytecode" || _objectKind == "deployedBytecode", ""); - std::vector components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences"}; + std::vector components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences", ".ethdebug"}; if (_objectKind == "deployedBytecode") components.push_back(".immutableReferences"); return util::applyMap(components, [&](auto const& _s) { return "evm." + _objectKind + _s; }); @@ -253,7 +262,7 @@ bool isBinaryRequested(Json const& _outputSelection) static std::vector const outputsThatRequireBinaries = std::vector{ "*", "ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson", - "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly" + "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly", "ethdebug" } + evmObjectComponents("bytecode") + evmObjectComponents("deployedBytecode"); for (auto const& fileRequests: _outputSelection) @@ -283,6 +292,21 @@ bool isEvmBytecodeRequested(Json const& _outputSelection) return false; } +/// @returns true if ethdebug was requested. +bool isEthdebugRequested(Json const& _outputSelection) +{ + if (!_outputSelection.is_object()) + return false; + + for (auto const& fileRequests: _outputSelection) + for (auto const& requests: fileRequests) + for (auto const& request: requests) + if (request == "evm.bytecode.ethdebug" || request == "evm.deployedBytecode.ethdebug") + return true; + + return false; +} + /// @returns The set of selected contracts, along with their compiler pipeline configuration, based /// on outputs requested in the JSON. Translates wildcards to the ones understood by CompilerStack. /// Note that as an exception, '*' does not yet match "ir", "irAst", "irOptimized" or "irOptimizedAst". @@ -374,33 +398,6 @@ Json formatImmutableReferences(std::map const& _artifactRequested -) -{ - Json output; - if (_artifactRequested("object")) - output["object"] = _object.toHex(); - if (_artifactRequested("opcodes")) - output["opcodes"] = evmasm::disassemble(_object.bytecode, _evmVersion); - if (_artifactRequested("sourceMap")) - output["sourceMap"] = _sourceMap ? *_sourceMap : ""; - if (_artifactRequested("functionDebugData")) - output["functionDebugData"] = StandardCompiler::formatFunctionDebugData(_object.functionDebugData); - if (_artifactRequested("linkReferences")) - output["linkReferences"] = formatLinkReferences(_object.linkReferences); - if (_runtimeObject && _artifactRequested("immutableReferences")) - output["immutableReferences"] = formatImmutableReferences(_object.immutableReferences); - if (_artifactRequested("generatedSources")) - output["generatedSources"] = std::move(_generatedSources); - return output; -} - std::optional checkKeys(Json const& _input, std::set const& _keys, std::string const& _name) { if (!_input.empty() && !_input.is_object()) @@ -568,12 +565,12 @@ std::optional checkOutputSelection(Json const& _outputSelection) /// Validates the optimizer settings and returns them in a parsed object. /// On error returns the json-formatted error message. -std::variant parseOptimizerSettings(Json const& _jsonInput) +std::variant parseOptimizerSettings(std::string_view const _language, Json const& _jsonInput) { if (auto result = checkOptimizerKeys(_jsonInput)) return *result; - OptimiserSettings settings = OptimiserSettings::minimal(); + OptimiserSettings settings = _language == "EVMAssembly" ? OptimiserSettings::none() : OptimiserSettings::minimal(); if (_jsonInput.contains("enabled")) { @@ -850,6 +847,9 @@ std::variant StandardCompiler::parseI ret.eofVersion = 1; } + if (ret.eofVersion.has_value() && !ret.evmVersion.supportsEOF()) + return formatFatalError(Error::Type::JSONError, "EOF is not supported by EVM versions earlier than " + EVMVersion::firstWithEOF().name() + "."); + if (settings.contains("debug")) { if (auto result = checkKeys(settings["debug"], {"revertStrings", "debugInfo"}, "settings.debug")) @@ -911,12 +911,16 @@ std::variant StandardCompiler::parseI if (settings.contains("optimizer")) { - auto optimiserSettings = parseOptimizerSettings(settings["optimizer"]); + auto optimiserSettings = parseOptimizerSettings(ret.language, settings["optimizer"]); if (std::holds_alternative(optimiserSettings)) return std::get(std::move(optimiserSettings)); // was an error else ret.optimiserSettings = std::get(std::move(optimiserSettings)); } + else if (ret.language == "EVMAssembly") + ret.optimiserSettings = OptimiserSettings::none(); + else + ret.optimiserSettings = OptimiserSettings::minimal(); Json const& jsonLibraries = settings.value("libraries", Json::object()); if (!jsonLibraries.is_object()) @@ -1145,9 +1149,6 @@ std::variant StandardCompiler::parseI if (!printQuery.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.printQuery must be a Boolean value."); - if (!(ret.modelCheckerSettings.solvers == smtutil::SMTSolverChoice::SMTLIB2())) - return formatFatalError(Error::Type::JSONError, "Only SMTLib2 solver can be enabled to print queries"); - ret.modelCheckerSettings.printQuery = printQuery.get(); } @@ -1179,6 +1180,39 @@ std::variant StandardCompiler::parseI ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].get(); } + if ((ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug) || isEthdebugRequested(ret.outputSelection)) + { + if (ret.language != "Solidity" && ret.language != "Yul") + return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' 'ethdebug' is only supported for languages 'Solidity' and 'Yul'."); + } + + if (isEthdebugRequested(ret.outputSelection)) + { + if (ret.language == "Solidity" && !ret.viaIR) + return formatFatalError(Error::Type::FatalError, "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set."); + + if (!ret.debugInfoSelection.has_value()) + { + ret.debugInfoSelection = DebugInfoSelection::Default(); + ret.debugInfoSelection->enable("ethdebug"); + } + else + { + if (!ret.debugInfoSelection->ethdebug && ret.language == "Solidity") + return formatFatalError(Error::Type::FatalError, "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output."); + } + } + + if ( + ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug && (ret.language == "Solidity" || ret.language == "Yul") && + !pipelineConfig(ret.outputSelection)[""][""].irCodegen && !isEthdebugRequested(ret.outputSelection) + ) + return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected."); + + if (isEthdebugRequested(ret.outputSelection)) + if (ret.optimiserSettings.runYulOptimiser) + solUnimplemented("Optimization is not yet supported with ethdebug."); + return {std::move(ret)}; } @@ -1208,7 +1242,13 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in if (!isBinaryRequested(_inputsAndSettings.outputSelection)) return Json::object(); - evmasm::EVMAssemblyStack stack(_inputsAndSettings.evmVersion, _inputsAndSettings.eofVersion); + evmasm::EVMAssemblyStack stack( + _inputsAndSettings.evmVersion, + _inputsAndSettings.eofVersion, + evmasm::Assembly::OptimiserSettings::translateSettings( + _inputsAndSettings.optimiserSettings + ) + ); std::string const& sourceName = _inputsAndSettings.jsonSources.begin()->first; // result of structured binding can only be used within lambda from C++20 on. Json const& sourceJson = _inputsAndSettings.jsonSources.begin()->second; try @@ -1220,10 +1260,6 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in { return formatFatalError(Error::Type::Exception, "Assembly import error: " + std::string(e.what())); } - catch (evmasm::InvalidOpcode const& e) - { - return formatFatalError(Error::Type::Exception, "Assembly import error: " + std::string(e.what())); - } catch (...) { return formatError( @@ -1250,22 +1286,26 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in evmObjectComponents("bytecode"), wildcardMatchesExperimental )) - evmData["bytecode"] = collectEVMObject( - _inputsAndSettings.evmVersion, - stack.object(sourceName), - stack.sourceMapping(sourceName), - {}, - false, // _runtimeObject - [&](std::string const& _element) { - return isArtifactRequested( - _inputsAndSettings.outputSelection, - sourceName, - "", - "evm.bytecode." + _element, - wildcardMatchesExperimental - ); - } - ); + { + auto const evmCreationArtifactRequested = [&](std::string const& _element) { + return isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.bytecode." + _element, wildcardMatchesExperimental); + }; + + Json creationJSON; + if (evmCreationArtifactRequested("object")) + creationJSON["object"] = stack.object(sourceName).toHex(); + if (evmCreationArtifactRequested("opcodes")) + creationJSON["opcodes"] = evmasm::disassemble(stack.object(sourceName).bytecode, _inputsAndSettings.evmVersion); + if (evmCreationArtifactRequested("sourceMap")) + creationJSON["sourceMap"] = stack.sourceMapping(sourceName) ? *stack.sourceMapping(sourceName) : ""; + if (evmCreationArtifactRequested("functionDebugData")) + creationJSON["functionDebugData"] = formatFunctionDebugData(stack.object(sourceName).functionDebugData); + if (evmCreationArtifactRequested("linkReferences")) + creationJSON["linkReferences"] = formatLinkReferences(stack.object(sourceName).linkReferences); + if (evmCreationArtifactRequested("ethdebug")) + creationJSON["ethdebug"] = stack.ethdebug(sourceName); + evmData["bytecode"] = creationJSON; + } if (isArtifactRequested( _inputsAndSettings.outputSelection, @@ -1274,22 +1314,28 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in evmObjectComponents("deployedBytecode"), wildcardMatchesExperimental )) - evmData["deployedBytecode"] = collectEVMObject( - _inputsAndSettings.evmVersion, - stack.runtimeObject(sourceName), - stack.runtimeSourceMapping(sourceName), - {}, - true, // _runtimeObject - [&](std::string const& _element) { - return isArtifactRequested( - _inputsAndSettings.outputSelection, - sourceName, - "", - "evm.deployedBytecode." + _element, - wildcardMatchesExperimental - ); - } - ); + { + auto const evmDeployedArtifactRequested = [&](std::string const& _element) { + return isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.deployedBytecode." + _element, wildcardMatchesExperimental); + }; + + Json deployedJSON; + if (evmDeployedArtifactRequested("object")) + deployedJSON["object"] = stack.runtimeObject(sourceName).toHex(); + if (evmDeployedArtifactRequested("opcodes")) + deployedJSON["opcodes"] = evmasm::disassemble(stack.runtimeObject(sourceName).bytecode, _inputsAndSettings.evmVersion); + if (evmDeployedArtifactRequested("sourceMap")) + deployedJSON["sourceMap"] = stack.runtimeSourceMapping(sourceName) ? *stack.runtimeSourceMapping(sourceName) : ""; + if (evmDeployedArtifactRequested("functionDebugData")) + deployedJSON["functionDebugData"] = formatFunctionDebugData(stack.runtimeObject(sourceName).functionDebugData); + if (evmDeployedArtifactRequested("linkReferences")) + deployedJSON["linkReferences"] = formatLinkReferences(stack.runtimeObject(sourceName).linkReferences); + if (evmDeployedArtifactRequested("immutableReferences")) + deployedJSON["immutableReferences"] = formatImmutableReferences(stack.runtimeObject(sourceName).immutableReferences); + if (evmDeployedArtifactRequested("ethdebug")) + deployedJSON["ethdebug"] = stack.ethdebugRuntime(sourceName); + evmData["deployedBytecode"] = deployedJSON; + } Json contractData; if (!evmData.empty()) @@ -1367,6 +1413,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu )); } } + // NOTE: This includes langutil::StackTooDeepError. catch (CompilerError const& _exception) { errors.emplace_back(formatErrorWithException( @@ -1377,14 +1424,22 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu "Compiler error (" + _exception.lineInfo() + ")" )); } - catch (InternalCompilerError const& _exception) + catch (yul::StackTooDeepError const& _exception) { errors.emplace_back(formatErrorWithException( compilerStack, _exception, + Error::Type::YulException, + "general", + "" // No prefix needed. These messages already say it's a "stack too deep" error. + )); + } + catch (InternalCompilerError const&) + { + errors.emplace_back(formatError( Error::Type::InternalCompilerError, "general", - "Internal compiler error (" + _exception.lineInfo() + ")" + "Internal compiler error:\n" + boost::current_exception_diagnostic_information() )); } catch (UnimplementedFeatureError const& _exception) @@ -1392,24 +1447,20 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu // let StandardCompiler::compile handle this throw _exception; } - catch (yul::YulException const& _exception) + catch (YulAssertion const&) { - errors.emplace_back(formatErrorWithException( - compilerStack, - _exception, + errors.emplace_back(formatError( Error::Type::YulException, "general", - "Yul exception" + "Yul assertion failed:\n" + boost::current_exception_diagnostic_information() )); } - catch (smtutil::SMTLogicError const& _exception) + catch (smtutil::SMTLogicError const&) { - errors.emplace_back(formatErrorWithException( - compilerStack, - _exception, + errors.emplace_back(formatError( Error::Type::SMTLogicException, "general", - "SMT logic exception" + "SMT logic error:\n" + boost::current_exception_diagnostic_information() )); } catch (...) @@ -1482,15 +1533,15 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu // IR if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ir", wildcardMatchesExperimental)) - contractData["ir"] = compilerStack.yulIR(contractName); + contractData["ir"] = compilerStack.yulIR(contractName).value_or(""); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irAst", wildcardMatchesExperimental)) - contractData["irAst"] = compilerStack.yulIRAst(contractName); + contractData["irAst"] = compilerStack.yulIRAst(contractName).value_or(Json{}); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irOptimized", wildcardMatchesExperimental)) - contractData["irOptimized"] = compilerStack.yulIROptimized(contractName); + contractData["irOptimized"] = compilerStack.yulIROptimized(contractName).value_or(""); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irOptimizedAst", wildcardMatchesExperimental)) - contractData["irOptimizedAst"] = compilerStack.yulIROptimizedAst(contractName); + contractData["irOptimizedAst"] = compilerStack.yulIROptimizedAst(contractName).value_or(Json{}); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "yulCFGJson", wildcardMatchesExperimental)) - contractData["yulCFGJson"] = compilerStack.yulCFGJson(contractName); + contractData["yulCFGJson"] = compilerStack.yulCFGJson(contractName).value_or(Json{}); // EVM Json evmData; @@ -1510,20 +1561,28 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu evmObjectComponents("bytecode"), wildcardMatchesExperimental )) - evmData["bytecode"] = collectEVMObject( - _inputsAndSettings.evmVersion, - compilerStack.object(contractName), - compilerStack.sourceMapping(contractName), - compilerStack.generatedSources(contractName), - false, - [&](std::string const& _element) { return isArtifactRequested( - _inputsAndSettings.outputSelection, - file, - name, - "evm.bytecode." + _element, - wildcardMatchesExperimental - ); } - ); + { + auto const evmCreationArtifactRequested = [&](std::string const& _element) { + return isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.bytecode." + _element, wildcardMatchesExperimental); + }; + + Json creationJSON; + if (evmCreationArtifactRequested("object")) + creationJSON["object"] = compilerStack.object(contractName).toHex(); + if (evmCreationArtifactRequested("opcodes")) + creationJSON["opcodes"] = evmasm::disassemble(compilerStack.object(contractName).bytecode, _inputsAndSettings.evmVersion); + if (evmCreationArtifactRequested("sourceMap")) + creationJSON["sourceMap"] = compilerStack.sourceMapping(contractName) ? *compilerStack.sourceMapping(contractName) : ""; + if (evmCreationArtifactRequested("functionDebugData")) + creationJSON["functionDebugData"] = formatFunctionDebugData(compilerStack.object(contractName).functionDebugData); + if (evmCreationArtifactRequested("linkReferences")) + creationJSON["linkReferences"] = formatLinkReferences(compilerStack.object(contractName).linkReferences); + if (evmCreationArtifactRequested("generatedSources")) + creationJSON["generatedSources"] = compilerStack.generatedSources(contractName, /* _runtime */ false); + if (evmCreationArtifactRequested("ethdebug")) + creationJSON["ethdebug"] = compilerStack.ethdebug(contractName); + evmData["bytecode"] = creationJSON; + } if (compilationSuccess && isArtifactRequested( _inputsAndSettings.outputSelection, @@ -1532,20 +1591,30 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu evmObjectComponents("deployedBytecode"), wildcardMatchesExperimental )) - evmData["deployedBytecode"] = collectEVMObject( - _inputsAndSettings.evmVersion, - compilerStack.runtimeObject(contractName), - compilerStack.runtimeSourceMapping(contractName), - compilerStack.generatedSources(contractName, true), - true, - [&](std::string const& _element) { return isArtifactRequested( - _inputsAndSettings.outputSelection, - file, - name, - "evm.deployedBytecode." + _element, - wildcardMatchesExperimental - ); } - ); + { + auto const evmDeployedArtifactRequested = [&](std::string const& _element) { + return isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.deployedBytecode." + _element, wildcardMatchesExperimental); + }; + + Json deployedJSON; + if (evmDeployedArtifactRequested("object")) + deployedJSON["object"] = compilerStack.runtimeObject(contractName).toHex(); + if (evmDeployedArtifactRequested("opcodes")) + deployedJSON["opcodes"] = evmasm::disassemble(compilerStack.runtimeObject(contractName).bytecode, _inputsAndSettings.evmVersion); + if (evmDeployedArtifactRequested("sourceMap")) + deployedJSON["sourceMap"] = compilerStack.runtimeSourceMapping(contractName) ? *compilerStack.runtimeSourceMapping(contractName) : ""; + if (evmDeployedArtifactRequested("functionDebugData")) + deployedJSON["functionDebugData"] = formatFunctionDebugData(compilerStack.runtimeObject(contractName).functionDebugData); + if (evmDeployedArtifactRequested("linkReferences")) + deployedJSON["linkReferences"] = formatLinkReferences(compilerStack.runtimeObject(contractName).linkReferences); + if (evmDeployedArtifactRequested("immutableReferences")) + deployedJSON["immutableReferences"] = formatImmutableReferences(compilerStack.runtimeObject(contractName).immutableReferences); + if (evmDeployedArtifactRequested("generatedSources")) + deployedJSON["generatedSources"] = compilerStack.generatedSources(contractName, /* _runtime */ true); + if (evmDeployedArtifactRequested("ethdebug")) + deployedJSON["ethdebug"] = compilerStack.ethdebugRuntime(contractName); + evmData["deployedBytecode"] = deployedJSON; + } if (!evmData.empty()) contractData["evm"] = evmData; @@ -1557,6 +1626,10 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu contractsOutput[file][name] = contractData; } } + + if (isEthdebugRequested(_inputsAndSettings.outputSelection)) + output["ethdebug"] = compilerStack.ethdebug(); + if (!contractsOutput.empty()) output["contracts"] = contractsOutput; @@ -1620,9 +1693,35 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) std::string const& sourceName = _inputsAndSettings.sources.begin()->first; std::string const& sourceContents = _inputsAndSettings.sources.begin()->second; - // Inconsistent state - stop here to receive error reports from users - if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors()) - solAssert(false, "No error reported, but parsing/analysis failed."); + std::string contractName; + bool const wildcardMatchesExperimental = true; + MachineAssemblyObject object; + MachineAssemblyObject deployedObject; + + bool successful = stack.parseAndAnalyze(sourceName, sourceContents); + if (!successful) + // Inconsistent state - stop here to receive error reports from users + solAssert(stack.hasErrors(), "No error reported, but parsing/analysis failed."); + else + { + contractName = stack.parserResult()->name; + if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental)) + output["contracts"][sourceName][contractName]["ir"] = stack.print(); + + if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ast", wildcardMatchesExperimental)) + { + Json sourceResult; + sourceResult["id"] = 0; + sourceResult["ast"] = stack.astJson(); + output["sources"][sourceName] = sourceResult; + } + stack.optimize(); + std::tie(object, deployedObject) = stack.assembleWithDeployed(); + if (object.bytecode) + object.bytecode->link(_inputsAndSettings.libraries); + if (deployedObject.bytecode) + deployedObject.bytecode->link(_inputsAndSettings.libraries); + } for (auto const& error: stack.errors()) { @@ -1639,30 +1738,6 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (stack.hasErrors()) return output; - std::string contractName = stack.parserResult()->name; - - bool const wildcardMatchesExperimental = true; - if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental)) - output["contracts"][sourceName][contractName]["ir"] = stack.print(); - - if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ast", wildcardMatchesExperimental)) - { - Json sourceResult; - sourceResult["id"] = 0; - sourceResult["ast"] = stack.astJson(); - output["sources"][sourceName] = sourceResult; - } - stack.optimize(); - - MachineAssemblyObject object; - MachineAssemblyObject deployedObject; - std::tie(object, deployedObject) = stack.assembleWithDeployed(); - - if (object.bytecode) - object.bytecode->link(_inputsAndSettings.libraries); - if (deployedObject.bytecode) - deployedObject.bytecode->link(_inputsAndSettings.libraries); - for (auto&& [kind, isDeployed]: {make_pair("bytecode"s, false), make_pair("deployedBytecode"s, true)}) if (isArtifactRequested( _inputsAndSettings.outputSelection, @@ -1672,23 +1747,36 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) wildcardMatchesExperimental )) { - MachineAssemblyObject const& o = isDeployed ? deployedObject : object; - if (o.bytecode) - output["contracts"][sourceName][contractName]["evm"][kind] = - collectEVMObject( - _inputsAndSettings.evmVersion, - *o.bytecode, - o.sourceMappings.get(), - Json::array(), - isDeployed, - [&, kind = kind](std::string const& _element) { return isArtifactRequested( - _inputsAndSettings.outputSelection, - sourceName, - contractName, - "evm." + kind + "." + _element, - wildcardMatchesExperimental - ); } - ); + auto const evmArtifactRequested = [&](std::string const& _kind, std::string const& _element) { + return isArtifactRequested( + _inputsAndSettings.outputSelection, + sourceName, + contractName, + "evm." + _kind + "." + _element, + wildcardMatchesExperimental + ); + }; + + MachineAssemblyObject const& selectedObject = isDeployed ? deployedObject : object; + if (selectedObject.bytecode) + { + Json bytecodeJSON; + if (evmArtifactRequested(kind, "object")) + bytecodeJSON["object"] = selectedObject.bytecode->toHex(); + if (evmArtifactRequested(kind, "opcodes")) + bytecodeJSON["opcodes"] = evmasm::disassemble(selectedObject.bytecode->bytecode, _inputsAndSettings.evmVersion); + if (evmArtifactRequested(kind, "sourceMap")) + bytecodeJSON["sourceMap"] = selectedObject.sourceMappings ? *selectedObject.sourceMappings : ""; + if (evmArtifactRequested(kind, "functionDebugData")) + bytecodeJSON["functionDebugData"] = formatFunctionDebugData(selectedObject.bytecode->functionDebugData); + if (evmArtifactRequested(kind, "linkReferences")) + bytecodeJSON["linkReferences"] = formatLinkReferences(selectedObject.bytecode->linkReferences); + if (evmArtifactRequested(kind, "ethdebug")) + bytecodeJSON["ethdebug"] = selectedObject.ethdebug; + if (isDeployed && evmArtifactRequested(kind, "immutableReferences")) + bytecodeJSON["immutableReferences"] = formatImmutableReferences(selectedObject.bytecode->immutableReferences); + output["contracts"][sourceName][contractName]["evm"][kind] = bytecodeJSON; + } } if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "irOptimized", wildcardMatchesExperimental)) @@ -1698,6 +1786,9 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "yulCFGJson", wildcardMatchesExperimental)) output["contracts"][sourceName][contractName]["yulCFGJson"] = stack.cfgJson(); + if (isEthdebugRequested(_inputsAndSettings.outputSelection)) + output["ethdebug"] = evmasm::ethdebug::resources({sourceName}, VersionString); + return output; } @@ -1729,7 +1820,10 @@ Json StandardCompiler::compile(Json const& _input) noexcept } catch (...) { - return formatFatalError(Error::Type::InternalCompilerError, "Internal exception in StandardCompiler::compile: " + boost::current_exception_diagnostic_information()); + return formatFatalError( + Error::Type::InternalCompilerError, + "Uncaught exception:\n" + boost::current_exception_diagnostic_information() + ); } } diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index 590d96b9c191..665e8b487158 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -80,7 +80,7 @@ class StandardCompiler std::optional eofVersion; std::vector remappings; RevertStrings revertStrings = RevertStrings::Default; - OptimiserSettings optimiserSettings = OptimiserSettings::minimal(); + OptimiserSettings optimiserSettings; std::optional debugInfoSelection; std::map libraries; bool metadataLiteralSources = false; diff --git a/libsolidity/interface/StorageLayout.cpp b/libsolidity/interface/StorageLayout.cpp index 8565fec68f26..05d799d08ffd 100644 --- a/libsolidity/interface/StorageLayout.cpp +++ b/libsolidity/interface/StorageLayout.cpp @@ -36,7 +36,7 @@ Json StorageLayout::generate(ContractDefinition const& _contractDef, DataLocatio solAssert(contractType, ""); Json variables = Json::array(); - for (auto [var, slot, offset]: contractType->stateVariables(_location)) + for (auto [var, slot, offset]: contractType->linearizedStateVariables(_location)) variables.emplace_back(generate(*var, slot, offset)); Json layout; diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index f8a2a51eb689..60a7a016bade 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -176,9 +176,14 @@ ASTPointer Parser::parse(CharStream& _charStream) solAssert(m_recursionDepth == 0, ""); return nodeFactory.createNode(findLicenseString(nodes), nodes, m_experimentalSolidityEnabledInCurrentSourceUnit); } - catch (FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } return nullptr; } } @@ -370,6 +375,31 @@ std::pair Parser::parseContractKind() return std::make_pair(kind, abstract); } +ASTPointer Parser::parseStorageLayoutSpecifier() +{ + RecursionGuard recursionGuard(*this); + ASTNodeFactory nodeFactory(*this); + ASTPointer layoutIdentifier = expectIdentifierToken(); + solAssert(layoutIdentifier && *layoutIdentifier == "layout"); + if ( + m_scanner->currentToken() != Token::Identifier || + m_scanner->currentLiteral() != "at" + ) + m_errorReporter.parserError( + 1994_error, + m_scanner->currentLocation(), + "Expected \'at\' but got " + tokenName(m_scanner->currentToken()) + ); + + advance(); + ASTPointer baseSlotExpression = parseExpression(); + solAssert(baseSlotExpression); + nodeFactory.setEndPositionFromNode(baseSlotExpression); + return nodeFactory.createNode( + baseSlotExpression + ); +} + ASTPointer Parser::parseContractDefinition() { RecursionGuard recursionGuard(*this); @@ -380,16 +410,54 @@ ASTPointer Parser::parseContractDefinition() std::vector> baseContracts; std::vector> subNodes; std::pair contractKind{}; + ASTPointer storageLayoutSpecifier; documentation = parseStructuredDocumentation(); contractKind = parseContractKind(); std::tie(name, nameLocation) = expectIdentifierWithLocation(); - if (m_scanner->currentToken() == Token::Is) - do + while (true) + { + if (m_scanner->currentToken() == Token::Is) { - advance(); - baseContracts.push_back(parseInheritanceSpecifier()); + if (baseContracts.size() != 0) + m_errorReporter.parserError( + 6668_error, + m_scanner->currentLocation(), + SecondarySourceLocation().append("Previous list:", baseContracts[0]->location()), + "More than one inheritance list." + ); + do + { + advance(); + baseContracts.push_back(parseInheritanceSpecifier()); + } + while (m_scanner->currentToken() == Token::Comma); } - while (m_scanner->currentToken() == Token::Comma); + else if ( + m_scanner->currentToken() == Token::Identifier && + m_scanner->currentLiteral() == "layout" && + contractKind.first == ContractKind::Contract + ) + { + if (storageLayoutSpecifier) + m_errorReporter.parserError( + 8714_error, + m_scanner->currentLocation(), + SecondarySourceLocation().append("Previous definition:", storageLayoutSpecifier->location()), + "More than one storage layout definition." + ); + + storageLayoutSpecifier = parseStorageLayoutSpecifier(); + } + else + break; + } + + if (storageLayoutSpecifier && baseContracts.size() > 0) + { + solAssert(!storageLayoutSpecifier->location().intersects(baseContracts[0]->location())); + solAssert(!baseContracts[0]->location().intersects(storageLayoutSpecifier->location())); + } + expectToken(Token::LBrace); while (true) { @@ -443,7 +511,8 @@ ASTPointer Parser::parseContractDefinition() baseContracts, subNodes, contractKind.first, - contractKind.second + contractKind.second, + storageLayoutSpecifier ); } @@ -1475,7 +1544,7 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con yul::Parser asmParser(m_errorReporter, dialect); std::shared_ptr ast = asmParser.parseInline(m_scanner); if (ast == nullptr) - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, "Failed to parse inline assembly."); location.end = nativeLocationOf(ast->root()).end; return std::make_shared(nextID(), location, _docString, dialect, std::move(flags), ast); diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 830df05c27c8..d208c1f8bd79 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -171,6 +171,8 @@ class Parser: public langutil::ParserBase FunctionCallArguments parseFunctionCallArguments(); FunctionCallArguments parseNamedArguments(); std::pair, langutil::SourceLocation> expectIdentifierWithLocation(); + + ASTPointer parseStorageLayoutSpecifier(); ///@} ///@{ diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index 6ece23805aac..1ec12051a619 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -7,7 +7,6 @@ set(sources CommonData.h CommonIO.cpp CommonIO.h - cxx20.h DisjointSet.cpp DisjointSet.h DominatorFinder.h @@ -27,6 +26,8 @@ set(sources Numeric.cpp Numeric.h picosha2.h + Profiler.cpp + Profiler.h Result.h SetOnce.h StackTooDeepString.h diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index 1a5451ef5191..ee3a6eb9551f 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -470,7 +470,7 @@ inline std::string asString(bytesConstRef _b) } /// Converts a string to a byte array containing the string's (byte) data. -inline bytes asBytes(std::string const& _b) +inline bytes asBytes(std::string_view const _b) { return bytes((uint8_t const*)_b.data(), (uint8_t const*)(_b.data() + _b.size())); } @@ -551,6 +551,29 @@ void iterateReplacingWindow(std::vector& _vector, F const& _f, std::index_seq } +/// Checks if two collections possess a non-empty intersection. +/// Assumes that both inputs are sorted in ascending order. +template +requires ( + std::forward_iterator> && + std::forward_iterator> +) +bool hasNonemptyIntersectionSorted(Collection1 const& _collection1, Collection2 const& _collection2) +{ + auto it1 = std::ranges::begin(_collection1); + auto it2 = std::ranges::begin(_collection2); + while (it1 != std::ranges::end(_collection1) && it2 != std::ranges::end(_collection2)) + { + if (*it1 == *it2) + return true; + if (*it1 < *it2) + ++it1; + else + ++it2; + } + return false; +} + /// Function that iterates over the vector @param _vector, /// calling the function @param _f on sequences of @tparam N of its /// elements. If @param _f returns a vector, these elements are replaced by diff --git a/libsolutil/Numeric.h b/libsolutil/Numeric.h index f4e88de3c17d..3ecc813c3da0 100644 --- a/libsolutil/Numeric.h +++ b/libsolutil/Numeric.h @@ -45,9 +45,11 @@ namespace solidity { // Numeric types. -using bigint = boost::multiprecision::number>; -using u256 = boost::multiprecision::number>; -using s256 = boost::multiprecision::number>; +using bigint = boost::multiprecision::cpp_int; +using u256 = boost::multiprecision::uint256_t; +using s256 = boost::multiprecision::int256_t; +using u512 = boost::multiprecision::uint512_t; + /// Interprets @a _u as a two's complement signed number and returns the resulting s256. inline s256 u2s(u256 _u) diff --git a/libsolutil/Profiler.cpp b/libsolutil/Profiler.cpp new file mode 100644 index 000000000000..1792963672fe --- /dev/null +++ b/libsolutil/Profiler.cpp @@ -0,0 +1,98 @@ +/* + 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 + +using namespace std::chrono; +using namespace solidity; + +#ifdef PROFILE_OPTIMIZER_STEPS + +util::Profiler::Probe::Probe(std::string _scopeName): + m_scopeName(std::move(_scopeName)), + m_startTime(steady_clock::now()) +{ +} + +util::Profiler::Probe::~Probe() +{ + steady_clock::time_point endTime = steady_clock::now(); + + auto [metricsIt, inserted] = Profiler::singleton().m_metrics.try_emplace(m_scopeName, Metrics{0us, 0}); + metricsIt->second.durationInMicroseconds += duration_cast(endTime - m_startTime); + ++metricsIt->second.callCount; +} + +util::Profiler::~Profiler() +{ + outputPerformanceMetrics(); +} + +util::Profiler& util::Profiler::singleton() +{ + static Profiler profiler; + return profiler; +} + +void util::Profiler::outputPerformanceMetrics() +{ + std::vector> sortedMetrics(m_metrics.begin(), m_metrics.end()); + std::sort( + sortedMetrics.begin(), + sortedMetrics.end(), + [](std::pair const& _lhs, std::pair const& _rhs) -> bool + { + return _lhs.second.durationInMicroseconds < _rhs.second.durationInMicroseconds; + } + ); + + std::chrono::microseconds totalDurationInMicroseconds = 0us; + size_t totalCallCount = 0; + for (auto&& [scopeName, scopeMetrics]: sortedMetrics) + { + totalDurationInMicroseconds += scopeMetrics.durationInMicroseconds; + totalCallCount += scopeMetrics.callCount; + } + + std::cerr << "PERFORMANCE METRICS FOR PROFILED SCOPES\n\n"; + std::cerr << "| Time % | Time | Calls | Scope |\n"; + std::cerr << "|-------:|-----------:|--------:|--------------------------------|\n"; + + double totalDurationInSeconds = duration_cast>(totalDurationInMicroseconds).count(); + for (auto&& [scopeName, scopeMetrics]: sortedMetrics) + { + double durationInSeconds = duration_cast>(scopeMetrics.durationInMicroseconds).count(); + double percentage = 100.0 * durationInSeconds / totalDurationInSeconds; + std::cerr << fmt::format( + "| {:5.1f}% | {:8.3f} s | {:7} | {:30} |\n", + percentage, + durationInSeconds, + scopeMetrics.callCount, + scopeName + ); + } + std::cerr << fmt::format("| {:5.1f}% | {:8.3f} s | {:7} | {:30} |\n", 100.0, totalDurationInSeconds, totalCallCount, "**TOTAL**"); +} + +#endif diff --git a/libsolutil/Profiler.h b/libsolutil/Profiler.h new file mode 100644 index 000000000000..79c516d0197b --- /dev/null +++ b/libsolutil/Profiler.h @@ -0,0 +1,81 @@ +/* + 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 + +#ifdef PROFILE_OPTIMIZER_STEPS +#define PROFILER_PROBE(_scopeName, _variable) solidity::util::Profiler::Probe _variable(_scopeName); +#else +#define PROFILER_PROBE(_scopeName, _variable) void(0); +#endif + +namespace solidity::util +{ + +#ifdef PROFILE_OPTIMIZER_STEPS + +/// Simpler profiler class that gathers metrics during program execution and prints them out on exit. +/// +/// To gather metrics, create a Probe instance and let it live until the end of the scope. +/// The probe will register its creation and destruction time and store the results in the profiler +/// singleton. +/// +/// Use the PROFILER_PROBE macro to create probes conditionally, in a way that will not affect performance +/// unless profiling is enabled at compilation time via PROFILE_OPTIMIZER_STEPS CMake option. +/// +/// Scopes are identified by the name supplied to the probe. Using the same name multiple times +/// will result in metrics for those scopes being aggregated together as if they were the same scope. +class Profiler +{ +public: + class Probe + { + public: + Probe(std::string _scopeName); + ~Probe(); + + private: + std::string m_scopeName; + std::chrono::steady_clock::time_point m_startTime; + }; + + static Profiler& singleton(); + +private: + ~Profiler(); + + struct Metrics + { + std::chrono::microseconds durationInMicroseconds; + size_t callCount; + }; + + /// Summarizes gathered metric and prints a report to standard error output. + void outputPerformanceMetrics(); + + std::map m_metrics; +}; + +#endif + +} diff --git a/libsolutil/StringUtils.h b/libsolutil/StringUtils.h index 77ffe6735401..763f1ea64f41 100644 --- a/libsolutil/StringUtils.h +++ b/libsolutil/StringUtils.h @@ -67,24 +67,24 @@ std::string joinHumanReadable { auto const itEnd = end(_list); - std::string result; + std::stringstream result; for (auto it = begin(_list); it != itEnd; ) { - std::string element = *it; + auto const& element = *it; bool first = (it == begin(_list)); ++it; if (!first) { if (it == itEnd && !_lastSeparator.empty()) - result += _lastSeparator; // last iteration + result << _lastSeparator; // last iteration else - result += _separator; + result << _separator; } - result += std::move(element); + result << element; } - return result; + return result.str(); } /// Joins collection of strings just like joinHumanReadable, but prepends the separator diff --git a/libsolutil/cxx20.h b/libsolutil/cxx20.h deleted file mode 100644 index a21a73e681af..000000000000 --- a/libsolutil/cxx20.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -// SPDX-License-Identifier: GPL-3.0 -#pragma once - -#include - -// Contains polyfills of STL functions and algorithms that will become available in C++20. -namespace solidity::cxx20 -{ - -// Taken from https://en.cppreference.com/w/cpp/container/map/erase_if. -template -typename std::map::size_type erase_if(std::map& _c, Pred _pred) -{ - auto old_size = _c.size(); - for (auto i = _c.begin(), last = _c.end(); i != last;) - if (_pred(*i)) - i = _c.erase(i); - else - ++i; - return old_size - _c.size(); -} - -// Taken from https://en.cppreference.com/w/cpp/container/unordered_map/erase_if. -template -typename std::unordered_map::size_type -erase_if(std::unordered_map& _c, Pred _pred) -{ - auto old_size = _c.size(); - for (auto i = _c.begin(), last = _c.end(); i != last;) - if (_pred(*i)) - i = _c.erase(i); - else - ++i; - return old_size - _c.size(); -} - -// Taken from https://en.cppreference.com/w/cpp/container/vector/erase2 -template -constexpr typename std::vector::size_type -erase_if(std::vector& c, Pred pred) -{ - auto it = std::remove_if(c.begin(), c.end(), pred); - auto r = std::distance(it, c.end()); - c.erase(it, c.end()); - return static_cast::size_type>(r); -} - -} diff --git a/libyul/AST.h b/libyul/AST.h index f51846280a8f..d5988ee05386 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -24,6 +24,7 @@ #pragma once #include +#include #include #include @@ -36,6 +37,8 @@ namespace solidity::yul { +class Dialect; + struct NameWithDebugData { langutil::DebugData::ConstPtr debugData; YulName name; }; using NameWithDebugDataList = std::vector; @@ -69,6 +72,9 @@ class LiteralValue { struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; LiteralValue value; }; /// External / internal identifier or label reference struct Identifier { langutil::DebugData::ConstPtr debugData; YulName name; }; +/// AST Node representing a reference to one of the built-in functions (as defined by the dialect). +/// In the source it's an actual name, while in the AST we only store a handle that can be used to find the function in the Dialect +struct BuiltinName { langutil::DebugData::ConstPtr debugData; BuiltinHandle handle; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// @@ -76,7 +82,7 @@ struct Identifier { langutil::DebugData::ConstPtr debugData; YulName name; }; /// a single stack slot and expects a single expression on the right hand returning /// the same amount of items as the number of variables. struct Assignment { langutil::DebugData::ConstPtr debugData; std::vector variableNames; std::unique_ptr value; }; -struct FunctionCall { langutil::DebugData::ConstPtr debugData; Identifier functionName; std::vector arguments; }; +struct FunctionCall { langutil::DebugData::ConstPtr debugData; FunctionName functionName; std::vector arguments; }; /// Statement that contains only a single expression struct ExpressionStatement { langutil::DebugData::ConstPtr debugData; Expression expression; }; /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted @@ -103,13 +109,20 @@ struct Leave { langutil::DebugData::ConstPtr debugData; }; class AST { public: - explicit AST(Block _root): m_root(std::move(_root)) {} + AST(Dialect const& _dialect, Block _root): m_dialect(_dialect), m_root(std::move(_root)) {} - [[nodiscard]] Block const& root() const { return m_root; } + Dialect const& dialect() const { return m_dialect; } + Block const& root() const { return m_root; } private: + Dialect const& m_dialect; Block m_root; }; +bool constexpr isBuiltinFunctionCall(FunctionCall const& _functionCall) noexcept +{ + return std::holds_alternative(_functionCall.functionName); +} + /// Extracts the IR source location from a Yul node. template inline langutil::SourceLocation nativeLocationOf(T const& _node) diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index 8aba4f248c07..868fc84b2827 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -28,6 +28,9 @@ namespace solidity::yul { +class YulString; +using YulName = YulString; + enum class LiteralKind; class LiteralValue; struct Literal; @@ -46,11 +49,17 @@ struct Continue; struct Leave; struct ExpressionStatement; struct Block; +struct BuiltinName; +struct BuiltinHandle; class AST; struct NameWithDebugData; using Expression = std::variant; +using FunctionName = std::variant; +/// Type that can refer to both user-defined functions and built-ins. +/// Technically the AST allows these names to overlap, but this is not possible to represent in the source. +using FunctionHandle = std::variant; using Statement = std::variant; } diff --git a/libyul/ASTLabelRegistry.cpp b/libyul/ASTLabelRegistry.cpp new file mode 100644 index 000000000000..8f26f2f5be8d --- /dev/null +++ b/libyul/ASTLabelRegistry.cpp @@ -0,0 +1,166 @@ +/* + 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 + +using namespace solidity::yul; + +ASTLabelRegistry::ASTLabelRegistry(): m_labels{""}, m_idToLabelMapping{0} {} + +ASTLabelRegistry::ASTLabelRegistry(std::vector _labels, std::vector _idToLabelMapping): + m_labels(std::move(_labels)), + m_idToLabelMapping(std::move(_idToLabelMapping)) +{ + yulAssert(!m_labels.empty()); + yulAssert(m_labels[0].empty()); + yulAssert(!m_idToLabelMapping.empty()); + yulAssert(m_idToLabelMapping[0] == 0); + // using vector over vector, as the latter is optimized for space-efficiency + std::vector labelVisited (m_labels.size(), false); + size_t numLabels = 0; + for (auto const& labelIndex: m_idToLabelMapping) + { + if (labelIndex == ghostLabelIndex()) + continue; + yulAssert(labelIndex < m_labels.size()); + // it is possible to have multiple references to the empty label index + // only the id == 0 refers to an actually empty label, otherwise the LabelID is unused + yulAssert( + labelIndex == 0 || !labelVisited[labelIndex], + fmt::format("LabelID {} (label \"{}\") is not unique.", labelIndex, m_labels[labelIndex]) + ); + labelVisited[labelIndex] = true; + if (labelIndex >= 1) + ++numLabels; + } + yulAssert(numLabels + 1 == m_labels.size(), "Unreferenced labels present."); +} + +ASTLabelRegistry::LabelID ASTLabelRegistry::maxID() const +{ + yulAssert(!m_idToLabelMapping.empty()); + return m_idToLabelMapping.size() - 1; +} + +size_t ASTLabelRegistry::idToLabelIndex(LabelID const _id) const +{ + yulAssert(_id < m_idToLabelMapping.size()); + return m_idToLabelMapping[_id]; +} + +std::string_view ASTLabelRegistry::operator[](LabelID const _id) const +{ + auto const labelIndex = idToLabelIndex(_id); + yulAssert(labelIndex != ghostLabelIndex(), "Ghost ids are not explicitly labelled in the registry."); + // not using `unused` here, as we already have evaluated the label index + // an id is unused if it is not id == 0 (empty label) but points at label index 0 + yulAssert(empty(_id) || labelIndex != 0, "Can only query ids that are not unused"); + return m_labels[labelIndex]; +} + +bool ASTLabelRegistry::ghost(LabelID const _id) const +{ + return idToLabelIndex(_id) == ghostLabelIndex(); +} + +bool ASTLabelRegistry::unused(LabelID const _id) const +{ + return !empty(_id) && idToLabelIndex(_id) == 0; +} + +std::optional ASTLabelRegistry::findIDForLabel(std::string_view const _label) const +{ + for (LabelID id = 0; id <= maxID(); ++id) + if ((*this)[id] == _label) + return id; + return std::nullopt; +} + +std::tuple ASTLabelRegistryBuilder::DefinedLabels::tryInsert( + std::string_view const _label, + ASTLabelRegistry::LabelID const _id +) +{ + auto const [it, emplaced] = m_labelToIDMapping.try_emplace(std::string{_label}, _id); + return std::make_tuple(it->second, emplaced); +} + +ASTLabelRegistryBuilder::ASTLabelRegistryBuilder(): + m_nextID(1) +{} + +ASTLabelRegistryBuilder::ASTLabelRegistryBuilder(ASTLabelRegistry const& _existingRegistry) +{ + yulAssert(!_existingRegistry.labels().empty() && _existingRegistry[0].empty()); + for (size_t id = 1; id <= _existingRegistry.maxID(); ++id) + { + if (!ASTLabelRegistry::empty(id) && !_existingRegistry.unused(id)) + { + // ghost ids are not added to the map as they are not explicitly labeled + if (_existingRegistry.ghost(id)) + m_ghosts.push_back(id); + else + { + auto const [_, inserted] = m_definedLabels.tryInsert(_existingRegistry[id], id); + yulAssert(inserted, "Existing registry cannot contain duplicate labels."); + } + } + } + m_nextID = _existingRegistry.maxID() + 1; +} + +ASTLabelRegistry::LabelID ASTLabelRegistryBuilder::define(std::string_view const _label) +{ + auto const [id, inserted] = m_definedLabels.tryInsert(_label, m_nextID); + if (inserted) + m_nextID++; + return id; +} + +ASTLabelRegistry::LabelID ASTLabelRegistryBuilder::addGhost() +{ + m_ghosts.push_back(m_nextID); + return m_nextID++; +} + +ASTLabelRegistry ASTLabelRegistryBuilder::build() const +{ + auto const& labelToIDMapping = m_definedLabels.labelToIDMapping(); + yulAssert(labelToIDMapping.contains("")); + yulAssert(labelToIDMapping.at("") == 0); + + std::vector labels{""}; + labels.reserve(labelToIDMapping.size()); + std::vector idToLabelMapping( m_nextID + 1, 0); + yulAssert(!idToLabelMapping.empty(), "Mapping must at least contain empty label"); + for (auto const& [label, id]: labelToIDMapping) + { + if (ASTLabelRegistry::empty(id)) + continue; + + labels.emplace_back(label); + idToLabelMapping[id] = labels.size() - 1; + } + for (auto const ghostId: m_ghosts) + idToLabelMapping[ghostId] = ASTLabelRegistry::ghostLabelIndex(); + return ASTLabelRegistry{std::move(labels), std::move(idToLabelMapping)}; +} diff --git a/libyul/ASTLabelRegistry.h b/libyul/ASTLabelRegistry.h new file mode 100644 index 000000000000..cb7c405af9fa --- /dev/null +++ b/libyul/ASTLabelRegistry.h @@ -0,0 +1,110 @@ +/* + 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 + +namespace solidity::yul +{ + +/// Instances of the `ASTLabelRegistry` are immutable containers describing a labelling of nodes inside the AST. +/// Each element of the AST that possesses a label has a `ASTLabelRegistry::LabelID`, with which the label can +/// be queried in O(1). +/// Preferred way of creating instances is via `ASTLabelRegistryBuilder` when parsing/importing and +/// via `LabelIDDispenser` during/after optimization. +/// Note: The id == 0 always corresponds to the empty label. Other ids can point at the label index 0, which means that +/// they are unused. To check, whether an id is unused, the `unused` function can be used. +/// Note: There is a special case of ghost ids, which are added during CFG construction. +/// They do not directly correspond to elements of an AST but live inside the CFG. They are assigned the +/// special `std::numeric_limits::max` label index. The labels themselves are - if required - generated from +/// the CFG. +class ASTLabelRegistry +{ +public: + /// unsafe to use from a different registry instance, it is up to the user to safeguard against this + using LabelID = size_t; + + ASTLabelRegistry(); + ASTLabelRegistry(std::vector _labels, std::vector _idToLabelMapping); + + std::string_view operator[](LabelID _id) const; + + static bool constexpr empty(LabelID const _id) { return _id == emptyID(); } + static LabelID constexpr emptyID() { return 0; } + static size_t constexpr ghostLabelIndex() { return std::numeric_limits::max(); } + + bool unused(LabelID _id) const; + bool ghost(LabelID _id) const; + std::vector const& labels() const { return m_labels; } + LabelID maxID() const; + + size_t idToLabelIndex(LabelID _id) const; + /// this is a potentially expensive operation + std::optional findIDForLabel(std::string_view _label) const; + +private: + /// All Yul AST labels present in the registry. + /// Always contains at least an empty label which also serves as a null-state for non-contiguous ID ranges. + /// All items must be unique. + std::vector const m_labels; + + /// Assignment of labels to `LabelID`s. Indices are `LabelID`s and values are indices into `m_labels`. + /// Every label except empty always has exactly one `LabelID` pointing at it. + /// The empty label has one canonical ID, but unused IDs point to it as well. + std::vector const m_idToLabelMapping; +}; + +/// Produces instances of `ASTLabelRegistry`. Preferably used during parsing/importing. +class ASTLabelRegistryBuilder +{ +public: + ASTLabelRegistryBuilder(); + /// Creates a new builder taking an already existing label registry into account. + /// Unused IDs are skipped, ghost IDs are recorded and inserted back into the newly built registry. + explicit ASTLabelRegistryBuilder(ASTLabelRegistry const& _existingRegistry); + + ASTLabelRegistry::LabelID define(std::string_view _label); + ASTLabelRegistry::LabelID addGhost(); + + /// Creates a new label registry based on what was defined and potentially an existing registry. If such registry + /// was provided, all labels (including unused and ghost label IDs) carry over. + ASTLabelRegistry build() const; + +private: + class DefinedLabels + { + public: + std::tuple tryInsert(std::string_view _label, ASTLabelRegistry::LabelID _id); + auto const& labelToIDMapping() const { return m_labelToIDMapping; } + + private: + std::map> m_labelToIDMapping = {{"", 0}}; + }; + + DefinedLabels m_definedLabels; + std::vector m_ghosts; + size_t m_nextID{}; +}; + +} diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index cf8c720f6b36..b6ff862b3850 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -68,31 +68,39 @@ bool AsmAnalyzer::analyze(Block const& _block) auto watcher = m_errorReporter.errorWatcher(); try { + // FIXME: Pass location of the object name. Now it's a location of first code section in yul + validateObjectStructure(nativeLocationOf(_block)); if (!(ScopeFiller(m_info, m_errorReporter))(_block)) return false; (*this)(_block); } - catch (FatalError const& error) + catch (FatalError const&) { // NOTE: There's a cap on the number of reported errors, but watcher.ok() will work fine even if // we exceed it because the reporter keeps counting (it just stops adding errors to the list). // Note also that fact of exceeding the cap triggers a FatalError so one can get thrown even // if we don't make any of our errors fatal. - yulAssert(!watcher.ok(), "Unreported fatal error: "s + error.what()); + if (watcher.ok()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + yulAssert(false, "Unreported fatal error."); + } } return watcher.ok(); } -AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object) +AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Object const& _object) { - return analyzeStrictAssertCorrect(_dialect, _object.code()->root(), _object.qualifiedDataNames()); + yulAssert(_object.dialect()); + return analyzeStrictAssertCorrect(*_object.dialect(), _object.code()->root(), _object.summarizeStructure()); } AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( Dialect const& _dialect, Block const& _astRoot, - std::set const& _qualifiedDataNames + Object::Structure const _objectStructure ) { ErrorList errorList; @@ -103,9 +111,38 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( errors, _dialect, {}, - _qualifiedDataNames + std::move(_objectStructure) ).analyze(_astRoot); - yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); + + if (!success) + { + auto formatErrors = [](ErrorList const& _errorList) { + std::vector formattedErrors; + for (std::shared_ptr const& error: _errorList) + { + yulAssert(error->comment()); + formattedErrors.push_back(fmt::format( + // Intentionally not showing source locations because we don't have the original + // source here and it's unlikely they match the pretty-printed version. + // They may not even match the original source if the AST was modified by the optimizer. + "- {} {}: {}", + Error::formatErrorType(error->type()), + error->errorId().error, + *error->comment() + )); + } + return joinHumanReadable(formattedErrors, "\n"); + }; + + yulAssert(errors.hasErrors(), "Yul analysis failed but did not report any errors."); + yulAssert(false, fmt::format( + "{}\n\nExpected valid Yul, but errors were reported during analysis:\n{}", + AsmPrinter{_dialect}(_astRoot), + formatErrors(errorList) + )); + } + + yulAssert(!errors.hasErrors()); return analysisInfo; } @@ -288,20 +325,36 @@ void AsmAnalyzer::operator()(FunctionDefinition const& _funDef) m_activeVariables.insert(&std::get(varScope.identifiers.at(var.name))); } + if (m_eofVersion.has_value()) + { + if (_funDef.parameters.size() >= 0x80) + m_errorReporter.typeError( + 8534_error, + nativeLocationOf(_funDef), + "Too many function parameters. At most 127 parameters allowed for EOF" + ); + + if (_funDef.returnVariables.size() >= 0x80) + m_errorReporter.typeError( + 2101_error, + nativeLocationOf(_funDef), + "Too many function return variables. At most 127 return variables allowed for EOF" + ); + } + (*this)(_funDef.body); } size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) { - yulAssert(!_funCall.functionName.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); std::optional numParameters; std::optional numReturns; std::vector> const* literalArguments = nullptr; - if (BuiltinFunction const* f = m_dialect.builtin(_funCall.functionName.name)) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_funCall.functionName, m_dialect)) { - if (_funCall.functionName.name == "selfdestruct"_yulname) + if (builtin->name == "selfdestruct") m_errorReporter.warning( 1699_error, nativeLocationOf(_funCall.functionName), @@ -314,7 +367,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) ); else if ( m_evmVersion.supportsTransientStorage() && - _funCall.functionName.name == "tstore"_yulname && + builtin->name == "tstore" && !m_errorReporter.hasError({2394}) ) m_errorReporter.warning( @@ -327,15 +380,15 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) "The use of transient storage for reentrancy guards that are cleared at the end of the call is safe." ); - numParameters = f->numParameters; - numReturns = f->numReturns; - if (!f->literalArguments.empty()) - literalArguments = &f->literalArguments; + numParameters = builtin->numParameters; + numReturns = builtin->numReturns; + if (!builtin->literalArguments.empty()) + literalArguments = &builtin->literalArguments; validateInstructions(_funCall); - m_sideEffects += f->sideEffects; + m_sideEffects += builtin->sideEffects; } - else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ + else if (m_currentScope->lookup(YulName{resolveFunctionName(_funCall.functionName, m_dialect)}, GenericVisitor{ [&](Scope::Variable const&) { m_errorReporter.typeError( @@ -351,10 +404,11 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) } })) { + yulAssert(std::holds_alternative(_funCall.functionName)); if (m_resolver) // We found a local reference, make sure there is no external reference. m_resolver( - _funCall.functionName, + std::get(_funCall.functionName), yul::IdentifierContext::NonExternal, m_currentScope->insideFunction() ); @@ -365,7 +419,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.declarationError( 4619_error, nativeLocationOf(_funCall.functionName), - "Function \"" + _funCall.functionName.name.str() + "\" not found." + fmt::format("Function \"{}\" not found.", resolveFunctionName(_funCall.functionName, m_dialect)) ); yulAssert(!watcher.ok(), "Expected a reported error."); } @@ -374,10 +428,12 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.typeError( 7000_error, nativeLocationOf(_funCall.functionName), - "Function \"" + _funCall.functionName.name.str() + "\" expects " + - std::to_string(*numParameters) + - " arguments but got " + - std::to_string(_funCall.arguments.size()) + "." + fmt::format( + "Function \"{}\" expects {} arguments but got {}.", + resolveFunctionName(_funCall.functionName, m_dialect), + *numParameters, + _funCall.arguments.size() + ) ); for (size_t i = _funCall.arguments.size(); i > 0; i--) @@ -403,11 +459,11 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) ); else if (*literalArgumentKind == LiteralKind::String) { - std::string functionName = _funCall.functionName.name.str(); + std::string_view functionName = resolveFunctionName(_funCall.functionName, m_dialect); if (functionName == "datasize" || functionName == "dataoffset") { auto const& argumentAsLiteral = std::get(arg); - if (!m_dataNames.count(formatLiteral(argumentAsLiteral))) + if (!m_objectStructure.contains(formatLiteral(argumentAsLiteral))) m_errorReporter.typeError( 3517_error, nativeLocationOf(arg), @@ -425,9 +481,52 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) "The \"verbatim_*\" builtins cannot be used with empty bytecode." ); } + else if (functionName == "eofcreate" || functionName == "returncontract") + { + auto const& argumentAsLiteral = std::get(arg); + auto const formattedLiteral = formatLiteral(argumentAsLiteral); + + if (util::contains(formattedLiteral, '.')) + m_errorReporter.typeError( + 2186_error, + nativeLocationOf(arg), + fmt::format("Name required but path given as \"{}\" argument.", functionName) + ); + + if (!m_objectStructure.topLevelSubObjectNames().count(formattedLiteral)) + { + if (m_objectStructure.containsData(formattedLiteral)) + m_errorReporter.typeError( + 7575_error, + nativeLocationOf(arg), + "Data name \"" + formattedLiteral + "\" cannot be used as an argument of eofcreate/returncontract. " + + "An object name is only acceptable." + ); + else + m_errorReporter.typeError( + 8970_error, + nativeLocationOf(arg), + "Unknown object \"" + formattedLiteral + "\"." + ); + } + } expectUnlimitedStringLiteral(std::get(arg)); continue; } + else if (*literalArgumentKind == LiteralKind::Number) + { + std::string_view functionName = resolveFunctionName(_funCall.functionName, m_dialect); + if (functionName == "auxdataloadn") + { + auto const& argumentAsLiteral = std::get(arg); + if (argumentAsLiteral.value.value() > std::numeric_limits::max()) + m_errorReporter.typeError( + 5202_error, + nativeLocationOf(arg), + "Invalid auxdataloadn argument value. Offset must be in range 0...0xFFFF" + ); + } + } } expectExpression(arg); } @@ -614,7 +713,7 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons "\"" + _identifier.str() + "\" is not a valid identifier (contains consecutive dots)." ); - if (m_dialect.reservedIdentifier(_identifier)) + if (m_dialect.reservedIdentifier(_identifier.str())) m_errorReporter.declarationError( 5017_error, _location, @@ -622,15 +721,38 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons ); } -bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) +bool AsmAnalyzer::validateInstructions(std::string_view _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. - // TODO: Add EOF support - auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt).builtin(YulName(_instructionIdentifier)); - if (builtin && builtin->instruction.has_value()) - return validateInstructions(builtin->instruction.value(), _location); - else - return false; + auto const& defaultEVMDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}, std::nullopt); + auto const builtinHandle = defaultEVMDialect.findBuiltin(_instructionIdentifier); + if (builtinHandle && defaultEVMDialect.builtin(*builtinHandle).instruction.has_value()) + return validateInstructions(*defaultEVMDialect.builtin(*builtinHandle).instruction, _location); + + solAssert(!m_eofVersion.has_value() || *m_eofVersion == 1); + auto const& eofDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion::firstWithEOF(), 1); + auto const eofBuiltinHandle = eofDialect.findBuiltin(_instructionIdentifier); + if (eofBuiltinHandle) + { + auto const builtin = eofDialect.builtin(*eofBuiltinHandle); + if (builtin.instruction.has_value()) + return validateInstructions(*builtin.instruction, _location); + // If builtin is available in EOF but not available in legacy (and we build to legacy) generate custom error. + else if (!m_eofVersion.has_value() && !builtinHandle) + { + m_errorReporter.declarationError( + 7223_error, + _location, + fmt::format( + "Builtin function \"{}\" is only available in EOF.", + fmt::arg("function", _instructionIdentifier) + ) + ); + return true; + } + } + + return false; } bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocation const& _location) @@ -645,8 +767,18 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio yulAssert( _instr != evmasm::Instruction::JUMP && _instr != evmasm::Instruction::JUMPI && - _instr != evmasm::Instruction::JUMPDEST, - ""); + _instr != evmasm::Instruction::JUMPDEST && + _instr != evmasm::Instruction::DATALOADN && + _instr != evmasm::Instruction::EOFCREATE && + _instr != evmasm::Instruction::RETURNCONTRACT && + _instr != evmasm::Instruction::RJUMP && + _instr != evmasm::Instruction::RJUMPI && + _instr != evmasm::Instruction::CALLF && + _instr != evmasm::Instruction::JUMPF && + _instr != evmasm::Instruction::RETF && + _instr != evmasm::Instruction::DUPN && + _instr != evmasm::Instruction::SWAPN + ); auto errorForVM = [&](ErrorId _errorId, std::string const& vmKindMessage) { m_errorReporter.typeError( @@ -702,13 +834,94 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio "PC instruction is a low-level EVM feature. " "Because of that PC is disallowed in strict assembly." ); + else if (!m_eofVersion.has_value() && ( + _instr == evmasm::Instruction::EXTCALL || + _instr == evmasm::Instruction::EXTDELEGATECALL || + _instr == evmasm::Instruction::EXTSTATICCALL + )) + { + m_errorReporter.typeError( + 4328_error, + _location, + fmt::format( + "The \"{}\" instruction is only available in EOF.", + fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)) + ) + ); + } + else if (m_eofVersion.has_value() && ( + _instr == evmasm::Instruction::CALL || + _instr == evmasm::Instruction::CALLCODE || + _instr == evmasm::Instruction::DELEGATECALL || + _instr == evmasm::Instruction::STATICCALL || + _instr == evmasm::Instruction::SELFDESTRUCT || + _instr == evmasm::Instruction::JUMP || + _instr == evmasm::Instruction::JUMPI || + _instr == evmasm::Instruction::PC || + _instr == evmasm::Instruction::CREATE || + _instr == evmasm::Instruction::CREATE2 || + _instr == evmasm::Instruction::CODESIZE || + _instr == evmasm::Instruction::CODECOPY || + _instr == evmasm::Instruction::EXTCODESIZE || + _instr == evmasm::Instruction::EXTCODECOPY || + _instr == evmasm::Instruction::EXTCODEHASH || + _instr == evmasm::Instruction::GAS + )) + { + m_errorReporter.typeError( + 9132_error, + _location, + fmt::format( + "The \"{instruction}\" instruction is {kind} VMs (you are currently compiling to EOF).", + fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)), + fmt::arg("kind", "only available in legacy bytecode") + ) + ); + } else + { + // Sanity check + solAssert(m_evmVersion.hasOpcode(_instr, m_eofVersion)); return false; + } + // Sanity check + // PC is not available in strict assembly but it is always valid opcode in legacy evm. + solAssert(_instr == evmasm::Instruction::PC || !m_evmVersion.hasOpcode(_instr, m_eofVersion)); return true; } bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall) { - return validateInstructions(_functionCall.functionName.name.str(), nativeLocationOf(_functionCall.functionName)); + return validateInstructions( + resolveFunctionName(_functionCall.functionName, m_dialect), + nativeLocationOf(_functionCall.functionName) + ); +} + +void AsmAnalyzer::validateObjectStructure(langutil::SourceLocation _astRootLocation) +{ + if (m_eofVersion.has_value()) + { + if (util::contains(m_objectStructure.objectName, '.')) // No dots in object name for EOF + m_errorReporter.syntaxError( + 9822_error, + _astRootLocation, + fmt::format( + "The object name \"{objectName}\" is invalid in EOF context. Object names must not contain 'dot' character.", + fmt::arg("objectName", m_objectStructure.objectName) + ) + ); + else if (m_objectStructure.topLevelSubObjectNames().size() > 256) + { + m_errorReporter.syntaxError( + 1305_error, + _astRootLocation, + fmt::format( + "Too many subobjects in \"{objectName}\". At most 256 subobjects allowed when compiling to EOF", + fmt::arg("objectName", m_objectStructure.objectName) + ) + ); + } + } } diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 64cab51f54c5..e8c02fbec132 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -61,27 +62,30 @@ class AsmAnalyzer langutil::ErrorReporter& _errorReporter, Dialect const& _dialect, ExternalIdentifierAccess::Resolver _resolver = ExternalIdentifierAccess::Resolver(), - std::set _dataNames = {} + Object::Structure const _objectStructure = {} ): m_resolver(std::move(_resolver)), m_info(_analysisInfo), m_errorReporter(_errorReporter), m_dialect(_dialect), - m_dataNames(std::move(_dataNames)) + m_objectStructure(std::move(_objectStructure)) { if (EVMDialect const* evmDialect = dynamic_cast(&m_dialect)) + { m_evmVersion = evmDialect->evmVersion(); + m_eofVersion = evmDialect->eofVersion(); + } } bool analyze(Block const& _block); /// Performs analysis on the outermost code of the given object and returns the analysis info. /// Asserts on failure. - static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object); + static AsmAnalysisInfo analyzeStrictAssertCorrect(Object const& _object); static AsmAnalysisInfo analyzeStrictAssertCorrect( Dialect const& _dialect, Block const& _astRoot, - std::set const& _qualifiedDataNames + Object::Structure const _objectStructure ); size_t operator()(Literal const& _literal); @@ -114,9 +118,11 @@ class AsmAnalyzer void expectValidIdentifier(YulName _identifier, langutil::SourceLocation const& _location); bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location); - bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); + bool validateInstructions(std::string_view _instrIdentifier, langutil::SourceLocation const& _location); bool validateInstructions(FunctionCall const& _functionCall); + void validateObjectStructure(langutil::SourceLocation _astRootLocation); + yul::ExternalIdentifierAccess::Resolver m_resolver; Scope* m_currentScope = nullptr; /// Variables that are active at the current point in assembly (as opposed to @@ -125,9 +131,10 @@ class AsmAnalyzer AsmAnalysisInfo& m_info; langutil::ErrorReporter& m_errorReporter; langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; Dialect const& m_dialect; /// Names of data objects to be referenced by builtin functions with literal arguments. - std::set m_dataNames; + Object::Structure m_objectStructure; ForLoop const* m_currentForLoop = nullptr; /// Worst side effects encountered during analysis (including within defined functions). SideEffects m_sideEffects; diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index 226ac52a5ac8..fd36dd26022c 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -20,8 +20,10 @@ * Converts inline assembly AST to JSON format */ -#include #include + +#include +#include #include #include #include @@ -83,6 +85,14 @@ Json AsmJsonConverter::operator()(Identifier const& _node) const return ret; } +Json AsmJsonConverter::operator()(BuiltinName const& _node) const +{ + // represents BuiltinName also with YulIdentifier node type to avoid a breaking change in the JSON interface + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIdentifier"); + ret["name"] = m_dialect.builtin(_node.handle).name; + return ret; +} + Json AsmJsonConverter::operator()(Assignment const& _node) const { yulAssert(_node.variableNames.size() >= 1, "Invalid assignment syntax"); @@ -96,7 +106,7 @@ Json AsmJsonConverter::operator()(Assignment const& _node) const Json AsmJsonConverter::operator()(FunctionCall const& _node) const { Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionCall"); - ret["functionName"] = (*this)(_node.functionName); + ret["functionName"] = std::visit(*this, _node.functionName); ret["arguments"] = vectorOfVariantsToJson(_node.arguments); return ret; } diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index 523825830f46..6705197f943f 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -33,6 +33,8 @@ namespace solidity::yul { +class Dialect; + /** * Converter of the yul AST into JSON format */ @@ -41,12 +43,14 @@ class AsmJsonConverter: public boost::static_visitor public: /// Create a converter to JSON for any block of inline assembly /// @a _sourceIndex to be used to abbreviate source name in the source locations - explicit AsmJsonConverter(std::optional _sourceIndex): m_sourceIndex(_sourceIndex) {} + AsmJsonConverter(Dialect const& _dialect, std::optional _sourceIndex): + m_dialect(_dialect), m_sourceIndex(_sourceIndex) {} Json operator()(Block const& _node) const; Json operator()(NameWithDebugData const& _node) const; Json operator()(Literal const& _node) const; Json operator()(Identifier const& _node) const; + Json operator()(BuiltinName const& _node) const; Json operator()(Assignment const& _node) const; Json operator()(VariableDeclaration const& _node) const; Json operator()(FunctionDefinition const& _node) const; @@ -66,6 +70,7 @@ class AsmJsonConverter: public boost::static_visitor template Json vectorOfVariantsToJson(std::vector const& vec) const; + Dialect const& m_dialect; std::optional const m_sourceIndex; }; diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 459d9d9becd5..a937be62fb7a 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -23,7 +23,9 @@ */ #include + #include +#include #include #include @@ -51,7 +53,7 @@ SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node) AST AsmJsonImporter::createAST(solidity::Json const& _node) { - return AST(createBlock(_node)); + return {m_dialect, createBlock(_node)}; } template @@ -255,7 +257,16 @@ FunctionCall AsmJsonImporter::createFunctionCall(Json const& _node) for (auto const& var: member(_node, "arguments")) functionCall.arguments.emplace_back(createExpression(var)); - functionCall.functionName = createIdentifier(member(_node, "functionName")); + auto const functionNameNode = member(_node, "functionName"); + auto const name = member(functionNameNode, "name").get(); + if (std::optional builtinHandle = m_dialect.findBuiltin(name)) + { + auto builtin = createAsmNode(functionNameNode); + builtin.handle = *builtinHandle; + functionCall.functionName = builtin; + } + else + functionCall.functionName = createIdentifier(functionNameNode); return functionCall; } diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index f3df8c178e9d..830e44b3acb1 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -32,13 +32,16 @@ namespace solidity::yul { +class Dialect; + /** * Component that imports an AST from json format to the internal format */ class AsmJsonImporter { public: - explicit AsmJsonImporter(std::vector> const& _sourceNames): + explicit AsmJsonImporter(Dialect const& _dialect, std::vector> const& _sourceNames): + m_dialect(_dialect), m_sourceNames(_sourceNames) {} @@ -73,6 +76,7 @@ class AsmJsonImporter yul::Break createBreak(Json const& _node); yul::Continue createContinue(Json const& _node); + Dialect const& m_dialect; std::vector> const& m_sourceNames; }; diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index d41b41a36a42..a6949d7f8bdb 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -125,11 +125,16 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanne m_scanner = _scanner; if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments) fetchDebugDataFromComment(); - return std::make_unique(parseBlock()); + return std::make_unique(m_dialect, parseBlock()); } - catch (FatalError const& error) + catch (FatalError const&) { - yulAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + yulAssert(false, "Unreported fatal error."); + } } return nullptr; @@ -147,12 +152,17 @@ void Parser::fetchDebugDataFromComment() { solAssert(m_sourceNames.has_value(), ""); + std::string_view commentLiteral = m_scanner->currentCommentLiteral(); + if (commentLiteral.empty()) + { + m_astIDFromComment = std::nullopt; + return; + } static std::regex const tagRegex = std::regex( R"~~((?:^|\s+)(@[a-zA-Z0-9\-_]+)(?:\s+|$))~~", // tag, e.g: @src std::regex_constants::ECMAScript | std::regex_constants::optimize ); - std::string_view commentLiteral = m_scanner->currentCommentLiteral(); std::match_results match; langutil::SourceLocation originLocation = m_locationFromComment; @@ -400,7 +410,7 @@ Statement Parser::parseStatement() // Options left: // Expression/FunctionCall // Assignment - std::variant elementary(parseLiteralOrIdentifier()); + std::variant elementary(parseLiteralOrIdentifier()); switch (currentToken()) { @@ -415,35 +425,47 @@ Statement Parser::parseStatement() Assignment assignment; assignment.debugData = debugDataOf(elementary); - while (true) + bool foundListEnd = false; + do { - if (!std::holds_alternative(elementary)) - { - auto const token = currentToken() == Token::Comma ? "," : ":="; - - fatalParserError( - 2856_error, - std::string("Variable name must precede \"") + - token + - "\"" + - (currentToken() == Token::Comma ? " in multiple assignment." : " in assignment.") - ); - } - - auto const& identifier = std::get(elementary); - - if (m_dialect.builtin(identifier.name)) - fatalParserError(6272_error, "Cannot assign to builtin function \"" + identifier.name.str() + "\"."); - - assignment.variableNames.emplace_back(identifier); - - if (currentToken() != Token::Comma) - break; - - expectToken(Token::Comma); - - elementary = parseLiteralOrIdentifier(); - } + std::visit(GenericVisitor{ + [&](Literal const&) + { + auto const token = currentToken() == Token::Comma ? "," : ":="; + + fatalParserError( + 2856_error, + std::string("Variable name must precede \"") + + token + + "\"" + + (currentToken() == Token::Comma ? " in multiple assignment." : " in assignment.") + ); + }, + [&](BuiltinName const& _builtin) + { + fatalParserError( + 6272_error, + fmt::format( + "Cannot assign to builtin function \"{}\".", + m_dialect.builtin(_builtin.handle).name + ) + ); + }, + [&](Identifier const& _identifier) + { + assignment.variableNames.emplace_back(_identifier); + + if (currentToken() != Token::Comma) + foundListEnd = true; + else + { + expectToken(Token::Comma); + elementary = parseLiteralOrIdentifier(); + } + } + }, elementary); + + } while (!foundListEnd); expectToken(Token::AssemblyAssign); @@ -470,7 +492,7 @@ Case Parser::parseCase() else if (currentToken() == Token::Case) { advance(); - std::variant literal = parseLiteralOrIdentifier(); + std::variant literal = parseLiteralOrIdentifier(); if (!std::holds_alternative(literal)) fatalParserError(4805_error, "Literal expected."); _case.value = std::make_unique(std::get(std::move(literal))); @@ -509,20 +531,25 @@ Expression Parser::parseExpression(bool _unlimitedLiteralArgument) { RecursionGuard recursionGuard(*this); - std::variant operation = parseLiteralOrIdentifier(_unlimitedLiteralArgument); + std::variant operation = parseLiteralOrIdentifier(_unlimitedLiteralArgument); return visit(GenericVisitor{ [&](Identifier& _identifier) -> Expression { if (currentToken() == Token::LParen) return parseCall(std::move(operation)); - if (m_dialect.builtin(_identifier.name)) - fatalParserError( - 7104_error, - nativeLocationOf(_identifier), - "Builtin function \"" + _identifier.name.str() + "\" must be called." - ); return std::move(_identifier); }, + [&](BuiltinName& _builtin) -> Expression + { + if (currentToken() == Token::LParen) + return parseCall(std::move(operation)); + fatalParserError( + 7104_error, + nativeLocationOf(_builtin), + "Builtin function \"" + m_dialect.builtin(_builtin.handle).name + "\" must be called." + ); + unreachable(); + }, [&](Literal& _literal) -> Expression { return std::move(_literal); @@ -530,16 +557,20 @@ Expression Parser::parseExpression(bool _unlimitedLiteralArgument) }, operation); } -std::variant Parser::parseLiteralOrIdentifier(bool _unlimitedLiteralArgument) +std::variant Parser::parseLiteralOrIdentifier(bool _unlimitedLiteralArgument) { RecursionGuard recursionGuard(*this); switch (currentToken()) { case Token::Identifier: { - Identifier identifier{createDebugData(), YulName{currentLiteral()}}; + std::variant literalOrIdentifier; + if (std::optional const builtinHandle = m_dialect.findBuiltin(currentLiteral())) + literalOrIdentifier = BuiltinName{createDebugData(), *builtinHandle}; + else + literalOrIdentifier = Identifier{createDebugData(), YulName{currentLiteral()}}; advance(); - return identifier; + return literalOrIdentifier; } case Token::StringLiteral: case Token::HexStringLiteral: @@ -666,35 +697,45 @@ FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -FunctionCall Parser::parseCall(std::variant&& _initialOp) +FunctionCall Parser::parseCall(std::variant&& _initialOp) { RecursionGuard recursionGuard(*this); - if (!std::holds_alternative(_initialOp)) - fatalParserError(9980_error, "Function name expected."); + std::function isUnlimitedLiteralArgument = [](size_t) -> bool { return false; }; + FunctionCall functionCall; + std::visit(GenericVisitor{ + [&](Literal const&) { fatalParserError(9980_error, "Function name expected."); }, + [&](Identifier const& _identifier) + { + functionCall.debugData = _identifier.debugData; + functionCall.functionName = _identifier; + }, + [&](BuiltinName const& _builtin) + { + isUnlimitedLiteralArgument = [builtinFunction=m_dialect.builtin(_builtin.handle)](size_t _index) { + if (_index < builtinFunction.literalArguments.size()) + return builtinFunction.literalArgument(_index).has_value(); + return false; + }; + functionCall.debugData = _builtin.debugData; + functionCall.functionName = _builtin; + } + }, _initialOp); - FunctionCall ret; - ret.functionName = std::move(std::get(_initialOp)); - ret.debugData = ret.functionName.debugData; - auto const isUnlimitedLiteralArgument = [f=m_dialect.builtin(ret.functionName.name)](size_t const index) { - if (f && index < f->literalArguments.size()) - return f->literalArgument(index).has_value(); - return false; - }; size_t argumentIndex {0}; expectToken(Token::LParen); if (currentToken() != Token::RParen) { - ret.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); + functionCall.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); while (currentToken() != Token::RParen) { expectToken(Token::Comma); - ret.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); + functionCall.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); } } - updateLocationEndFrom(ret.debugData, currentLocation()); + updateLocationEndFrom(functionCall.debugData, currentLocation()); expectToken(Token::RParen); - return ret; + return functionCall; } NameWithDebugData Parser::parseNameWithDebugData() @@ -718,8 +759,14 @@ NameWithDebugData Parser::parseNameWithDebugData() YulName Parser::expectAsmIdentifier() { YulName name{currentLiteral()}; - if (currentToken() == Token::Identifier && m_dialect.builtin(name)) - fatalParserError(5568_error, "Cannot use builtin function name \"" + name.str() + "\" as identifier name."); + if (currentToken() == Token::Identifier && m_dialect.findBuiltin(name.str())) + // Non-fatal. We'll continue and wrongly parse it as an identifier. May lead to some spurious + // errors after this point, but likely also much more useful ones. + m_errorReporter.parserError( + 5568_error, + currentLocation(), + "Cannot use builtin function name \"" + name.str() + "\" as identifier name." + ); // NOTE: We keep the expectation here to ensure the correct source location for the error above. expectToken(Token::Identifier); return name; @@ -743,7 +790,7 @@ void Parser::checkBreakContinuePosition(std::string const& _which) } } -bool Parser::isValidNumberLiteral(std::string const& _literal) +bool Parser::isValidNumberLiteral(std::string_view const _literal) { try { @@ -757,7 +804,7 @@ bool Parser::isValidNumberLiteral(std::string const& _literal) if (boost::starts_with(_literal, "0x")) return true; else - return _literal.find_first_not_of("0123456789") == std::string::npos; + return _literal.find_first_not_of("0123456789") == std::string_view::npos; } void Parser::raiseUnsupportedTypesError(SourceLocation const& _location) const diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index d4616a2a9508..75c1cba873f9 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -141,10 +141,10 @@ class Parser: public langutil::ParserBase Expression parseExpression(bool _unlimitedLiteralArgument = false); /// Parses an elementary operation, i.e. a literal, identifier, instruction or /// builtin function call (only the name). - std::variant parseLiteralOrIdentifier(bool _unlimitedLiteralArgument = false); + std::variant parseLiteralOrIdentifier(bool _unlimitedLiteralArgument = false); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); - FunctionCall parseCall(std::variant&& _initialOp); + FunctionCall parseCall(std::variant&& _index); NameWithDebugData parseNameWithDebugData(); YulName expectAsmIdentifier(); void raiseUnsupportedTypesError(langutil::SourceLocation const& _location) const; @@ -152,7 +152,7 @@ class Parser: public langutil::ParserBase /// Reports an error if we are currently not inside the body part of a for loop. void checkBreakContinuePosition(std::string const& _which); - static bool isValidNumberLiteral(std::string const& _literal); + static bool isValidNumberLiteral(std::string_view _literal); private: Dialect const& m_dialect; diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 5841fdfd3249..a3f7b4ca2b23 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -42,6 +43,16 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; +std::string AsmPrinter::format( + AST const& _ast, + std::optional>> const& _sourceIndexToName, + DebugInfoSelection const& _debugInfoSelection, + CharStreamProvider const* _soliditySourceProvider) +{ + return AsmPrinter{_ast.dialect(), _sourceIndexToName, _debugInfoSelection, _soliditySourceProvider}(_ast.root()); +} + + std::string AsmPrinter::operator()(Literal const& _literal) { yulAssert(validLiteral(_literal)); @@ -67,6 +78,11 @@ std::string AsmPrinter::operator()(Identifier const& _identifier) return formatDebugData(_identifier) + _identifier.name.str(); } +std::string AsmPrinter::operator()(BuiltinName const& _builtin) +{ + return formatDebugData(_builtin) + m_dialect.builtin(_builtin.handle).name; +} + std::string AsmPrinter::operator()(ExpressionStatement const& _statement) { std::string const locationComment = formatDebugData(_statement); @@ -135,7 +151,7 @@ std::string AsmPrinter::operator()(FunctionDefinition const& _functionDefinition std::string AsmPrinter::operator()(FunctionCall const& _functionCall) { std::string const locationComment = formatDebugData(_functionCall); - std::string const functionName = (*this)(_functionCall.functionName); + std::string const functionName = std::visit(*this, _functionCall.functionName); return locationComment + functionName + "(" + diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index cc17c6a04ce3..60a7f9a0f289 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -37,6 +37,8 @@ namespace solidity::yul { +class Dialect; + /** * Converts a parsed Yul AST into readable string representation. * Ignores source locations. @@ -44,11 +46,20 @@ namespace solidity::yul class AsmPrinter { public: + static std::string format( + AST const& _ast, + std::optional>> const& _sourceIndexToName = {}, + langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), + langutil::CharStreamProvider const* _soliditySourceProvider = nullptr + ); + explicit AsmPrinter( - std::optional>> _sourceIndexToName = {}, + Dialect const& _dialect, + std::optional>> const& _sourceIndexToName = {}, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ): + m_dialect(_dialect), m_debugInfoSelection(_debugInfoSelection), m_soliditySourceProvider(_soliditySourceProvider) { @@ -59,6 +70,7 @@ class AsmPrinter std::string operator()(Literal const& _literal); std::string operator()(Identifier const& _identifier); + std::string operator()(BuiltinName const& _builtin); std::string operator()(ExpressionStatement const& _expr); std::string operator()(Assignment const& _assignment); std::string operator()(VariableDeclaration const& _variableDeclaration); @@ -89,6 +101,7 @@ class AsmPrinter return formatDebugData(_node.debugData, !isExpression); } + Dialect const& m_dialect; std::map m_nameToSourceIndex; langutil::SourceLocation m_lastLocation = {}; langutil::DebugInfoSelection m_debugInfoSelection = {}; diff --git a/libsmtutil/Z3Loader.h b/libyul/Builtins.h similarity index 70% rename from libsmtutil/Z3Loader.h rename to libyul/Builtins.h index 5e755cb24b0a..8ee17de4b668 100644 --- a/libsmtutil/Z3Loader.h +++ b/libyul/Builtins.h @@ -18,21 +18,18 @@ #pragma once -namespace solidity::smtutil +#include + +namespace solidity::yul { -class Z3Loader +/// Handle to reference a builtin function in the AST +struct BuiltinHandle { -public: - Z3Loader(Z3Loader const&) = delete; - Z3Loader& operator=(Z3Loader const&) = delete; - static Z3Loader const& get(); - void* loadSymbol(char const* _name) const; - bool available() const; -private: - Z3Loader(); - ~Z3Loader(); - void* m_handle = nullptr; + size_t id; + + bool operator==(BuiltinHandle const& _other) const { return id == _other.id; } + bool operator<(BuiltinHandle const& _other) const { return id < _other.id; } }; -} \ No newline at end of file +} diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index f621b2089e9b..fc3302a82332 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -7,6 +7,8 @@ add_library(yul AST.h AST.cpp ASTForward.h + ASTLabelRegistry.cpp + ASTLabelRegistry.h AsmJsonConverter.h AsmJsonConverter.cpp AsmJsonImporter.h @@ -15,6 +17,7 @@ add_library(yul AsmParser.h AsmPrinter.cpp AsmPrinter.h + Builtins.h YulStack.h YulStack.cpp CompilabilityChecker.cpp @@ -48,6 +51,8 @@ add_library(yul backends/evm/AsmCodeGen.h backends/evm/ConstantOptimiser.cpp backends/evm/ConstantOptimiser.h + backends/evm/ControlFlow.cpp + backends/evm/ControlFlow.h backends/evm/ControlFlowGraph.h backends/evm/ControlFlowGraphBuilder.cpp backends/evm/ControlFlowGraphBuilder.h @@ -65,6 +70,8 @@ add_library(yul backends/evm/NoOutputAssembly.cpp backends/evm/OptimizedEVMCodeTransform.cpp backends/evm/OptimizedEVMCodeTransform.h + backends/evm/SSACFGLiveness.cpp + backends/evm/SSACFGLiveness.h backends/evm/SSACFGLoopNestingForest.cpp backends/evm/SSACFGLoopNestingForest.h backends/evm/SSACFGTopologicalSort.cpp diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 8ece236bf425..cc46ecb77000 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -31,20 +31,19 @@ using namespace solidity::yul; using namespace solidity::util; CompilabilityChecker::CompilabilityChecker( - Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation ) { yulAssert(_object.hasCode()); - if (auto const* evmDialect = dynamic_cast(&_dialect)) + if (auto const* evmDialect = dynamic_cast(_object.dialect())) { NoOutputEVMDialect noOutputDialect(*evmDialect); yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( noOutputDialect, _object.code()->root(), - _object.qualifiedDataNames() + _object.summarizeStructure() ); BuiltinContext builtinContext; diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index 160aeca8c783..1b7bf65a5b1b 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -45,7 +45,6 @@ namespace solidity::yul struct CompilabilityChecker { CompilabilityChecker( - Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation ); diff --git a/libyul/ControlFlowSideEffects.h b/libyul/ControlFlowSideEffects.h index d4debab9381a..8de6b53d4832 100644 --- a/libyul/ControlFlowSideEffects.h +++ b/libyul/ControlFlowSideEffects.h @@ -18,6 +18,9 @@ #pragma once +#include +#include + namespace solidity::yul { @@ -44,6 +47,33 @@ struct ControlFlowSideEffects { return (canTerminate || canRevert) && !canContinue; } + + static ControlFlowSideEffects fromInstruction(evmasm::Instruction _instruction) + { + ControlFlowSideEffects controlFlowSideEffects; + if (evmasm::SemanticInformation::terminatesControlFlow(_instruction)) + { + controlFlowSideEffects.canContinue = false; + if (evmasm::SemanticInformation::reverts(_instruction)) + { + controlFlowSideEffects.canTerminate = false; + controlFlowSideEffects.canRevert = true; + } + else + { + controlFlowSideEffects.canTerminate = true; + controlFlowSideEffects.canRevert = false; + } + } + + return controlFlowSideEffects; + } + + /// @returns the worst-case control flow side effects. + static ControlFlowSideEffects worst() + { + return ControlFlowSideEffects{true, true, true}; + } }; } diff --git a/libyul/ControlFlowSideEffectsCollector.cpp b/libyul/ControlFlowSideEffectsCollector.cpp index 471a164e523b..28089b029fca 100644 --- a/libyul/ControlFlowSideEffectsCollector.cpp +++ b/libyul/ControlFlowSideEffectsCollector.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -271,7 +272,7 @@ ControlFlowNode const* ControlFlowSideEffectsCollector::nextProcessableNode(Func ControlFlowSideEffects const& ControlFlowSideEffectsCollector::sideEffects(FunctionCall const& _call) const { - if (auto const* builtin = m_dialect.builtin(_call.functionName.name)) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_call.functionName, m_dialect)) return builtin->controlFlowSideEffects; else return m_functionSideEffects.at(m_functionReferences.at(&_call)); diff --git a/libyul/ControlFlowSideEffectsCollector.h b/libyul/ControlFlowSideEffectsCollector.h index 5a1c76297012..2ef7a4bfa003 100644 --- a/libyul/ControlFlowSideEffectsCollector.h +++ b/libyul/ControlFlowSideEffectsCollector.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct ControlFlowNode { diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 3589e953f60f..2afd4a579288 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -21,13 +21,16 @@ #pragma once -#include +#include #include +#include #include +#include -#include -#include #include +#include +#include +#include namespace solidity::yul { @@ -38,7 +41,7 @@ struct Literal; struct BuiltinFunction { - YulName name; + std::string name; size_t numParameters; size_t numReturns; SideEffects sideEffects; @@ -54,32 +57,36 @@ struct BuiltinFunction } }; -struct Dialect +class Dialect { +public: /// Noncopiable. Dialect(Dialect const&) = delete; Dialect& operator=(Dialect const&) = delete; - /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. - virtual BuiltinFunction const* builtin(YulName /*_name*/) const { return nullptr; } + /// Finds a builtin by name and returns the corresponding handle. + /// @returns Builtin handle or null if the name does not match any builtin in the dialect. + virtual std::optional findBuiltin(std::string_view /*_name*/) const { return std::nullopt; } + + /// Retrieves the description of a builtin function by its handle. + /// Note that handles are dialect-specific and can be used only with a dialect that created them. + virtual BuiltinFunction const& builtin(BuiltinHandle const&) const { yulAssert(false); } /// @returns true if the identifier is reserved. This includes the builtins too. - virtual bool reservedIdentifier(YulName _name) const { return builtin(_name) != nullptr; } + virtual bool reservedIdentifier(std::string_view _name) const { return findBuiltin(_name).has_value(); } - virtual BuiltinFunction const* discardFunction() const { return nullptr; } - virtual BuiltinFunction const* equalityFunction() const { return nullptr; } - virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; } + virtual std::optional discardFunctionHandle() const { return std::nullopt; } + virtual std::optional equalityFunctionHandle() const { return std::nullopt; } + virtual std::optional booleanNegationFunctionHandle() const { return std::nullopt; } - virtual BuiltinFunction const* memoryStoreFunction() const { return nullptr; } - virtual BuiltinFunction const* memoryLoadFunction() const { return nullptr; } - virtual BuiltinFunction const* storageStoreFunction() const { return nullptr; } - virtual BuiltinFunction const* storageLoadFunction() const { return nullptr; } - virtual YulName hashFunction() const { return YulName{}; } + virtual std::optional memoryStoreFunctionHandle() const { return std::nullopt; } + virtual std::optional memoryLoadFunctionHandle() const { return std::nullopt; } + virtual std::optional storageStoreFunctionHandle() const { return std::nullopt; } + virtual std::optional storageLoadFunctionHandle() const { return std::nullopt; } + virtual std::optional hashFunctionHandle() const { return std::nullopt; } Literal zeroLiteral() const; - virtual std::set fixedFunctionNames() const { return {}; } - Dialect() = default; virtual ~Dialect() = default; }; diff --git a/libyul/Exceptions.h b/libyul/Exceptions.h index f92268180971..4f08e192f788 100644 --- a/libyul/Exceptions.h +++ b/libyul/Exceptions.h @@ -36,7 +36,7 @@ namespace solidity::yul struct YulException: virtual util::Exception {}; struct OptimizerException: virtual YulException {}; struct CodegenException: virtual YulException {}; -struct YulAssertion: virtual YulException {}; +struct YulAssertion: virtual util::Exception {}; struct StackTooDeepError: virtual YulException { diff --git a/libyul/FunctionReferenceResolver.cpp b/libyul/FunctionReferenceResolver.cpp index 99e83c2130e7..bf3f536a49a8 100644 --- a/libyul/FunctionReferenceResolver.cpp +++ b/libyul/FunctionReferenceResolver.cpp @@ -34,15 +34,17 @@ FunctionReferenceResolver::FunctionReferenceResolver(Block const& _ast) void FunctionReferenceResolver::operator()(FunctionCall const& _functionCall) { - for (auto&& scope: m_scopes | ranges::views::reverse) - if (FunctionDefinition const** function = util::valueOrNullptr(scope, _functionCall.functionName.name)) + if (!isBuiltinFunctionCall(_functionCall)) + for (auto&& scope: m_scopes | ranges::views::reverse) { - m_functionReferences[&_functionCall] = *function; - break; + yulAssert(std::holds_alternative(_functionCall.functionName)); + if (FunctionDefinition const** function = util::valueOrNullptr(scope, std::get(_functionCall.functionName).name)) + { + m_functionReferences[&_functionCall] = *function; + break; + } } - // If we did not find anything, it was a builtin call. - ASTWalker::operator()(_functionCall); } diff --git a/libyul/Object.cpp b/libyul/Object.cpp index c6ba5311ad5c..54ec6a3cfd7a 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -49,13 +49,15 @@ std::string Object::toString( ) const { yulAssert(hasCode(), "No code"); + yulAssert(dialect(), "No dialect"); yulAssert(debugData, "No debug data"); - std::string inner = "code " + AsmPrinter( + std::string inner = "code " + AsmPrinter::format( + *code(), debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider - )(code()->root()); + ); for (auto const& obj: subObjects) inner += "\n" + obj->toString(_debugInfoSelection, _soliditySourceProvider); @@ -93,10 +95,11 @@ std::string ObjectDebugData::formatUseSrcComment() const Json Object::toJson() const { yulAssert(hasCode(), "No code"); + yulAssert(dialect(), "No dialect"); Json codeJson; codeJson["nodeType"] = "YulCode"; - codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(code()->root()); + codeJson["block"] = AsmJsonConverter(*dialect(), 0 /* sourceIndex */)(code()->root()); Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) @@ -110,29 +113,60 @@ Json Object::toJson() const return ret; } -std::set Object::qualifiedDataNames() const + +std::set Object::Structure::topLevelSubObjectNames() const +{ + std::set topLevelObjectNames; + + for (auto const& path: objectPaths) + if (!util::contains(path, '.') && path != objectName) + topLevelObjectNames.insert(path); + + return topLevelObjectNames; +} + +Object::Structure Object::summarizeStructure() const { - std::set qualifiedNames = + Structure structure; + + structure.objectPaths = name.empty() || util::contains(name, '.') ? std::set{} : std::set{name}; + + structure.objectName = name; + for (std::shared_ptr const& subObjectNode: subObjects) { - yulAssert(qualifiedNames.count(subObjectNode->name) == 0, ""); + yulAssert(!structure.contains(subObjectNode->name)); if (util::contains(subObjectNode->name, '.')) continue; - qualifiedNames.insert(subObjectNode->name); + if (auto const* subObject = dynamic_cast(subObjectNode.get())) - for (auto const& subSubObj: subObject->qualifiedDataNames()) + { + structure.objectPaths.insert(subObjectNode->name); + + auto const subObjectStructure = subObject->summarizeStructure(); + + for (auto const& subSubObj: subObjectStructure.objectPaths) if (subObject->name != subSubObj) { - yulAssert(qualifiedNames.count(subObject->name + "." + subSubObj) == 0, ""); - qualifiedNames.insert(subObject->name + "." + subSubObj); + yulAssert(!structure.contains(subObject->name + "." + subSubObj)); + structure.objectPaths.insert(subObject->name + "." + subSubObj); + } + for (auto const& subSubObjData: subObjectStructure.dataPaths) + if (subObject->name != subSubObjData) + { + yulAssert(!structure.contains(subObject->name + "." + subSubObjData)); + structure.dataPaths.insert(subObject->name + "." + subSubObjData); } + } + else + structure.dataPaths.insert(subObjectNode->name); } - yulAssert(qualifiedNames.count("") == 0, ""); - return qualifiedNames; + yulAssert(!structure.contains("")); + return structure; } std::vector Object::pathToSubObject(std::string_view _qualifiedName) const @@ -208,3 +242,10 @@ bool Object::hasContiguousSourceIndices() const solAssert(maxSourceIndex + 1 >= indices.size()); return indices.size() == 0 || indices.size() == maxSourceIndex + 1; } + +Dialect const* Object::dialect() const +{ + if (!m_code) + return nullptr; + return &m_code->dialect(); +} diff --git a/libyul/Object.h b/libyul/Object.h index 230f97866e09..c865b906ed37 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -21,8 +21,8 @@ #pragma once -#include #include +#include #include #include @@ -36,12 +36,12 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct AsmAnalysisInfo; using SourceNameMap = std::map>; -struct Object; +class Object; /** * Generic base class for both Yul objects and Yul data. @@ -88,7 +88,7 @@ struct ObjectDebugData /** * Yul code and data object container. */ -struct Object: public ObjectNode +class Object: public ObjectNode { public: /// @returns a (parseable) string representation. @@ -98,10 +98,32 @@ struct Object: public ObjectNode ) const override; /// @returns a compact JSON representation of the AST. Json toJson() const override; + + /// Summarizes the structure of the subtree rooted at a given object, + /// in particular the paths that can be used from within to refer to nested nodes (objects and data). + struct Structure + { + /// The name of the object + std::string objectName; + /// Available dot-separated paths to nested objects (relative to current object). + std::set objectPaths; + /// Available dot-separated paths to nested data entries (relative to current object). + std::set dataPaths; + + /// Checks if a path is available. + bool contains(std::string const& _path) const { return containsObject(_path) || containsData(_path); } + /// Checks if a path is available and leads to an object. + bool containsObject(std::string const& _path) const { return objectPaths.count(_path) > 0; } + /// Checks if a path is available and leads to a data entry. + bool containsData(std::string const& _path) const { return dataPaths.count(_path) > 0; } + + std::set topLevelSubObjectNames() const; + }; + /// @returns the set of names of data objects accessible from within the code of /// this object, including the name of object itself /// Handles all names containing dots as reserved identifiers, not accessible as data. - std::set qualifiedDataNames() const; + Structure summarizeStructure() const; /// @returns vector of subIDs if possible to reach subobject with @a _qualifiedName, throws otherwise /// For "B.C" should return vector of two values if success (subId of B and subId of C in B). @@ -139,6 +161,8 @@ struct Object: public ObjectNode /// @returns the name of the special metadata data object. static std::string metadataName() { return ".metadata"; } + Dialect const* dialect() const; + private: std::shared_ptr m_code; }; diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 511fc979ddb0..a09e88791577 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -90,7 +90,6 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool } OptimiserSuite::run( - dialect, meter.get(), _object, _settings.optimizeStackAllocation, @@ -118,15 +117,15 @@ void ObjectOptimizer::overwriteWithOptimizedObject(util::h256 _cacheKey, Object& CachedObject const& cachedObject = m_cachedObjects.at(_cacheKey); yulAssert(cachedObject.optimizedAST); - _object.setCode(std::make_shared(ASTCopier{}.translate(*cachedObject.optimizedAST))); + yulAssert(cachedObject.dialect); + _object.setCode(std::make_shared(*cachedObject.dialect, ASTCopier{}.translate(*cachedObject.optimizedAST))); yulAssert(_object.code()); + yulAssert(_object.dialect()); // There's no point in caching AnalysisInfo because it references AST nodes. It can't be shared // by multiple ASTs and it's easier to recalculate it than properly clone it. - yulAssert(cachedObject.dialect); _object.analysisInfo = std::make_shared( AsmAnalyzer::analyzeStrictAssertCorrect( - *cachedObject.dialect, _object ) ); @@ -142,6 +141,7 @@ std::optional ObjectOptimizer::calculateCacheKey( ) { AsmPrinter asmPrinter( + languageToDialect(_settings.language, _settings.evmVersion, _settings.eofVersion), _debugData.sourceNames, DebugInfoSelection::All() ); @@ -154,12 +154,13 @@ std::optional ObjectOptimizer::calculateCacheKey( rawKey += keccak256(asmPrinter(_ast)).asBytes(); rawKey += keccak256(_debugData.formatUseSrcComment()).asBytes(); rawKey += h256(u256(_settings.language)).asBytes(); - rawKey += FixedHash<1>(uint8_t(_settings.optimizeStackAllocation ? 0 : 1)).asBytes(); + static_assert(static_cast(static_cast(2)) == 1); + rawKey += FixedHash<1>(static_cast(_settings.optimizeStackAllocation)).asBytes(); rawKey += h256(u256(_settings.expectedExecutionsPerDeployment)).asBytes(); - rawKey += FixedHash<1>(uint8_t(_isCreation ? 0 : 1)).asBytes(); + rawKey += FixedHash<1>(static_cast(_isCreation)).asBytes(); rawKey += keccak256(_settings.evmVersion.name()).asBytes(); yulAssert(!_settings.eofVersion.has_value() || *_settings.eofVersion > 0); - rawKey += FixedHash<1>(uint8_t(_settings.eofVersion ? 0 : *_settings.eofVersion)).asBytes(); + rawKey += FixedHash<1>(static_cast(_settings.eofVersion ? *_settings.eofVersion : 0)).asBytes(); rawKey += keccak256(_settings.yulOptimiserSteps).asBytes(); rawKey += keccak256(_settings.yulOptimiserCleanupSteps).asBytes(); diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 123dedcb483d..dfa604941ab5 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -63,9 +63,14 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca expectToken(Token::EOS); return object; } - catch (FatalError const& error) + catch (FatalError const&) { - yulAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + yulAssert(false, "Unreported fatal error."); + } } return nullptr; } @@ -198,7 +203,7 @@ void ObjectParser::parseData(Object& _containingObject) std::string ObjectParser::parseUniqueName(Object const* _containingObject) { expectToken(Token::StringLiteral, false); - auto const name = currentLiteral(); + std::string const name{currentLiteral()}; if (name.empty()) parserError(3287_error, "Object name cannot be empty."); else if (_containingObject && _containingObject->name == name) diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index 4bbfb42437b0..e7caf1b2dff4 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -21,11 +21,15 @@ #include +#include + #include +#include #include #include #include +#include #include @@ -237,3 +241,40 @@ bool SwitchCaseCompareByLiteralValue::operator()(Case const* _lhs, Case const* _ yulAssert(_lhs && _rhs, ""); return Less{}(_lhs->value.get(), _rhs->value.get()); } + +std::string_view yul::resolveFunctionName(FunctionName const& _functionName, Dialect const& _dialect) +{ + GenericVisitor visitor{ + [&](Identifier const& _identifier) -> std::string const& { return _identifier.name.str(); }, + [&](BuiltinName const& _builtin) -> std::string const& { return _dialect.builtin(_builtin.handle).name; } + }; + return std::visit(visitor, _functionName); +} + +BuiltinFunction const* yul::resolveBuiltinFunction(FunctionName const& _functionName, Dialect const& _dialect) +{ + GenericVisitor visitor{ + [&](Identifier const&) -> BuiltinFunction const* { return nullptr; }, + [&](BuiltinName const& _builtin) -> BuiltinFunction const* { return &_dialect.builtin(_builtin.handle); } + }; + return std::visit(visitor, _functionName); +} + +BuiltinFunctionForEVM const* yul::resolveBuiltinFunctionForEVM(FunctionName const& _functionName, EVMDialect const& _dialect) +{ + GenericVisitor visitor{ + [&](Identifier const&) -> BuiltinFunctionForEVM const* { return nullptr; }, + [&](BuiltinName const& _builtin) -> BuiltinFunctionForEVM const* { return &_dialect.builtin(_builtin.handle); } + }; + return std::visit(visitor, _functionName); +} + +FunctionHandle yul::functionNameToHandle(FunctionName const& _functionName) +{ + GenericVisitor visitor{ + [&](Identifier const& _identifier) -> FunctionHandle { return _identifier.name; }, + [&](BuiltinName const& _builtin) -> FunctionHandle { return _builtin.handle; } + }; + return std::visit(visitor, _functionName); +} + diff --git a/libyul/Utilities.h b/libyul/Utilities.h index 434c5e9c5a3a..64b5f456ac1f 100644 --- a/libyul/Utilities.h +++ b/libyul/Utilities.h @@ -30,6 +30,11 @@ namespace solidity::yul { +class Dialect; +class EVMDialect; +struct BuiltinFunction; +struct BuiltinFunctionForEVM; + std::string reindent(std::string const& _code); LiteralValue valueOfNumberLiteral(std::string_view _literal); @@ -83,4 +88,10 @@ struct SwitchCaseCompareByLiteralValue bool operator()(Case const* _lhsCase, Case const* _rhsCase) const; }; +std::string_view resolveFunctionName(FunctionName const& _functionName, Dialect const& _dialect); + +BuiltinFunction const* resolveBuiltinFunction(FunctionName const& _functionName, Dialect const& _dialect); +BuiltinFunctionForEVM const* resolveBuiltinFunctionForEVM(FunctionName const& _functionName, EVMDialect const& _dialect); +FunctionHandle functionNameToHandle(FunctionName const& _functionName); + } diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp index 3f347fcf4f91..65c0805f984a 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -31,7 +31,7 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; -YulControlFlowGraphExporter::YulControlFlowGraphExporter(ControlFlow const& _controlFlow): m_controlFlow(_controlFlow) +YulControlFlowGraphExporter::YulControlFlowGraphExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness): m_controlFlow(_controlFlow), m_liveness(_liveness) { } @@ -58,45 +58,45 @@ std::string YulControlFlowGraphExporter::varToString(SSACFG const& _cfg, SSACFG: Json YulControlFlowGraphExporter::run() { + if (m_liveness) + yulAssert(&m_liveness->controlFlow.get() == &m_controlFlow); + Json yulObjectJson = Json::object(); - yulObjectJson["blocks"] = exportBlock(*m_controlFlow.mainGraph, SSACFG::BlockId{0}); + yulObjectJson["blocks"] = exportBlock(*m_controlFlow.mainGraph, SSACFG::BlockId{0}, m_liveness ? m_liveness->mainLiveness.get() : nullptr); Json functionsJson = Json::object(); + size_t index = 0; for (auto const& [function, functionGraph]: m_controlFlow.functionGraphMapping) - functionsJson[function->name.str()] = exportFunction(*functionGraph); + functionsJson[function->name.str()] = exportFunction(*functionGraph, m_liveness ? m_liveness->functionLiveness[index++].get() : nullptr); yulObjectJson["functions"] = functionsJson; return yulObjectJson; } -Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg) +Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg, SSACFGLiveness const* _liveness) { Json functionJson = Json::object(); functionJson["type"] = "Function"; functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); - functionJson["arguments"] = Json::array(); - for (auto const& [arg, valueId]: _cfg.arguments) - functionJson["arguments"].emplace_back(arg.get().name.str()); - functionJson["returns"] = Json::array(); - for (auto const& ret: _cfg.returns) - functionJson["returns"].emplace_back(ret.get().name.str()); - functionJson["blocks"] = exportBlock(_cfg, _cfg.entry); + static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", std::get<1>(_arg).value); }; + functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; + functionJson["numReturns"] = _cfg.returns.size(); + functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness); return functionJson; } -Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId) +Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, SSACFGLiveness const* _liveness) { Json blocksJson = Json::array(); util::BreadthFirstSearch bfs{{{_entryId}}}; bfs.run([&](SSACFG::BlockId _blockId, auto _addChild) { auto const& block = _cfg.block(_blockId); // Convert current block to JSON - Json blockJson = toJson(_cfg, _blockId); + Json blockJson = toJson(_cfg, _blockId, _liveness); Json exitBlockJson = Json::object(); std::visit(util::GenericVisitor{ [&](SSACFG::BasicBlock::MainExit const&) { - exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; exitBlockJson["type"] = "MainExit"; }, [&](SSACFG::BasicBlock::Jump const& _jump) @@ -115,12 +115,10 @@ Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockI _addChild(_conditionalJump.nonZero); }, [&](SSACFG::BasicBlock::FunctionReturn const& _return) { - exitBlockJson["instructions"] = toJson(_cfg, _return.returnValues); - exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; + exitBlockJson["returnValues"] = toJson(_cfg, _return.returnValues); exitBlockJson["type"] = "FunctionReturn"; }, [&](SSACFG::BasicBlock::Terminated const&) { - exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; exitBlockJson["type"] = "Terminated"; }, [&](SSACFG::BasicBlock::JumpTable const&) { @@ -134,12 +132,25 @@ Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockI return blocksJson; } -Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId) +Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness) { + auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; + Json blockJson = Json::object(); auto const& block = _cfg.block(_blockId); blockJson["id"] = "Block" + std::to_string(_blockId.value); + if (_liveness) + { + Json livenessJson = Json::object(); + livenessJson["in"] = _liveness->liveIn(_blockId) + | ranges::views::transform(valueToString) + | ranges::to(); + livenessJson["out"] = _liveness->liveOut(_blockId) + | ranges::views::transform(valueToString) + | ranges::to(); + blockJson["liveness"] = livenessJson; + } blockJson["instructions"] = Json::array(); if (!block.phis.empty()) { @@ -193,7 +204,7 @@ Json YulControlFlowGraphExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG: if (!builtinArgsJson.empty()) opJson["builtinArgs"] = builtinArgsJson; - opJson["op"] = _call.builtin.get().name.str(); + opJson["op"] = _call.builtin.get().name; }, }, _operation.kind); diff --git a/libyul/YulControlFlowGraphExporter.h b/libyul/YulControlFlowGraphExporter.h index 37520e194b21..91f9d040e404 100644 --- a/libyul/YulControlFlowGraphExporter.h +++ b/libyul/YulControlFlowGraphExporter.h @@ -28,15 +28,16 @@ using namespace yul; class YulControlFlowGraphExporter { public: - YulControlFlowGraphExporter(ControlFlow const& _controlFlow); + YulControlFlowGraphExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness=nullptr); Json run(); - Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _blockId); - Json exportFunction(SSACFG const& _cfg); + Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness); + Json exportFunction(SSACFG const& _cfg, SSACFGLiveness const* _liveness); std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var); private: ControlFlow const& m_controlFlow; - Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId); + ControlFlowLiveness const* m_liveness; + Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness); Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation); Json toJson(SSACFG const& _cfg, std::vector const& _values); }; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 8b559e23f46d..5adb8d6d5c9a 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source) catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); + return false; } if (!m_errorReporter.hasErrors()) @@ -94,7 +96,7 @@ void YulStack::optimize() { if ( !m_optimiserSettings.runYulOptimiser && - yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion, m_eofVersion), *m_parserResult) + yul::MSizeFinder::containsMSize(*m_parserResult) ) return; @@ -166,7 +168,7 @@ bool YulStack::analyzeParsed(Object& _object) m_errorReporter, languageToDialect(m_language, m_evmVersion, m_eofVersion), {}, - _object.qualifiedDataNames() + _object.summarizeStructure() ); bool success = false; @@ -192,19 +194,7 @@ bool YulStack::analyzeParsed(Object& _object) void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const { - EVMDialect const* dialect = nullptr; - switch (m_language) - { - case Language::Assembly: - case Language::StrictAssembly: - dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion, m_eofVersion); - break; - default: - yulAssert(false, "Invalid language."); - break; - } - - EVMObjectCompiler::compile(*m_parserResult, _assembly, *dialect, _optimize, m_eofVersion); + EVMObjectCompiler::compile(*m_parserResult, _assembly, _optimize); } void YulStack::reparse() @@ -260,9 +250,14 @@ MachineAssemblyObject YulStack::assemble(Machine _machine) std::pair YulStack::assembleWithDeployed(std::optional _deployName) { + yulAssert(m_charStream); + auto [creationAssembly, deployedAssembly] = assembleEVMWithDeployed(_deployName); - yulAssert(creationAssembly, ""); - yulAssert(m_charStream, ""); + if (!creationAssembly) + { + yulAssert(!deployedAssembly); + return {MachineAssemblyObject{}, MachineAssemblyObject{}}; + } MachineAssemblyObject creationObject; MachineAssemblyObject deployedObject; @@ -279,11 +274,15 @@ YulStack::assembleWithDeployed(std::optional _deployName) {{m_charStream->name(), 0}} ); } + if (debugInfoSelection().ethdebug) + creationObject.ethdebug = evmasm::ethdebug::program(creationObject.assembly->name(), 0, creationObject.assembly.get(), *creationObject.bytecode.get()); if (deployedAssembly) { deployedObject.bytecode = std::make_shared(deployedAssembly->assemble()); deployedObject.assembly = deployedAssembly; + if (debugInfoSelection().ethdebug) + deployedObject.ethdebug = evmasm::ethdebug::program(deployedObject.assembly->name(), 0, deployedObject.assembly.get(), *deployedObject.bytecode.get()); solAssert(deployedAssembly->codeSections().size() == 1); deployedObject.sourceMappings = std::make_unique( evmasm::AssemblyItem::computeSourceMapping( @@ -293,9 +292,15 @@ YulStack::assembleWithDeployed(std::optional _deployName) ); } } + catch (Error const& _error) + { + m_errorReporter.codeGenerationError(_error); + return {MachineAssemblyObject{}, MachineAssemblyObject{}}; + } catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); + return {MachineAssemblyObject{}, MachineAssemblyObject{}}; } return {std::move(creationObject), std::move(deployedObject)}; @@ -317,13 +322,13 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) // it with the minimal steps required to avoid "stack too deep". bool optimize = m_optimiserSettings.optimizeStackAllocation || ( !m_optimiserSettings.runYulOptimiser && - !yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion, m_eofVersion), *m_parserResult) + !yul::MSizeFinder::containsMSize(*m_parserResult) ); try { compileEVM(adapter, optimize); - assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings, m_evmVersion)); + assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings)); std::optional subIndex; @@ -349,12 +354,18 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) return {std::make_shared(assembly), std::make_shared(runtimeAssembly)}; } } + catch (Error const& _error) + { + m_errorReporter.codeGenerationError(_error); + return {nullptr, nullptr}; + } catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); + return {nullptr, nullptr}; } - return {std::make_shared(assembly), {}}; + return {std::make_shared(assembly), nullptr}; } std::string YulStack::print() const @@ -362,7 +373,7 @@ std::string YulStack::print() const yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->hasCode(), ""); - return m_parserResult->toString( + return (m_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "") + m_parserResult->toString( m_debugInfoSelection, m_soliditySourceProvider ) + "\n"; @@ -389,7 +400,8 @@ Json YulStack::cfgJson() const languageToDialect(m_language, m_evmVersion, m_eofVersion), _object.code()->root() ); - YulControlFlowGraphExporter exporter(*controlFlow); + std::unique_ptr liveness = std::make_unique(*controlFlow); + YulControlFlowGraphExporter exporter(*controlFlow, liveness.get()); return exporter.run(); }; @@ -402,7 +414,7 @@ Json YulStack::cfgJson() const subObjectsJson[subObject->name] = exportCFGFromObject(*subObject); subObjectsJson["type"] = "subObject"; if (!subObject->subObjects.empty()) - subObjectsJson["subObjects"] = exportCFGFromSubObjects(subObject->subObjects); + subObjectsJson[subObject->name]["subObjects"] = exportCFGFromSubObjects(subObject->subObjects); } return subObjectsJson; }; @@ -411,7 +423,8 @@ Json YulStack::cfgJson() const Json jsonObject = Json::object(); jsonObject[object.name] = exportCFGFromObject(object); jsonObject["type"] = "Object"; - jsonObject["subObjects"] = exportCFGFromSubObjects(object.subObjects); + if (!object.subObjects.empty()) + jsonObject[object.name]["subObjects"] = exportCFGFromSubObjects(object.subObjects); return jsonObject; } @@ -423,8 +436,18 @@ std::shared_ptr YulStack::parserResult() const return m_parserResult; } +Dialect const& YulStack::dialect() const +{ + yulAssert(m_stackState >= AnalysisSuccessful); + yulAssert(m_parserResult && m_parserResult->dialect()); + return *m_parserResult->dialect(); +} + void YulStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) { - solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); + yulAssert(m_charStream); + yulAssert(_error.comment(), "Errors must include a message for the user."); + if (_error.sourceLocation().sourceName) + yulAssert(*_error.sourceLocation().sourceName == m_charStream->name()); m_errorReporter.unimplementedFeatureError(1920_error, _error.sourceLocation(), *_error.comment()); } diff --git a/libyul/YulStack.h b/libyul/YulStack.h index de391f591044..e9d75b6ae9d9 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -25,6 +25,8 @@ #include #include #include +#include + #include #include @@ -58,6 +60,7 @@ struct MachineAssemblyObject std::shared_ptr bytecode; std::shared_ptr assembly; std::unique_ptr sourceMappings; + Json ethdebug = Json::object(); }; /* @@ -137,6 +140,7 @@ class YulStack: public langutil::CharStreamProvider /// @returns the errors generated during parsing, analysis (and potentially assembly). langutil::ErrorList const& errors() const { return m_errors; } bool hasErrors() const { return m_errorReporter.hasErrors(); } + bool hasErrorsWarningsOrInfos() const { return m_errorReporter.hasErrorsWarningsOrInfos(); } /// Pretty-print the input after having parsed it. std::string print() const; @@ -148,6 +152,8 @@ class YulStack: public langutil::CharStreamProvider /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; + Dialect const& dialect() const; + langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; } private: diff --git a/libyul/YulString.h b/libyul/YulString.h index bd9438e5abc9..d6c13f0d3751 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace solidity::yul @@ -51,7 +52,7 @@ class YulStringRepository return inst; } - Handle stringToHandle(std::string const& _string) + Handle stringToHandle(std::string_view const _string) { if (_string.empty()) return { 0, emptyHash() }; @@ -68,7 +69,7 @@ class YulStringRepository } std::string const& idToString(size_t _id) const { return *m_strings.at(_id); } - static std::uint64_t hash(std::string const& v) + static std::uint64_t hash(std::string_view const v) { // FNV hash - can be replaced by a better one, e.g. xxhash64 std::uint64_t hash = emptyHash(); @@ -126,7 +127,7 @@ class YulString { public: YulString() = default; - explicit YulString(std::string const& _s): m_handle(YulStringRepository::instance().stringToHandle(_s)) {} + explicit YulString(std::string_view const _s): m_handle(YulStringRepository::instance().stringToHandle(_s)) {} YulString(YulString const&) = default; YulString(YulString&&) = default; YulString& operator=(YulString const&) = default; diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index fe45008962c8..41f480f442a0 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -56,6 +56,8 @@ class AbstractAssembly public: using LabelID = size_t; using SubID = size_t; + using ContainerID = uint8_t; + using FunctionID = uint16_t; enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; virtual ~AbstractAssembly() = default; @@ -100,6 +102,27 @@ class AbstractAssembly virtual void appendAssemblySize() = 0; /// Creates a new sub-assembly, which can be referenced using dataSize and dataOffset. virtual std::pair, SubID> createSubAssembly(bool _creation, std::string _name = "") = 0; + + /// Registers a new function with given signature and returns its ID. + /// The function is initially empty and its body must be filled with instructions. + /// `_rets` even for non-returning function matters in case of stack height calculation. + virtual FunctionID registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) = 0; + /// Selects a function as a target for newly appended instructions. + /// May only be called after the main code section is already filled and + /// must not be called when another function is already selected. + /// Filling the same function more than once is not allowed. + /// @a endFunction() must be called at the end to finalize the function. + virtual void beginFunction(FunctionID _functionID) = 0; + /// Finalizes the process of filling a function body and switches back to the main code section. + /// Must not be called if no function is selected. + /// Must be called after filling the main yul section + virtual void endFunction() = 0; + /// Appends function call to a function under given ID + virtual void appendFunctionCall(FunctionID _functionID) = 0; + /// Appends an instruction that returns values from the current function. + /// Only allowed inside a function body. + virtual void appendFunctionReturn() = 0; + /// Appends the offset of the given sub-assembly or data. virtual void appendDataOffset(std::vector const& _subPath) = 0; /// Appends the size of the given sub-assembly or data. @@ -112,9 +135,27 @@ class AbstractAssembly /// Appends an assignment to an immutable variable. virtual void appendImmutableAssignment(std::string const& _identifier) = 0; + /// Appends an operation that loads 32 bytes of data from a known offset relative to the start of the static_aux_data area of the EOF data section. + /// Note that static_aux_data is only a part or the data section. + /// It is preceded by the pre_deploy_data, whose size is not determined before the bytecode is assembled, and which cannot be accessed using this function. + /// The function is meant to allow indexing into static_aux_data in a way that's independent of the size of pre_deploy_data. + virtual void appendAuxDataLoadN(uint16_t _offset) = 0; + + /// Appends EOF contract creation instruction which takes creation code from subcontainer with _containerID. + virtual void appendEOFCreate(ContainerID _containerID) = 0; + /// Appends EOF contract return instruction which returns a subcontainer ID (_containerID) with auxiliary data filled in. + virtual void appendReturnContract(ContainerID _containerID) = 0; /// Appends data to the very end of the bytecode. Repeated calls concatenate. + /// EOF auxiliary data in data section and the auxiliary data are different things. virtual void appendToAuxiliaryData(bytes const& _data) = 0; + /// Appends a SWAPN with 1-based indexing for @arg _depth. I.e. a depth of 1 would be equivalent to emitting SWAP1. + /// @arg _depth ranges from 1 to 256. + virtual void appendSwapN(size_t _depth) = 0; + /// Appends a DUPN with 1-based indexing for @arg _depth. I.e. a depth of 1 would be equivalent to emitting DUP1. + /// @arg _depth ranges from 1 to 256. + virtual void appendDupN(size_t _depth) = 0; + /// Mark this assembly as invalid. Any attempt to request bytecode from it should throw. virtual void markAsInvalid() = 0; diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index 1bb23cbc9282..aa744415bf9d 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -74,10 +74,10 @@ struct MiniEVMInterpreter u256 operator()(FunctionCall const& _funCall) { - BuiltinFunctionForEVM const* fun = m_dialect.builtin(_funCall.functionName.name); - yulAssert(fun, "Expected builtin function."); - yulAssert(fun->instruction, "Expected EVM instruction."); - return eval(*fun->instruction, _funCall.arguments); + BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_funCall.functionName, m_dialect); + yulAssert(builtin, "Expected builtin function."); + yulAssert(builtin->instruction, "Expected EVM instruction."); + return eval(*builtin->instruction, _funCall.arguments); } u256 operator()(Literal const& _literal) { @@ -125,11 +125,19 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu if (m_cache.count(_value)) return m_cache.at(_value); + yulAssert(m_dialect.auxiliaryBuiltinHandles().not_); + yulAssert(m_dialect.auxiliaryBuiltinHandles().exp); + yulAssert(m_dialect.auxiliaryBuiltinHandles().mul); + yulAssert(m_dialect.auxiliaryBuiltinHandles().add); + yulAssert(m_dialect.auxiliaryBuiltinHandles().sub); + + auto const& auxHandles = m_dialect.auxiliaryBuiltinHandles(); + Representation routine = represent(_value); if (numberEncodingSize(~_value) < numberEncodingSize(_value)) // Negated is shorter to represent - routine = min(std::move(routine), represent("not"_yulname, findRepresentation(~_value))); + routine = min(std::move(routine), represent(*auxHandles.not_, findRepresentation(~_value))); // Decompose value into a * 2**k + b where abs(b) << 2**k for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits) @@ -152,21 +160,21 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu continue; Representation newRoutine; if (m_dialect.evmVersion().hasBitwiseShifting()) - newRoutine = represent("shl"_yulname, represent(bits), findRepresentation(upperPart)); + newRoutine = represent(*auxHandles.shl, represent(bits), findRepresentation(upperPart)); else { - newRoutine = represent("exp"_yulname, represent(2), represent(bits)); + newRoutine = represent(*auxHandles.exp, represent(2), represent(bits)); if (upperPart != 1) - newRoutine = represent("mul"_yulname, findRepresentation(upperPart), newRoutine); + newRoutine = represent(*auxHandles.mul, findRepresentation(upperPart), newRoutine); } if (newRoutine.cost >= routine.cost) continue; if (lowerPart > 0) - newRoutine = represent("add"_yulname, newRoutine, findRepresentation(u256(abs(lowerPart)))); + newRoutine = represent(*auxHandles.add, newRoutine, findRepresentation(u256(abs(lowerPart)))); else if (lowerPart < 0) - newRoutine = represent("sub"_yulname, newRoutine, findRepresentation(u256(abs(lowerPart)))); + newRoutine = represent(*auxHandles.sub, newRoutine, findRepresentation(u256(abs(lowerPart)))); if (m_maxSteps > 0) m_maxSteps--; @@ -185,22 +193,22 @@ Representation RepresentationFinder::represent(u256 const& _value) const } Representation RepresentationFinder::represent( - YulName _instruction, + BuiltinHandle const& _instruction, Representation const& _argument ) const { Representation repr; repr.expression = std::make_unique(FunctionCall{ m_debugData, - Identifier{m_debugData, _instruction}, + BuiltinName{m_debugData, _instruction}, {ASTCopier{}.translate(*_argument.expression)} }); - repr.cost = _argument.cost + m_meter.instructionCosts(*m_dialect.builtin(_instruction)->instruction); + repr.cost = _argument.cost + m_meter.instructionCosts(*m_dialect.builtin(_instruction).instruction); return repr; } Representation RepresentationFinder::represent( - YulName _instruction, + BuiltinHandle const& _instruction, Representation const& _arg1, Representation const& _arg2 ) const @@ -208,10 +216,10 @@ Representation RepresentationFinder::represent( Representation repr; repr.expression = std::make_unique(FunctionCall{ m_debugData, - Identifier{m_debugData, _instruction}, + BuiltinName{m_debugData, _instruction}, {ASTCopier{}.translate(*_arg1.expression), ASTCopier{}.translate(*_arg2.expression)} }); - repr.cost = m_meter.instructionCosts(*m_dialect.builtin(_instruction)->instruction) + _arg1.cost + _arg2.cost; + repr.cost = m_meter.instructionCosts(*m_dialect.builtin(_instruction).instruction) + _arg1.cost + _arg2.cost; return repr; } diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index 35d7dfa43254..9c25450bf96f 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -37,7 +37,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; class GasMeter; /** @@ -93,8 +93,8 @@ class RepresentationFinder Representation const& findRepresentation(u256 const& _value); Representation represent(u256 const& _value) const; - Representation represent(YulName _instruction, Representation const& _arg) const; - Representation represent(YulName _instruction, Representation const& _arg1, Representation const& _arg2) const; + Representation represent(BuiltinHandle const& _instruction, Representation const& _arg) const; + Representation represent(BuiltinHandle const& _instruction, Representation const& _arg1, Representation const& _arg2) const; Representation min(Representation _a, Representation _b); diff --git a/libyul/backends/evm/ControlFlow.cpp b/libyul/backends/evm/ControlFlow.cpp new file mode 100644 index 000000000000..863fa30f6c7d --- /dev/null +++ b/libyul/backends/evm/ControlFlow.cpp @@ -0,0 +1,33 @@ +/* + 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 + +using namespace solidity::yul; + +ControlFlowLiveness::ControlFlowLiveness(ControlFlow const& _controlFlow): + controlFlow(_controlFlow), + mainLiveness(std::make_unique(*_controlFlow.mainGraph)), + functionLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique(*_cfg); }) | ranges::to) +{ } + +std::string ControlFlowLiveness::toDot() const +{ + return controlFlow.get().toDot(this); +} diff --git a/libyul/backends/evm/ControlFlow.h b/libyul/backends/evm/ControlFlow.h index 59bc1b677b57..394ce00c58c4 100644 --- a/libyul/backends/evm/ControlFlow.h +++ b/libyul/backends/evm/ControlFlow.h @@ -20,11 +20,24 @@ #include #include +#include #include namespace solidity::yul { +struct ControlFlow; + +struct ControlFlowLiveness{ + explicit ControlFlowLiveness(ControlFlow const& _controlFlow); + + std::reference_wrapper controlFlow; + std::unique_ptr mainLiveness; + std::vector> functionLiveness; + + std::string toDot() const; +}; + struct ControlFlow { std::unique_ptr mainGraph{std::make_unique()}; @@ -39,14 +52,21 @@ struct ControlFlow return nullptr; } - std::string toDot() const + std::string toDot(ControlFlowLiveness const* _liveness=nullptr) const { + if (_liveness) + yulAssert(&_liveness->controlFlow.get() == this); std::ostringstream output; output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; - output << mainGraph->toDot(false); - size_t index = 1; - for (auto const& [function, functionGraph]: functionGraphMapping) - output << functionGraph->toDot(false, index++); + output << mainGraph->toDot(false, std::nullopt, _liveness ? _liveness->mainLiveness.get() : nullptr); + + for (size_t index=0; index < functionGraphs.size(); ++index) + output << functionGraphs[index]->toDot( + false, + index+1, + _liveness ? _liveness->functionLiveness[index].get() : nullptr + ); + output << "}\n"; return output.str(); } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 46ef933ba28e..d9456e4c32d0 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -24,8 +24,8 @@ #include #include #include +#include -#include #include #include @@ -51,12 +51,23 @@ namespace /// Removes edges to blocks that are not reachable. void cleanUnreachable(CFG& _cfg) { + // If operation is a function call it adds the callee entry as child + auto const addFunctionsEntries = [&_cfg](CFG::BasicBlock* _node, auto&& _addChild) + { + for (auto const& operation: _node->operations) + { + if (auto const* functionCall = std::get_if(&operation.operation)) + { + auto const functionInfo = _cfg.functionInfo.at(&(functionCall->function.get())); + _addChild(functionInfo.entry); + } + } + }; + // Determine which blocks are reachable from the entry. util::BreadthFirstSearch reachabilityCheck{{_cfg.entry}}; - for (auto const& functionInfo: _cfg.functionInfo | ranges::views::values) - reachabilityCheck.verticesToTraverse.emplace_back(functionInfo.entry); - reachabilityCheck.run([&](CFG::BasicBlock* _node, auto&& _addChild) { + addFunctionsEntries(_node, _addChild); visit(util::GenericVisitor{ [&](CFG::BasicBlock::Jump const& _jump) { _addChild(_jump.target); @@ -73,9 +84,19 @@ void cleanUnreachable(CFG& _cfg) // Remove all entries from unreachable nodes from the graph. for (CFG::BasicBlock* node: reachabilityCheck.visited) - cxx20::erase_if(node->entries, [&](CFG::BasicBlock* entry) -> bool { + std::erase_if(node->entries, [&](CFG::BasicBlock* entry) -> bool { return !reachabilityCheck.visited.count(entry); }); + + // Remove functions which are never referenced. + _cfg.functions.erase(std::remove_if(_cfg.functions.begin(), _cfg.functions.end(), [&](auto const& item) { + return !reachabilityCheck.visited.count(_cfg.functionInfo.at(item).entry); + }), _cfg.functions.end()); + + // Remove functionInfos which are never referenced. + std::erase_if(_cfg.functionInfo, [&](auto const& entry) -> bool { + return !reachabilityCheck.visited.count(entry.second.entry); + }); } /// Sets the ``recursive`` member to ``true`` for all recursive function calls. @@ -211,6 +232,10 @@ std::unique_ptr ControlFlowGraphBuilder::build( Block const& _block ) { + std::optional eofVersion; + if (EVMDialect const* evmDialect = dynamic_cast(&_dialect)) + eofVersion = evmDialect->eofVersion(); + auto result = std::make_unique(); result->entry = &result->makeBlock(debugDataOf(_block)); @@ -241,6 +266,8 @@ ControlFlowGraphBuilder::ControlFlowGraphBuilder( m_functionSideEffects(_functionSideEffects), m_dialect(_dialect) { + if (EVMDialect const* evmDialect = dynamic_cast(&m_dialect)) + m_simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); } StackSlot ControlFlowGraphBuilder::operator()(Literal const& _literal) @@ -349,21 +376,22 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) CFG::Assignment{_switch.debugData, {ghostVarSlot}} }); - BuiltinFunction const* equalityBuiltin = m_dialect.equalityFunction(); - yulAssert(equalityBuiltin, ""); + std::optional const& equalityBuiltinHandle = m_dialect.equalityFunctionHandle(); + yulAssert(equalityBuiltinHandle); // Artificially generate: // eq(, ) auto makeValueCompare = [&](Case const& _case) { yul::FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(yul::FunctionCall{ debugDataOf(_case), - yul::Identifier{{}, "eq"_yulname}, + BuiltinName{{}, *equalityBuiltinHandle}, {*_case.value, Identifier{{}, ghostVariableName}} }); + BuiltinFunction const& equalityBuiltin = m_dialect.builtin(*equalityBuiltinHandle); CFG::Operation& operation = m_currentBlock->operations.emplace_back(CFG::Operation{ Stack{ghostVarSlot, LiteralSlot{_case.value->value.value(), debugDataOf(*_case.value)}}, Stack{TemporarySlot{ghostCall, 0}}, - CFG::BuiltinCall{debugDataOf(_case), *equalityBuiltin, ghostCall, 2}, + CFG::BuiltinCall{debugDataOf(_case), equalityBuiltin, ghostCall, 2}, }); return operation.output.front(); }; @@ -516,7 +544,7 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal Stack const* output = nullptr; bool canContinue = true; - if (BuiltinFunction const* builtin = m_dialect.builtin(_call.functionName.name)) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_call.functionName, m_dialect)) { Stack inputs; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) @@ -537,10 +565,12 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal } else { - Scope::Function const& function = lookupFunction(_call.functionName.name); + yulAssert(std::holds_alternative(_call.functionName)); + Scope::Function const& function = lookupFunction(std::get(_call.functionName).name); canContinue = m_graph.functionInfo.at(&function).canContinue; Stack inputs; - if (canContinue) + // For EOF (m_simulateFunctionsWithJumps == false) we do not have to put return label on stack. + if (m_simulateFunctionsWithJumps && canContinue) inputs.emplace_back(FunctionCallReturnLabelSlot{_call}); for (auto const& arg: _call.arguments | ranges::views::reverse) inputs.emplace_back(std::visit(*this, arg)); diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index 77feaea7b469..1d0227a56b71 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -90,6 +90,8 @@ class ControlFlowGraphBuilder }; std::optional m_forLoopInfo; std::optional m_currentFunction; + /// True if control flow graph simulates functions with jumps. False otherwise. True for legacy bytecode + bool m_simulateFunctionsWithJumps = true; }; } diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 694639565421..f77e4e047d7a 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -230,7 +230,7 @@ void CodeTransform::operator()(FunctionCall const& _call) yulAssert(m_scope, ""); m_assembly.setSourceLocation(originLocationOf(_call)); - if (BuiltinFunctionForEVM const* builtin = m_dialect.builtin(_call.functionName.name)) + if (BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_call.functionName, m_dialect)) { for (auto&& [i, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) if (!builtin->literalArgument(i)) @@ -240,11 +240,12 @@ void CodeTransform::operator()(FunctionCall const& _call) } else { + yulAssert(std::holds_alternative(_call.functionName)); AbstractAssembly::LabelID returnLabel = m_assembly.newLabelId(); m_assembly.appendLabelReference(returnLabel); Scope::Function* function = nullptr; - yulAssert(m_scope->lookup(_call.functionName.name, GenericVisitor{ + yulAssert(m_scope->lookup(std::get(_call.functionName).name, GenericVisitor{ [](Scope::Variable&) { yulAssert(false, "Expected function name."); }, [&](Scope::Function& _function) { function = &_function; } }), "Function name not found."); diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 6bfdc9cb9de3..d68ef16348b1 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -25,13 +25,17 @@ #include #include #include -#include #include #include #include #include +#include +#include + #include +#include +#include using namespace std::string_literals; using namespace solidity; @@ -41,32 +45,30 @@ using namespace solidity::util; namespace { -std::pair createEVMFunction( +size_t constexpr toContinuousVerbatimIndex(size_t _arguments, size_t _returnVariables) +{ + return _arguments + _returnVariables * EVMDialect::verbatimMaxInputSlots; +} + +std::tuple constexpr verbatimIndexToArgsAndRets(size_t _index) +{ + size_t const numRets = _index / EVMDialect::verbatimMaxInputSlots; + return std::make_tuple(_index - numRets * EVMDialect::verbatimMaxInputSlots, numRets); +} + +BuiltinFunctionForEVM createEVMFunction( langutil::EVMVersion _evmVersion, std::string const& _name, evmasm::Instruction _instruction ) { - evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); BuiltinFunctionForEVM f; - f.name = YulName{_name}; + evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); + f.name = _name; f.numParameters = static_cast(info.args); f.numReturns = static_cast(info.ret); f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); - if (evmasm::SemanticInformation::terminatesControlFlow(_instruction)) - { - f.controlFlowSideEffects.canContinue = false; - if (evmasm::SemanticInformation::reverts(_instruction)) - { - f.controlFlowSideEffects.canTerminate = false; - f.controlFlowSideEffects.canRevert = true; - } - else - { - f.controlFlowSideEffects.canTerminate = true; - f.controlFlowSideEffects.canRevert = false; - } - } + f.controlFlowSideEffects = ControlFlowSideEffects::fromInstruction(_instruction); f.isMSize = _instruction == evmasm::Instruction::MSIZE; f.literalArguments.clear(); f.instruction = _instruction; @@ -77,36 +79,35 @@ std::pair createEVMFunction( ) { _assembly.appendInstruction(_instruction); }; - - YulName name = f.name; - return {name, std::move(f)}; + return f; } -std::pair createFunction( - std::string _name, +BuiltinFunctionForEVM createFunction( + std::string const& _name, size_t _params, size_t _returns, SideEffects _sideEffects, + ControlFlowSideEffects _controlFlowSideEffects, std::vector> _literalArguments, std::function _generateCode ) { yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), ""); - YulName name{std::move(_name)}; BuiltinFunctionForEVM f; - f.name = name; + f.name = _name; f.numParameters = _params; f.numReturns = _returns; - f.sideEffects = std::move(_sideEffects); + f.sideEffects = _sideEffects; + f.controlFlowSideEffects = _controlFlowSideEffects; f.literalArguments = std::move(_literalArguments); f.isMSize = false; f.instruction = {}; f.generateCode = std::move(_generateCode); - return {name, f}; + return f; } -std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) +std::set> createReservedIdentifiers(langutil::EVMVersion _evmVersion, std::optional _eofVersion) { // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name // basefee for VMs before london. @@ -152,7 +153,17 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) (_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD); }; - std::set reserved; + auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool + { + solAssert(!_eofVersion.has_value() || (*_eofVersion == 1 && _evmVersion.supportsEOF())); + if (_eofVersion.has_value()) + // For EOF every instruction is reserved identifier. + return false; + return langutil::EVMVersion::firstWithEOF().hasOpcode(_instr, 1) && + !langutil::EVMVersion::firstWithEOF().hasOpcode(_instr, std::nullopt); + }; + + std::set> reserved; for (auto const& instr: evmasm::c_instructions) { std::string name = toLower(instr.first); @@ -162,22 +173,29 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) !blobHashException(instr.second) && !blobBaseFeeException(instr.second) && !mcopyException(instr.second) && - !transientStorageException(instr.second) + !transientStorageException(instr.second) && + !eofIdentifiersException(instr.second) ) reserved.emplace(name); } - reserved += std::vector{ - "linkersymbol"_yulname, - "datasize"_yulname, - "dataoffset"_yulname, - "datacopy"_yulname, - "setimmutable"_yulname, - "loadimmutable"_yulname, + reserved += std::vector{ + "linkersymbol", + "datasize", + "dataoffset", + "datacopy", + "setimmutable", + "loadimmutable", }; + + if (_eofVersion.has_value()) + reserved += std::vector{ + "auxdataloadn", + }; + return reserved; } -std::map createBuiltins(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess) +std::vector> createBuiltins(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess) { // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. @@ -186,172 +204,266 @@ std::map createBuiltins(langutil::EVMVersion _ev return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris()); }; - std::map builtins; + std::vector> builtins; for (auto const& instr: evmasm::c_instructions) { std::string name = toLower(instr.first); auto const opcode = instr.second; if ( - !evmasm::isDupInstruction(opcode) && - !evmasm::isSwapInstruction(opcode) && + !(opcode >= evmasm::Instruction::DUP1 && opcode <= evmasm::Instruction::DUP16) && + !(opcode >= evmasm::Instruction::SWAP1 && opcode <= evmasm::Instruction::SWAP16) && !evmasm::isPushInstruction(opcode) && opcode != evmasm::Instruction::JUMP && opcode != evmasm::Instruction::JUMPI && opcode != evmasm::Instruction::JUMPDEST && + opcode != evmasm::Instruction::DATALOADN && + opcode != evmasm::Instruction::EOFCREATE && + opcode != evmasm::Instruction::RETURNCONTRACT && + opcode != evmasm::Instruction::RJUMP && + opcode != evmasm::Instruction::RJUMPI && + opcode != evmasm::Instruction::CALLF && + opcode != evmasm::Instruction::JUMPF && + opcode != evmasm::Instruction::DUPN && + opcode != evmasm::Instruction::SWAPN && + opcode != evmasm::Instruction::RETF && _evmVersion.hasOpcode(opcode, _eofVersion) && !prevRandaoException(name) ) - builtins.emplace(createEVMFunction(_evmVersion, name, opcode)); + builtins.emplace_back(createEVMFunction(_evmVersion, name, opcode)); + else + builtins.emplace_back(std::nullopt); } - if (_objectAccess) + auto const createIfObjectAccess = [_objectAccess]( + std::string const& _name, + size_t _params, + size_t _returns, + SideEffects _sideEffects, + ControlFlowSideEffects _controlFlowSideEffects, + std::vector> _literalArguments, + std::function _generateCode + ) -> std::optional { - builtins.emplace(createFunction("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, []( + if (!_objectAccess) + return std::nullopt; + return createFunction(_name, _params, _returns, _sideEffects, _controlFlowSideEffects, std::move(_literalArguments), std::move(_generateCode)); + }; + + builtins.emplace_back(createIfObjectAccess("linkersymbol", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); + })); + builtins.emplace_back(createIfObjectAccess( + "memoryguard", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::Number}, + []( FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& ) { + yulAssert(_call.arguments.size() == 1, ""); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + _assembly.appendConstant(literal->value.value()); + }) + ); + if (!_eofVersion.has_value()) + { + builtins.emplace_back(createIfObjectAccess("datasize", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& _context + ) { + yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendAssemblySize(); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataSize(subIdPath); + } })); - - builtins.emplace(createFunction( - "memoryguard", - 1, - 1, - SideEffects{}, - {LiteralKind::Number}, + builtins.emplace_back(createIfObjectAccess("dataoffset", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& _context + ) { + yulAssert(_context.currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendConstant(0); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataOffset(subIdPath); + } + })); + builtins.emplace_back(createIfObjectAccess( + "datacopy", + 3, + 0, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::CODECOPY), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::CODECOPY), + {}, []( - FunctionCall const& _call, + FunctionCall const&, AbstractAssembly& _assembly, BuiltinContext& ) { - yulAssert(_call.arguments.size() == 1, ""); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - _assembly.appendConstant(literal->value.value()); - }) - ); - - if (!_eofVersion.has_value()) - { - builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, []( + _assembly.appendInstruction(evmasm::Instruction::CODECOPY); + } + )); + builtins.emplace_back(createIfObjectAccess( + "setimmutable", + 3, + 0, + SideEffects{ + false, // movable + false, // movableApartFromEffects + false, // canBeRemoved + false, // canBeRemovedIfNotMSize + true, // cannotLoop + SideEffects::None, // otherState + SideEffects::None, // storage + SideEffects::Write, // memory + SideEffects::None // transientStorage + }, + ControlFlowSideEffects{}, + {std::nullopt, LiteralKind::String, std::nullopt}, + []( FunctionCall const& _call, AbstractAssembly& _assembly, - BuiltinContext& _context + BuiltinContext& ) { - yulAssert(_context.currentObject, "No object available."); - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendAssemblySize(); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataSize(subIdPath); - } - })); - builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, []( + yulAssert(_call.arguments.size() == 3, ""); + auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); + _assembly.appendImmutableAssignment(identifier); + } + )); + builtins.emplace_back(createIfObjectAccess( + "loadimmutable", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::String}, + []( FunctionCall const& _call, AbstractAssembly& _assembly, - BuiltinContext& _context + BuiltinContext& ) { - yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendConstant(0); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataOffset(subIdPath); - } - })); - builtins.emplace(createFunction( - "datacopy", - 3, - 0, - SideEffects{ - false, // movable - true, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage - }, - {}, + _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); + } + )); + } + else // EOF context + { + if (_objectAccess) + { + builtins.emplace_back(createFunction( + "auxdataloadn", + 1, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), + {LiteralKind::Number}, []( - FunctionCall const&, + FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& ) { - _assembly.appendInstruction(evmasm::Instruction::CODECOPY); + yulAssert(_call.arguments.size() == 1); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + yulAssert(literal->value.value() <= std::numeric_limits::max()); + _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); } )); - builtins.emplace(createFunction( - "setimmutable", - 3, - 0, - SideEffects{ - false, // movable - false, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage - }, - {std::nullopt, LiteralKind::String, std::nullopt}, + + builtins.emplace_back(createFunction( + "eofcreate", + 5, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), + {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, []( FunctionCall const& _call, AbstractAssembly& _assembly, - BuiltinContext& + BuiltinContext& context ) { - yulAssert(_call.arguments.size() == 3, ""); - auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); - _assembly.appendImmutableAssignment(identifier); + yulAssert(_call.arguments.size() == 5); + Literal const* literal = std::get_if(&_call.arguments.front()); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendEOFCreate(static_cast(*containerID)); } - )); - builtins.emplace(createFunction( - "loadimmutable", - 1, - 1, - SideEffects{}, - {LiteralKind::String}, + )); + + builtins.emplace_back(createFunction( + "returncontract", + 3, + 0, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::RETURNCONTRACT), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::RETURNCONTRACT), + {LiteralKind::String, std::nullopt, std::nullopt}, []( FunctionCall const& _call, AbstractAssembly& _assembly, - BuiltinContext& + BuiltinContext& context ) { - yulAssert(_call.arguments.size() == 1, ""); - _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); + yulAssert(_call.arguments.size() == 3); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendReturnContract(static_cast(*containerID)); } )); } } + yulAssert( + ranges::all_of(builtins, [](std::optional const& _builtinFunction){ + return !_builtinFunction || _builtinFunction->name.substr(0, "verbatim_"s.size()) != "verbatim_"; + }), + "Builtin functions besides verbatim should not start with the verbatim_ prefix." + ); return builtins; } std::regex const& verbatimPattern() { - std::regex static const pattern{"verbatim_([1-9]?[0-9])i_([1-9]?[0-9])o"}; + std::regex static const pattern{"([1-9]?[0-9])i_([1-9]?[0-9])o"}; return pattern; } @@ -363,29 +475,70 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional m_evmVersion(_evmVersion), m_eofVersion(_eofVersion), m_functions(createBuiltins(_evmVersion, _eofVersion, _objectAccess)), - m_reserved(createReservedIdentifiers(_evmVersion)) + m_reserved(createReservedIdentifiers(_evmVersion, _eofVersion)) { + for (auto const& [index, maybeBuiltin]: m_functions | ranges::views::enumerate) + if (maybeBuiltin) + // ids are offset by the maximum number of verbatim functions + m_builtinFunctionsByName[maybeBuiltin->name] = BuiltinHandle{index + verbatimIDOffset}; + + m_discardFunction = findBuiltin("pop"); + m_equalityFunction = findBuiltin("eq"); + m_booleanNegationFunction = findBuiltin("iszero"); + m_memoryStoreFunction = findBuiltin("mstore"); + m_memoryLoadFunction = findBuiltin("mload"); + m_storageStoreFunction = findBuiltin("sstore"); + m_storageLoadFunction = findBuiltin("sload"); + m_hashFunction = findBuiltin("keccak256"); + + m_auxiliaryBuiltinHandles.add = EVMDialect::findBuiltin("add"); + m_auxiliaryBuiltinHandles.exp = EVMDialect::findBuiltin("exp"); + m_auxiliaryBuiltinHandles.mul = EVMDialect::findBuiltin("mul"); + m_auxiliaryBuiltinHandles.not_ = EVMDialect::findBuiltin("not"); + m_auxiliaryBuiltinHandles.shl = EVMDialect::findBuiltin("shl"); + m_auxiliaryBuiltinHandles.sub = EVMDialect::findBuiltin("sub"); } -BuiltinFunctionForEVM const* EVMDialect::builtin(YulName _name) const +std::optional EVMDialect::findBuiltin(std::string_view _name) const { - if (m_objectAccess) + if (m_objectAccess && _name.substr(0, "verbatim_"s.size()) == "verbatim_") { std::smatch match; - if (regex_match(_name.str(), match, verbatimPattern())) + std::string name(_name.substr("verbatim_"s.size())); + if (regex_match(name, match, verbatimPattern())) return verbatimFunction(stoul(match[1]), stoul(match[2])); } - auto it = m_functions.find(_name); - if (it != m_functions.end()) - return &it->second; - else - return nullptr; + + if ( + auto it = m_builtinFunctionsByName.find(_name); + it != m_builtinFunctionsByName.end() + ) + return it->second; + + return std::nullopt; } -bool EVMDialect::reservedIdentifier(YulName _name) const +BuiltinFunctionForEVM const& EVMDialect::builtin(BuiltinHandle const& _handle) const +{ + if (isVerbatimHandle(_handle)) + { + yulAssert(_handle.id < verbatimIDOffset); + auto const& verbatimFunctionPtr = m_verbatimFunctions[_handle.id]; + yulAssert(verbatimFunctionPtr); + return *verbatimFunctionPtr; + } + + yulAssert(_handle.id - verbatimIDOffset < m_functions.size()); + auto const& maybeBuiltin = m_functions[_handle.id - verbatimIDOffset]; + yulAssert(maybeBuiltin.has_value()); + return *maybeBuiltin; +} + + +bool EVMDialect::reservedIdentifier(std::string_view _name) const { if (m_objectAccess) - if (_name.str().substr(0, "verbatim"s.size()) == "verbatim") + if (_name.substr(0, "verbatim"s.size()) == "verbatim") return true; return m_reserved.count(_name) != 0; } @@ -428,35 +581,52 @@ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instructio }; } -BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const +BuiltinFunctionForEVM EVMDialect::createVerbatimFunctionFromHandle(BuiltinHandle const& _handle) { - std::pair key{_arguments, _returnVariables}; - std::shared_ptr& function = m_verbatimFunctions[key]; - if (!function) - { - BuiltinFunctionForEVM builtinFunction = createFunction( - "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o", - 1 + _arguments, - _returnVariables, - SideEffects::worst(), - std::vector>{LiteralKind::String} + std::vector>(_arguments), - [=]( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == (1 + _arguments), ""); - Expression const& bytecode = _call.arguments.front(); - - _assembly.appendVerbatim( - asBytes(formatLiteral(std::get(bytecode))), - _arguments, - _returnVariables - ); - } - ).second; - builtinFunction.isMSize = true; - function = std::make_shared(std::move(builtinFunction)); - } - return function.get(); + return std::apply(createVerbatimFunction, verbatimIndexToArgsAndRets(_handle.id)); +} + +BuiltinFunctionForEVM EVMDialect::createVerbatimFunction(size_t _arguments, size_t _returnVariables) +{ + BuiltinFunctionForEVM builtinFunction = createFunction( + "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o", + 1 + _arguments, + _returnVariables, + SideEffects::worst(), + ControlFlowSideEffects::worst(), // Worst control flow side effects because verbatim can do anything. + std::vector>{LiteralKind::String} + std::vector>(_arguments), + [=]( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == (1 + _arguments), ""); + Expression const& bytecode = _call.arguments.front(); + + _assembly.appendVerbatim( + asBytes(formatLiteral(std::get(bytecode))), + _arguments, + _returnVariables + ); + } + ); + builtinFunction.isMSize = true; + return builtinFunction; +} + +BuiltinHandle EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const +{ + yulAssert(_arguments <= verbatimMaxInputSlots); + yulAssert(_returnVariables <= verbatimMaxOutputSlots); + + auto const verbatimIndex = toContinuousVerbatimIndex(_arguments, _returnVariables); + yulAssert(verbatimIndex < verbatimIDOffset); + + if ( + auto& verbatimFunctionPtr = m_verbatimFunctions[verbatimIndex]; + !verbatimFunctionPtr + ) + verbatimFunctionPtr = std::make_unique(createVerbatimFunction(_arguments, _returnVariables)); + + return {verbatimIndex}; } diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index cc064c3a0f1e..0440daade1ce 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include @@ -34,7 +35,7 @@ namespace solidity::yul { struct FunctionCall; -struct Object; +class Object; /** * Context used during code generation. @@ -44,6 +45,8 @@ struct BuiltinContext Object const* currentObject = nullptr; /// Mapping from named objects to abstract assembly sub IDs. std::map subIDs; + + std::map functionIDs; }; struct BuiltinFunctionForEVM: public BuiltinFunction @@ -62,45 +65,79 @@ struct BuiltinFunctionForEVM: public BuiltinFunction * The main difference is that the builtin functions take an AbstractAssembly for the * code generation. */ -struct EVMDialect: public Dialect +class EVMDialect: public Dialect { +public: + /// Handles to (depending on dialect, potentially existing) builtins, which are not accessible via the + /// `...FunctionHandle` functions of `Dialect` and of which it is statically known, that they are needed in, + /// e.g., certain optimization steps. + struct AuxiliaryBuiltinHandles + { + std::optional add; + std::optional exp; + std::optional mul; + std::optional not_; + std::optional shl; + std::optional sub; + }; /// Constructor, should only be used internally. Use the factory functions below. EVMDialect(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess); - /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. - BuiltinFunctionForEVM const* builtin(YulName _name) const override; + std::optional findBuiltin(std::string_view _name) const override; + + BuiltinFunctionForEVM const& builtin(BuiltinHandle const& _handle) const override; - /// @returns true if the identifier is reserved. This includes the builtins too. - bool reservedIdentifier(YulName _name) const override; + bool reservedIdentifier(std::string_view _name) const override; - BuiltinFunctionForEVM const* discardFunction() const override { return builtin("pop"_yulname); } - BuiltinFunctionForEVM const* equalityFunction() const override { return builtin("eq"_yulname); } - BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulname); } - BuiltinFunctionForEVM const* memoryStoreFunction() const override { return builtin("mstore"_yulname); } - BuiltinFunctionForEVM const* memoryLoadFunction() const override { return builtin("mload"_yulname); } - BuiltinFunctionForEVM const* storageStoreFunction() const override { return builtin("sstore"_yulname); } - BuiltinFunctionForEVM const* storageLoadFunction() const override { return builtin("sload"_yulname); } - YulName hashFunction() const override { return "keccak256"_yulname; } + std::optional discardFunctionHandle() const override { return m_discardFunction; } + std::optional equalityFunctionHandle() const override { return m_equalityFunction; } + std::optional booleanNegationFunctionHandle() const override { return m_booleanNegationFunction; } + std::optional memoryStoreFunctionHandle() const override { return m_memoryStoreFunction; } + std::optional memoryLoadFunctionHandle() const override { return m_memoryLoadFunction; } + std::optional storageStoreFunctionHandle() const override { return m_storageStoreFunction; } + std::optional storageLoadFunctionHandle() const override { return m_storageLoadFunction; } + std::optional hashFunctionHandle() const override { return m_hashFunction; } + AuxiliaryBuiltinHandles const& auxiliaryBuiltinHandles() const { return m_auxiliaryBuiltinHandles; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _evmVersion, std::optional _eofVersion); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _evmVersion, std::optional _eofVersion); langutil::EVMVersion evmVersion() const { return m_evmVersion; } std::optional eofVersion() const { return m_eofVersion; } + size_t reachableStackDepth() const { return m_eofVersion.has_value() ? 256 : 16; } bool providesObjectAccess() const { return m_objectAccess; } static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction); + static size_t constexpr verbatimMaxInputSlots = 100; + static size_t constexpr verbatimMaxOutputSlots = 100; + protected: - BuiltinFunctionForEVM const* verbatimFunction(size_t _arguments, size_t _returnVariables) const; + static bool constexpr isVerbatimHandle(BuiltinHandle const& _handle) { return _handle.id < verbatimIDOffset; } + static BuiltinFunctionForEVM createVerbatimFunctionFromHandle(BuiltinHandle const& _handle); + static BuiltinFunctionForEVM createVerbatimFunction(size_t _arguments, size_t _returnVariables); + BuiltinHandle verbatimFunction(size_t _arguments, size_t _returnVariables) const; + + static size_t constexpr verbatimIDOffset = verbatimMaxInputSlots * verbatimMaxOutputSlots; bool const m_objectAccess; langutil::EVMVersion const m_evmVersion; std::optional m_eofVersion; - std::map m_functions; - std::map, std::shared_ptr> mutable m_verbatimFunctions; - std::set m_reserved; + std::unordered_map m_builtinFunctionsByName; + std::vector> m_functions; + std::array, verbatimIDOffset> mutable m_verbatimFunctions{}; + std::set> m_reserved; + + std::optional m_discardFunction; + std::optional m_equalityFunction; + std::optional m_booleanNegationFunction; + std::optional m_memoryStoreFunction; + std::optional m_memoryLoadFunction; + std::optional m_storageStoreFunction; + std::optional m_storageLoadFunction; + std::optional m_hashFunction; + AuxiliaryBuiltinHandles m_auxiliaryBuiltinHandles; }; } diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index 539279bf20d9..57593fdc26da 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -76,10 +76,10 @@ std::pair GasMeterVisitor::instructionCosts( void GasMeterVisitor::operator()(FunctionCall const& _funCall) { ASTWalker::operator()(_funCall); - if (BuiltinFunctionForEVM const* f = m_dialect.builtin(_funCall.functionName.name)) - if (f->instruction) + if (BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_funCall.functionName, m_dialect)) + if (builtin->instruction) { - instructionCostsInternal(*f->instruction); + instructionCostsInternal(*builtin->instruction); return; } yulAssert(false, "Functions not implemented."); diff --git a/libyul/backends/evm/EVMMetrics.h b/libyul/backends/evm/EVMMetrics.h index b67cb77cdd50..1475246f1686 100644 --- a/libyul/backends/evm/EVMMetrics.h +++ b/libyul/backends/evm/EVMMetrics.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct EVMDialect; +class EVMDialect; /** * Gas meter for expressions only involving literals, identifiers and diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index a7ac67c3a6c3..830c32752dba 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -37,17 +37,19 @@ using namespace solidity::yul; void EVMObjectCompiler::compile( Object const& _object, AbstractAssembly& _assembly, - EVMDialect const& _dialect, - bool _optimize, - std::optional _eofVersion + bool _optimize ) { - EVMObjectCompiler compiler(_assembly, _dialect, _eofVersion); + EVMObjectCompiler compiler(_assembly); compiler.run(_object, _optimize); } void EVMObjectCompiler::run(Object const& _object, bool _optimize) { + yulAssert(_object.dialect()); + auto const* evmDialect = dynamic_cast(_object.dialect()); + yulAssert(evmDialect); + BuiltinContext context; context.currentObject = &_object; @@ -59,7 +61,7 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name); context.subIDs[subObject->name] = subAssemblyAndID.second; subObject->subId = subAssemblyAndID.second; - compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize, m_eofVersion); + compile(*subObject, *subAssemblyAndID.first, _optimize); } else { @@ -73,26 +75,29 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) yulAssert(_object.analysisInfo, "No analysis info."); yulAssert(_object.hasCode(), "No code."); - if (m_eofVersion.has_value()) - yulAssert( - _optimize && (m_dialect.evmVersion() >= langutil::EVMVersion::prague()), - "Experimental EOF support is only available for optimized via-IR compilation and the most recent EVM version." - ); - if (_optimize && m_dialect.evmVersion().canOverchargeGasForCall()) + if (evmDialect->eofVersion().has_value()) + { + solUnimplementedAssert(_optimize, "EOF supported only for optimized compilation via IR."); + yulAssert(evmDialect->evmVersion().supportsEOF()); + } + if (_optimize && evmDialect->evmVersion().canOverchargeGasForCall()) { auto stackErrors = OptimizedEVMCodeTransform::run( m_assembly, *_object.analysisInfo, _object.code()->root(), - m_dialect, + *evmDialect, context, OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName ); if (!stackErrors.empty()) { + yulAssert(evmDialect->providesObjectAccess()); + auto const memoryGuardHandle = evmDialect->findBuiltin("memoryguard"); + yulAssert(memoryGuardHandle, "Compiling with object access, memoryguard should be available as builtin."); std::vector memoryGuardCalls = findFunctionCalls( _object.code()->root(), - "memoryguard"_yulname + *memoryGuardHandle ); auto stackError = stackErrors.front(); std::string msg = stackError.comment() ? *stackError.comment() : ""; @@ -114,7 +119,7 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) m_assembly, *_object.analysisInfo, _object.code()->root(), - m_dialect, + *evmDialect, context, _optimize, {}, diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index d37ade2cd211..cca346ae7845 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -26,9 +26,9 @@ namespace solidity::yul { -struct Object; +class Object; class AbstractAssembly; -struct EVMDialect; +class EVMDialect; class EVMObjectCompiler { @@ -36,20 +36,14 @@ class EVMObjectCompiler static void compile( Object const& _object, AbstractAssembly& _assembly, - EVMDialect const& _dialect, - bool _optimize, - std::optional _eofVersion + bool _optimize ); private: - EVMObjectCompiler(AbstractAssembly& _assembly, EVMDialect const& _dialect, std::optional _eofVersion): - m_assembly(_assembly), m_dialect(_dialect), m_eofVersion(_eofVersion) - {} + EVMObjectCompiler(AbstractAssembly& _assembly): m_assembly(_assembly) {} void run(Object const& _object, bool _optimize); AbstractAssembly& m_assembly; - EVMDialect const& m_dialect; - std::optional m_eofVersion; }; } diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index e3a2e01e1b1f..960e663dfa7a 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -106,14 +106,31 @@ void EthAssemblyAdapter::appendJump(int _stackDiffAfter, JumpType _jumpType) void EthAssemblyAdapter::appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) { - appendLabelReference(_labelId); - appendJump(_stackDiffAfter, _jumpType); + if (m_assembly.supportsRelativeJumps()) + { + m_assembly.append(evmasm::AssemblyItem::relativeJumpTo(evmasm::AssemblyItem(evmasm::Tag, _labelId))); + yulAssert(_jumpType == JumpType::Ordinary); + m_assembly.adjustDeposit(_stackDiffAfter); + } + else + { + appendLabelReference(_labelId); + appendJump(_stackDiffAfter, _jumpType); + } } void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId, JumpType _jumpType) { - appendLabelReference(_labelId); - appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType); + if (m_assembly.supportsRelativeJumps()) + { + m_assembly.append(evmasm::AssemblyItem::conditionalRelativeJumpTo(evmasm::AssemblyItem(evmasm::Tag, _labelId))); + yulAssert(_jumpType == JumpType::Ordinary); + } + else + { + appendLabelReference(_labelId); + appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType); + } } void EthAssemblyAdapter::appendAssemblySize() @@ -128,6 +145,41 @@ std::pair, AbstractAssembly::SubID> EthAssembl return {std::make_shared(*assembly), static_cast(sub.data())}; } +AbstractAssembly::FunctionID EthAssemblyAdapter::registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) +{ + return m_assembly.createFunction(_args, _rets, _nonReturning); +} + +void EthAssemblyAdapter::beginFunction(AbstractAssembly::FunctionID _functionID) +{ + m_assembly.beginFunction(_functionID); +} + +void EthAssemblyAdapter::endFunction() +{ + m_assembly.endFunction(); +} + +void EthAssemblyAdapter::appendFunctionReturn() +{ + m_assembly.appendFunctionReturn(); +} + +void EthAssemblyAdapter::appendFunctionCall(FunctionID _functionID) +{ + m_assembly.appendFunctionCall(_functionID); +} + +void EthAssemblyAdapter::appendEOFCreate(ContainerID _containerID) +{ + m_assembly.appendEOFCreate(_containerID); +} + +void EthAssemblyAdapter::appendReturnContract(ContainerID _containerID) +{ + m_assembly.appendReturnContract(_containerID); +} + void EthAssemblyAdapter::appendDataOffset(std::vector const& _subPath) { if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end()) @@ -175,6 +227,22 @@ void EthAssemblyAdapter::appendImmutableAssignment(std::string const& _identifie m_assembly.appendImmutableAssignment(_identifier); } +void EthAssemblyAdapter::appendAuxDataLoadN(uint16_t _offset) +{ + m_assembly.appendAuxDataLoadN(_offset); +} + +void EthAssemblyAdapter::appendSwapN(size_t _depth) +{ + m_assembly.appendSwapN(_depth); +} + +void EthAssemblyAdapter::appendDupN(size_t _depth) +{ + m_assembly.appendDupN(_depth); +} + + void EthAssemblyAdapter::markAsInvalid() { m_assembly.markAsInvalid(); diff --git a/libyul/backends/evm/EthAssemblyAdapter.h b/libyul/backends/evm/EthAssemblyAdapter.h index 011081dedaac..dd708b8b33de 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.h +++ b/libyul/backends/evm/EthAssemblyAdapter.h @@ -56,6 +56,13 @@ class EthAssemblyAdapter: public AbstractAssembly void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override; void appendAssemblySize() override; std::pair, SubID> createSubAssembly(bool _creation, std::string _name = {}) override; + AbstractAssembly::FunctionID registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) override; + void beginFunction(AbstractAssembly::FunctionID _functionID) override; + void endFunction() override; + void appendFunctionCall(FunctionID _functionID) override; + void appendFunctionReturn() override; + void appendEOFCreate(ContainerID _containerID) override; + void appendReturnContract(ContainerID _containerID) override; void appendDataOffset(std::vector const& _subPath) override; void appendDataSize(std::vector const& _subPath) override; SubID appendData(bytes const& _data) override; @@ -65,6 +72,11 @@ class EthAssemblyAdapter: public AbstractAssembly void appendImmutable(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override; + void appendAuxDataLoadN(uint16_t _offset) override; + + void appendSwapN(size_t _depth) override; + void appendDupN(size_t _depth) override; + void markAsInvalid() override; langutil::EVMVersion evmVersion() const override; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index c444a71435c0..78025265f342 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -33,6 +33,23 @@ using namespace solidity::yul; using namespace solidity::util; using namespace solidity::langutil; +namespace +{ + +void modifyBuiltinToNoOutput(BuiltinFunctionForEVM& _builtin) +{ + _builtin.generateCode = [_builtin](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) + { + for (size_t i: ranges::views::iota(0u, _call.arguments.size())) + if (!_builtin.literalArgument(i)) + _assembly.appendInstruction(evmasm::Instruction::POP); + + for (size_t i = 0; i < _builtin.numReturns; i++) + _assembly.appendConstant(u256(0)); + }; +} + +} void NoOutputAssembly::appendInstruction(evmasm::Instruction _instr) { @@ -97,12 +114,55 @@ void NoOutputAssembly::appendAssemblySize() appendInstruction(evmasm::Instruction::PUSH1); } +void NoOutputAssembly::appendDupN(size_t) +{ + m_stackHeight++; +} + std::pair, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(bool, std::string) { yulAssert(false, "Sub assemblies not implemented."); return {}; } +AbstractAssembly::FunctionID NoOutputAssembly::registerFunction(uint8_t _args, uint8_t _rets, bool) +{ + yulAssert(m_context.numFunctions <= std::numeric_limits::max()); + AbstractAssembly::FunctionID id = static_cast(m_context.numFunctions++); + m_context.functionSignatures[id] = {_args, _rets}; + return id; +} + +void NoOutputAssembly::beginFunction(FunctionID _functionID) +{ + yulAssert(m_currentFunctionID == 0, "Attempted to begin a function before ending the last one."); + yulAssert(m_context.functionSignatures.count(_functionID) == 1, "Filling unregistered function."); + yulAssert(m_stackHeight == 0, "Non-empty stack on beginFunction call."); + m_currentFunctionID = _functionID; +} + +void NoOutputAssembly::endFunction() +{ + yulAssert(m_currentFunctionID != 0, "End function without begin function."); + auto const [_, rets] = m_context.functionSignatures.at(m_currentFunctionID); + yulAssert(m_stackHeight == rets, "Stack height mismatch at function end."); + m_currentFunctionID = 0; +} + +void NoOutputAssembly::appendFunctionCall(FunctionID _functionID) +{ + auto [args, rets] = m_context.functionSignatures.at(_functionID); + m_stackHeight += static_cast(rets) - static_cast(args); + solAssert(m_stackHeight >= 0); +} + +void NoOutputAssembly::appendFunctionReturn() +{ + yulAssert(m_currentFunctionID != 0, "End function without begin function."); + auto const [_, rets] = m_context.functionSignatures.at(m_currentFunctionID); + yulAssert(m_stackHeight == rets, "Stack height mismatch at function end."); +} + void NoOutputAssembly::appendDataOffset(std::vector const&) { appendInstruction(evmasm::Instruction::PUSH1); @@ -129,20 +189,40 @@ void NoOutputAssembly::appendImmutableAssignment(std::string const&) yulAssert(false, "setimmutable not implemented."); } +void NoOutputAssembly::appendAuxDataLoadN(uint16_t) +{ + yulAssert(false, "auxdataloadn not implemented."); +} + +void NoOutputAssembly::appendEOFCreate(ContainerID) +{ + yulAssert(false, "eofcreate not implemented."); + +} +void NoOutputAssembly::appendReturnContract(ContainerID) +{ + yulAssert(false, "returncontract not implemented."); +} + NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): EVMDialect(_copyFrom.evmVersion(), _copyFrom.eofVersion(), _copyFrom.providesObjectAccess()) { for (auto& fun: m_functions) - { - size_t returns = fun.second.numReturns; - fun.second.generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) + if (fun) + modifyBuiltinToNoOutput(*fun); +} + +BuiltinFunctionForEVM const& NoOutputEVMDialect::builtin(BuiltinHandle const& _handle) const +{ + if (isVerbatimHandle(_handle)) + // for verbatims the modification is performed lazily as they are stored in a lookup table fashion + if ( + auto& builtin = m_verbatimFunctions[_handle.id]; + !builtin + ) { - for (size_t i: ranges::views::iota(0u, _call.arguments.size())) - if (!fun.second.literalArgument(i)) - _assembly.appendInstruction(evmasm::Instruction::POP); - - for (size_t i = 0; i < returns; i++) - _assembly.appendConstant(u256(0)); - }; - } + builtin = std::make_unique(createVerbatimFunctionFromHandle(_handle)); + modifyBuiltinToNoOutput(*builtin); + } + return EVMDialect::builtin(_handle); } diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index 8d7dda0bb50c..502f90d854f5 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -37,6 +37,13 @@ struct SourceLocation; namespace solidity::yul { +class NoOutputAssembly; + +struct NoOutputAssemblyContext +{ + size_t numFunctions = 0; + std::map> functionSignatures; +}; /** * Assembly class that just ignores everything and only performs stack counting. @@ -66,6 +73,11 @@ class NoOutputAssembly: public AbstractAssembly void appendAssemblySize() override; std::pair, SubID> createSubAssembly(bool _creation, std::string _name = "") override; + FunctionID registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) override; + void beginFunction(FunctionID) override; + void endFunction() override; + void appendFunctionCall(FunctionID _functionID) override; + void appendFunctionReturn() override; void appendDataOffset(std::vector const& _subPath) override; void appendDataSize(std::vector const& _subPath) override; SubID appendData(bytes const& _data) override; @@ -75,12 +87,20 @@ class NoOutputAssembly: public AbstractAssembly void appendImmutable(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override; + void appendAuxDataLoadN(uint16_t) override; + void appendEOFCreate(ContainerID) override; + void appendReturnContract(ContainerID) override; + void appendSwapN(size_t) override {} + void appendDupN(size_t) override; + void markAsInvalid() override {} langutil::EVMVersion evmVersion() const override { return m_evmVersion; } private: + NoOutputAssemblyContext m_context = {}; int m_stackHeight = 0; + FunctionID m_currentFunctionID = 0; langutil::EVMVersion m_evmVersion; }; @@ -88,9 +108,12 @@ class NoOutputAssembly: public AbstractAssembly /** * EVM dialect that does not generate any code. */ -struct NoOutputEVMDialect: public EVMDialect +class NoOutputEVMDialect: public EVMDialect { +public: explicit NoOutputEVMDialect(EVMDialect const& _copyFrom); + + BuiltinFunctionForEVM const& builtin(BuiltinHandle const& _handle) const override; }; diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 8ef01f0b6a86..69cd046debd0 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -23,10 +23,10 @@ #include +#include #include #include -#include #include #include @@ -49,13 +49,32 @@ std::vector OptimizedEVMCodeTransform::run( ) { std::unique_ptr dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _block); - StackLayout stackLayout = StackLayoutGenerator::run(*dfg); + StackLayout stackLayout = StackLayoutGenerator::run(*dfg, _dialect); + + if (_dialect.eofVersion().has_value()) + { + for (Scope::Function const* function: dfg->functions) + { + auto const& info = dfg->functionInfo.at(function); + yulAssert(info.parameters.size() <= std::numeric_limits::max()); + yulAssert(info.returnVariables.size() <= std::numeric_limits::max()); + auto functionID = _assembly.registerFunction( + static_cast(info.parameters.size()), + static_cast(info.returnVariables.size()), + !info.canContinue + ); + _builtinContext.functionIDs[function] = functionID; + } + } + OptimizedEVMCodeTransform optimizedCodeTransform( _assembly, _builtinContext, _useNamedLabelsForFunctions, *dfg, - stackLayout + stackLayout, + !_dialect.eofVersion().has_value(), + _dialect ); // Create initial entry layout. optimizedCodeTransform.createStackLayout(debugDataOf(*dfg->entry), stackLayout.blockInfos.at(dfg->entry).entryLayout); @@ -67,10 +86,11 @@ std::vector OptimizedEVMCodeTransform::run( void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) { + bool useReturnLabel = m_simulateFunctionsWithJumps && _call.canContinue; // Validate stack. { yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); - yulAssert(m_stack.size() >= _call.function.get().numArguments + (_call.canContinue ? 1 : 0), ""); + yulAssert(m_stack.size() >= _call.function.get().numArguments + (useReturnLabel ? 1 : 0), ""); // Assert that we got the correct arguments on stack for the call. for (auto&& [arg, slot]: ranges::zip_view( _call.functionCall.get().arguments | ranges::views::reverse, @@ -78,7 +98,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) )) validateSlot(slot, arg); // Assert that we got the correct return label on stack. - if (_call.canContinue) + if (useReturnLabel) { auto const* returnLabelSlot = std::get_if( &m_stack.at(m_stack.size() - _call.functionCall.get().arguments.size() - 1) @@ -90,19 +110,22 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) // Emit code. { m_assembly.setSourceLocation(originLocationOf(_call)); - m_assembly.appendJumpTo( - getFunctionLabel(_call.function), - static_cast(_call.function.get().numReturns) - static_cast(_call.function.get().numArguments) - (_call.canContinue ? 1 : 0), - AbstractAssembly::JumpType::IntoFunction - ); - if (_call.canContinue) + if (!m_simulateFunctionsWithJumps) + m_assembly.appendFunctionCall(m_builtinContext.functionIDs.at(&_call.function.get())); + else + m_assembly.appendJumpTo( + getFunctionLabel(_call.function), + static_cast(_call.function.get().numReturns) - static_cast(_call.function.get().numArguments) - (_call.canContinue ? 1 : 0), + AbstractAssembly::JumpType::IntoFunction + ); + if (useReturnLabel) m_assembly.appendLabel(m_returnLabels.at(&_call.functionCall.get())); } // Update stack. { // Remove arguments and return label from m_stack. - for (size_t i = 0; i < _call.function.get().numArguments + (_call.canContinue ? 1 : 0); ++i) + for (size_t i = 0; i < _call.function.get().numArguments + (useReturnLabel ? 1 : 0); ++i) m_stack.pop_back(); // Push return values to m_stack. for (size_t index: ranges::views::iota(0u, _call.function.get().numReturns)) @@ -177,13 +200,16 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions, CFG const& _dfg, - StackLayout const& _stackLayout + StackLayout const& _stackLayout, + bool _simulateFunctionsWithJumps, + EVMDialect const& _dialect ): m_assembly(_assembly), m_builtinContext(_builtinContext), m_dfg(_dfg), m_stackLayout(_stackLayout), - m_functionLabels([&](){ + m_dialect(_dialect), + m_functionLabels(!_simulateFunctionsWithJumps ? decltype(m_functionLabels)() : [&](){ std::map functionLabels; std::set assignedFunctionNames; for (Scope::Function const* function: m_dfg.functions) @@ -203,7 +229,9 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( m_assembly.newLabelId(); } return functionLabels; - }()) + }()), + m_simulateFunctionsWithJumps(_simulateFunctionsWithJumps), + m_reachableStackDepth(_dialect.reachableStackDepth()) { } @@ -216,6 +244,7 @@ void OptimizedEVMCodeTransform::assertLayoutCompatibility(Stack const& _currentS AbstractAssembly::LabelID OptimizedEVMCodeTransform::getFunctionLabel(Scope::Function const& _function) { + yulAssert(m_simulateFunctionsWithJumps); return m_functionLabels.at(&m_dfg.functionInfo.at(&_function)); } @@ -258,18 +287,18 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight(), ""); yulAssert(_i > 0 && _i < m_stack.size(), ""); - if (_i <= 16) - m_assembly.appendInstruction(evmasm::swapInstruction(_i)); + if (_i <= m_reachableStackDepth) + appendSwap(_i); else { - int deficit = static_cast(_i) - 16; + int deficit = static_cast(_i) - static_cast(m_reachableStackDepth); StackSlot const& deepSlot = m_stack.at(m_stack.size() - _i - 1); YulName varNameDeep = slotVariableName(deepSlot); YulName varNameTop = slotVariableName(m_stack.back()); std::string msg = - "Cannot swap " + (varNameDeep.empty() ? "Slot " + stackSlotToString(deepSlot) : "Variable " + varNameDeep.str()) + - " with " + (varNameTop.empty() ? "Slot " + stackSlotToString(m_stack.back()) : "Variable " + varNameTop.str()) + - ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack); + "Cannot swap " + (varNameDeep.empty() ? "Slot " + stackSlotToString(deepSlot, m_dialect) : "Variable " + varNameDeep.str()) + + " with " + (varNameTop.empty() ? "Slot " + stackSlotToString(m_stack.back(), m_dialect) : "Variable " + varNameTop.str()) + + ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack, m_dialect); m_stackErrors.emplace_back(StackTooDeepError( m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulName{}, varNameDeep.empty() ? varNameTop : varNameDeep, @@ -283,22 +312,21 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr [&](StackSlot const& _slot) { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight(), ""); - // Dup the slot, if already on stack and reachable. if (auto depth = util::findOffset(m_stack | ranges::views::reverse, _slot)) { - if (*depth < 16) + if (*depth < m_reachableStackDepth) { - m_assembly.appendInstruction(evmasm::dupInstruction(static_cast(*depth + 1))); + appendDup(*depth + 1); return; } else if (!canBeFreelyGenerated(_slot)) { - int deficit = static_cast(*depth - 15); + int deficit = static_cast(*depth - (m_reachableStackDepth - 1)); YulName varName = slotVariableName(_slot); std::string msg = - (varName.empty() ? "Slot " + stackSlotToString(_slot) : "Variable " + varName.str()) - + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack); + (varName.empty() ? "Slot " + stackSlotToString(_slot, m_dialect) : "Variable " + varName.str()) + + " is " + std::to_string(*depth - (m_reachableStackDepth - 1)) + " too deep in the stack " + stackToString(m_stack, m_dialect); m_stackErrors.emplace_back(StackTooDeepError( m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulName{}, varName, @@ -361,11 +389,34 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr [&]() { m_assembly.appendInstruction(evmasm::Instruction::POP); - } + }, + m_reachableStackDepth ); yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); } +void OptimizedEVMCodeTransform::appendSwap(size_t _depth) +{ + if (_depth <= 16) + m_assembly.appendInstruction(evmasm::swapInstruction(static_cast(_depth))); + else + { + yulAssert(_depth <= m_reachableStackDepth); + m_assembly.appendSwapN(_depth); + } +} + +void OptimizedEVMCodeTransform::appendDup(size_t _depth) +{ + if (_depth <= 16) + m_assembly.appendInstruction(evmasm::dupInstruction(static_cast(_depth))); + else + { + yulAssert(_depth <= m_reachableStackDepth); + m_assembly.appendDupN(_depth); + } +} + void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block) { // Assert that this is the first visit of the block and mark as generated. @@ -493,11 +544,15 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block) Stack exitStack = m_currentFunctionInfo->returnVariables | ranges::views::transform([](auto const& _varSlot){ return StackSlot{_varSlot}; }) | ranges::to; - exitStack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); + if (m_simulateFunctionsWithJumps) + exitStack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); // Create the function return layout and jump. createStackLayout(debugDataOf(_functionReturn), exitStack); - m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction); + if (!m_simulateFunctionsWithJumps) + m_assembly.appendFunctionReturn(); + else + m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction); }, [&](CFG::BasicBlock::Terminated const&) { @@ -518,25 +573,31 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block) void OptimizedEVMCodeTransform::operator()(CFG::FunctionInfo const& _functionInfo) { + bool useReturnLabel = m_simulateFunctionsWithJumps && _functionInfo.canContinue; yulAssert(!m_currentFunctionInfo, ""); ScopedSaveAndRestore currentFunctionInfoRestore(m_currentFunctionInfo, &_functionInfo); yulAssert(m_stack.empty() && m_assembly.stackHeight() == 0, ""); // Create function entry layout in m_stack. - if (_functionInfo.canContinue) + if (useReturnLabel) m_stack.emplace_back(FunctionReturnLabelSlot{_functionInfo.function}); for (auto const& param: _functionInfo.parameters | ranges::views::reverse) m_stack.emplace_back(param); + if (!m_simulateFunctionsWithJumps) + m_assembly.beginFunction(m_builtinContext.functionIDs[&_functionInfo.function]); m_assembly.setStackHeight(static_cast(m_stack.size())); m_assembly.setSourceLocation(originLocationOf(_functionInfo)); - m_assembly.appendLabel(getFunctionLabel(_functionInfo.function)); + if (m_simulateFunctionsWithJumps) + m_assembly.appendLabel(getFunctionLabel(_functionInfo.function)); // Create the entry layout of the function body block and visit. createStackLayout(debugDataOf(_functionInfo), m_stackLayout.blockInfos.at(_functionInfo.entry).entryLayout); (*this)(*_functionInfo.entry); m_stack.clear(); + if (!m_simulateFunctionsWithJumps) + m_assembly.endFunction(); m_assembly.setStackHeight(0); } diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.h b/libyul/backends/evm/OptimizedEVMCodeTransform.h index 7e648ca964bb..2cb251fba8d5 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.h +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.h @@ -68,7 +68,9 @@ class OptimizedEVMCodeTransform BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions, CFG const& _dfg, - StackLayout const& _stackLayout + StackLayout const& _stackLayout, + bool _simulateFunctionsWithJumps, + EVMDialect const& _dialect ); /// Assert that it is valid to transition from @a _currentStack to @a _desiredStack. @@ -85,6 +87,9 @@ class OptimizedEVMCodeTransform /// Sets the source locations to the one in @a _debugData. void createStackLayout(langutil::DebugData::ConstPtr _debugData, Stack _targetStack); + void appendSwap(size_t _depth); + void appendDup(size_t _depth); + /// Generate code for the given block @a _block. /// Expects the current stack layout m_stack to be a stack layout that is compatible with the /// entry layout expected by the block. @@ -101,15 +106,20 @@ class OptimizedEVMCodeTransform BuiltinContext& m_builtinContext; CFG const& m_dfg; StackLayout const& m_stackLayout; + EVMDialect const& m_dialect; Stack m_stack; std::map m_returnLabels; std::map m_blockLabels; + /// Non-empty only if m_dfg.simulateFunctionsWithJumps == true std::map const m_functionLabels; /// Set of blocks already generated. If any of the contained blocks is ever jumped to, m_blockLabels should /// contain a jump label for it. std::set m_generated; CFG::FunctionInfo const* m_currentFunctionInfo = nullptr; std::vector m_stackErrors; + /// True if it simulates functions with jumps. False otherwise. True for legacy bytecode + bool m_simulateFunctionsWithJumps = true; + size_t const m_reachableStackDepth{}; }; } diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/SSACFGLiveness.cpp new file mode 100644 index 000000000000..a0bfeb5bb143 --- /dev/null +++ b/libyul/backends/evm/SSACFGLiveness.cpp @@ -0,0 +1,185 @@ +/* + 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 + +using namespace solidity::yul; + +namespace +{ +constexpr auto literalsFilter(SSACFG const& _cfg) +{ + return [&_cfg](SSACFG::ValueId const& _valueId) -> bool + { + return !std::holds_alternative(_cfg.valueInfo(_valueId));; + }; +} +} + +std::set SSACFGLiveness::blockExitValues(SSACFG::BlockId const& _blockId) const +{ + std::set result; + util::GenericVisitor exitVisitor { + [](SSACFG::BasicBlock::MainExit const&) {}, + [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { + result += _functionReturn.returnValues | ranges::views::filter(literalsFilter(m_cfg)); + }, + [&](SSACFG::BasicBlock::JumpTable const& _jt) { + if (literalsFilter(m_cfg)(_jt.value)) + result.emplace(_jt.value); + }, + [](SSACFG::BasicBlock::Jump const&) {}, + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { + if (literalsFilter(m_cfg)(_conditionalJump.condition)) + result.emplace(_conditionalJump.condition); + }, + [](SSACFG::BasicBlock::Terminated const&) {} + }; + std::visit(exitVisitor, m_cfg.block(_blockId).exit); + return result; +} + +SSACFGLiveness::SSACFGLiveness(SSACFG const& _cfg): + m_cfg(_cfg), + m_topologicalSort(_cfg), + m_loopNestingForest(m_topologicalSort), + m_liveIns(_cfg.numBlocks()), + m_liveOuts(_cfg.numBlocks()), + m_operationLiveOuts(_cfg.numBlocks()) +{ + runDagDfs(); + for (auto const loopRootNode: m_loopNestingForest.loopRootNodes()) + runLoopTreeDfs(loopRootNode); + + fillOperationsLiveOut(); +} + +void SSACFGLiveness::runDagDfs() +{ + // SSA Book, Algorithm 9.2 + for (auto const blockIdValue: m_topologicalSort.postOrder()) + { + // post-order traversal + SSACFG::BlockId blockId{blockIdValue}; + auto const& block = m_cfg.block(blockId); + + // live <- PhiUses(B) + std::set live{}; + block.forEachExit( + [&](SSACFG::BlockId const& _successor) + { + for (auto const& phi: m_cfg.block(_successor).phis) + { + auto const& info = m_cfg.valueInfo(phi); + yulAssert(std::holds_alternative(info), "value info of phi wasn't PhiValue"); + auto const argIndex = m_cfg.phiArgumentIndex(blockId, _successor); + yulAssert(argIndex < std::get(info).arguments.size()); + auto const arg = std::get(info).arguments.at(argIndex); + if (!std::holds_alternative(m_cfg.valueInfo(arg))) + live.insert(arg); + } + }); + + // for each S \in succs(B) s.t. (B, S) not a back edge: live <- live \cup (LiveIn(S) - PhiDefs(S)) + block.forEachExit( + [&](SSACFG::BlockId const& _successor) { + if (!m_topologicalSort.backEdge(blockId, _successor)) + live += m_liveIns[_successor.value] - m_cfg.block(_successor).phis; + }); + + if (std::holds_alternative(block.exit)) + live += std::get(block.exit).returnValues + | ranges::views::filter(literalsFilter(m_cfg)); + + // clean out unreachables + live = live | ranges::views::filter([&](auto const& valueId) { return !std::holds_alternative(m_cfg.valueInfo(valueId)); }) | ranges::to; + + // LiveOut(B) <- live + m_liveOuts[blockId.value] = live; + + // for each program point p in B, backwards, do: + { + // add value ids to the live set that are used in exit blocks + live += blockExitValues(blockId); + + for (auto const& op: block.operations | ranges::views::reverse) + { + // remove variables defined at p from live + live -= op.outputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + // add uses at p to live + live += op.inputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + } + } + + // livein(b) <- live \cup PhiDefs(B) + m_liveIns[blockId.value] = live + block.phis; + } +} + +void SSACFGLiveness::runLoopTreeDfs(size_t const _loopHeader) +{ + // SSA Book, Algorithm 9.3 + if (m_loopNestingForest.loopNodes().count(_loopHeader) > 0) + { + // the loop header block id + auto const& block = m_cfg.block(SSACFG::BlockId{_loopHeader}); + // LiveLoop <- LiveIn(B_N) - PhiDefs(B_N) + auto liveLoop = m_liveIns[_loopHeader] - block.phis; + // must be live out of header if live in of children + m_liveOuts[_loopHeader] += liveLoop; + // for each blockId \in children(loopHeader) + for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) + if (m_loopNestingForest.loopParents()[blockIdValue] == _loopHeader) + { + // propagate loop liveness information down to the loop header's children + m_liveIns[blockIdValue] += liveLoop; + m_liveOuts[blockIdValue] += liveLoop; + + runLoopTreeDfs(blockIdValue); + } + } +} + +void SSACFGLiveness::fillOperationsLiveOut() +{ + for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) + { + SSACFG::BlockId const blockId{blockIdValue}; + auto const& operations = m_cfg.block(blockId).operations; + auto& liveOuts = m_operationLiveOuts[blockIdValue]; + liveOuts.resize(operations.size()); + if (!operations.empty()) + { + auto live = m_liveOuts[blockIdValue] + blockExitValues(blockId); + auto rit = liveOuts.rbegin(); + for (auto const& op: operations | ranges::views::reverse) + { + *rit = live; + live -= op.outputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + live += op.inputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + ++rit; + } + } + } +} diff --git a/libyul/backends/evm/SSACFGLiveness.h b/libyul/backends/evm/SSACFGLiveness.h new file mode 100644 index 000000000000..6ec0d16884d6 --- /dev/null +++ b/libyul/backends/evm/SSACFGLiveness.h @@ -0,0 +1,60 @@ +/* + 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 + +namespace solidity::yul +{ + +/// Performs liveness analysis on a reducible SSA CFG following Algorithm 9.1 in [1]. +/// +/// [1] Rastello, Fabrice, and Florent Bouchez Tichadou, eds. SSA-based Compiler Design. Springer, 2022. +class SSACFGLiveness +{ +public: + using LivenessData = std::set; + explicit SSACFGLiveness(SSACFG const& _cfg); + + LivenessData const& liveIn(SSACFG::BlockId _blockId) const { return m_liveIns[_blockId.value]; } + LivenessData const& liveOut(SSACFG::BlockId _blockId) const { return m_liveOuts[_blockId.value]; } + std::vector const& operationsLiveOut(SSACFG::BlockId _blockId) const { return m_operationLiveOuts[_blockId.value]; } + ForwardSSACFGTopologicalSort const& topologicalSort() const { return m_topologicalSort; } +private: + + void runDagDfs(); + void runLoopTreeDfs(size_t _loopHeader); + void fillOperationsLiveOut(); + std::set blockExitValues(SSACFG::BlockId const& _blockId) const; + + SSACFG const& m_cfg; + ForwardSSACFGTopologicalSort m_topologicalSort; + SSACFGLoopNestingForest m_loopNestingForest; + std::vector m_liveIns; + std::vector m_liveOuts; + std::vector> m_operationLiveOuts; +}; + +} diff --git a/libyul/backends/evm/SSACFGTopologicalSort.cpp b/libyul/backends/evm/SSACFGTopologicalSort.cpp index 5e3e0c0ec61b..881e48ea1b32 100644 --- a/libyul/backends/evm/SSACFGTopologicalSort.cpp +++ b/libyul/backends/evm/SSACFGTopologicalSort.cpp @@ -28,11 +28,7 @@ ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): yulAssert(m_cfg.entry.value == 0); m_preOrder.reserve(m_cfg.numBlocks()); m_postOrder.reserve(m_cfg.numBlocks()); - for (size_t id = 0; id < m_cfg.numBlocks(); ++id) - { - if (!m_explored[id]) - dfs(id); - } + dfs(0); for (auto const& [v1, v2]: m_potentialBackEdges) if (ancestor(v2, v1)) diff --git a/libyul/backends/evm/SSACFGTopologicalSort.h b/libyul/backends/evm/SSACFGTopologicalSort.h index 973f286f286a..025054b9504c 100644 --- a/libyul/backends/evm/SSACFGTopologicalSort.h +++ b/libyul/backends/evm/SSACFGTopologicalSort.h @@ -38,6 +38,8 @@ class ForwardSSACFGTopologicalSort std::set const& backEdgeTargets() const { return m_backEdgeTargets; } SSACFG const& cfg() const { return m_cfg; } bool backEdge(SSACFG::BlockId const& _block1, SSACFG::BlockId const& _block2) const; + size_t preOrderIndexOf(size_t _block) const { return m_blockWisePreOrder[_block]; } + size_t maxSubtreePreOrderIndexOf(size_t _block) const { return m_blockWiseMaxSubtreePreOrder[_block]; } private: void dfs(size_t _vertex); diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/SSAControlFlowGraph.cpp index e98936aaabbd..733f4967d806 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.cpp +++ b/libyul/backends/evm/SSAControlFlowGraph.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include @@ -37,13 +39,15 @@ namespace class SSACFGPrinter { public: - SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId) + SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness): + m_cfg(_cfg), m_functionIndex(0), m_liveness(_liveness) { - printBlock(_cfg, _blockId, 0); + printBlock(_blockId); } - SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function) + SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function, SSACFGLiveness const* _liveness): + m_cfg(_cfg), m_functionIndex(_functionIndex), m_liveness(_liveness) { - printFunction(_cfg, _functionIndex, _function); + printFunction(_function); } friend std::ostream& operator<<(std::ostream& stream, SSACFGPrinter const& printer) { stream << printer.m_result.str(); @@ -73,6 +77,39 @@ class SSACFGPrinter ); } + static std::string escape(std::string_view const str) + { + using namespace std::literals; + static constexpr auto replacements = std::array{std::make_tuple('$', "_d_")}; + std::stringstream ss; + for (auto const c: str) + { + auto const it = std::find_if(replacements.begin(), replacements.end(), [c](auto const& replacement) + { + return std::get<0>(replacement) == c; + }); + if (it != replacements.end()) + ss << std::get<1>(*it); + else + ss << c; + } + return ss.str(); + } + + std::string formatBlockHandle(SSACFG::BlockId const& _id) const + { + return fmt::format("Block{}_{}", m_functionIndex, _id.value); + } + + std::string formatEdge(SSACFG::BlockId const& _v, SSACFG::BlockId const& _w, std::optional const& _vPort = std::nullopt) + { + std::string const style = m_liveness && m_liveness->topologicalSort().backEdge(_v, _w) ? "dashed" : "solid"; + if (_vPort) + return fmt::format("{}Exit:{} -> {} [style=\"{}\"];\n", formatBlockHandle(_v), *_vPort, formatBlockHandle(_w), style); + else + return fmt::format("{}Exit -> {} [style=\"{}\"];\n", formatBlockHandle(_v), formatBlockHandle(_w), style); + } + static std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) { auto const transform = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; @@ -86,22 +123,41 @@ class SSACFGPrinter return "φ()"; } - void writeBlock(SSACFG const& _cfg, SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block, size_t const _functionIndex) + void writeBlock(SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block) { - auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; - bool entryBlock = _id.value == 0 && _functionIndex == 0; + auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(m_cfg, valueId); }; + bool entryBlock = _id.value == 0 && m_functionIndex == 0; if (entryBlock) { - m_result << fmt::format("Entry{} [label=\"Entry\"];\n", _functionIndex); - m_result << fmt::format("Entry{} -> Block{}_{};\n", _functionIndex, _functionIndex, _id.value); + m_result << fmt::format("Entry{} [label=\"Entry\"];\n", m_functionIndex); + m_result << fmt::format("Entry{} -> {};\n", m_functionIndex, formatBlockHandle(_id)); } { - m_result << fmt::format("Block{1}_{0} [label=\"\\\nBlock {0}\\n", _id.value, _functionIndex); + if (m_liveness) + { + m_result << fmt::format( + "{} [label=\"\\\nBlock {}; ({}, max {})\\n", + formatBlockHandle(_id), + _id.value, + m_liveness->topologicalSort().preOrderIndexOf(_id.value), + m_liveness->topologicalSort().maxSubtreePreOrderIndexOf(_id.value) + ); + m_result << fmt::format( + "LiveIn: {}\\l\\\n", + fmt::join(m_liveness->liveIn(_id) | ranges::views::transform(valueToString), ",") + ); + m_result << fmt::format( + "LiveOut: {}\\l\\n", + fmt::join(m_liveness->liveOut(_id) | ranges::views::transform(valueToString), ",") + ); + } + else + m_result << fmt::format("{} [label=\"\\\nBlock {}\\n", formatBlockHandle(_id), _id.value); for (auto const& phi: _block.phis) { - auto const* phiValue = std::get_if(&_cfg.valueInfo(phi)); + auto const* phiValue = std::get_if(&m_cfg.valueInfo(phi)); solAssert(phiValue); - m_result << fmt::format("v{} := {}\\l\\\n", phi.value, formatPhi(_cfg, *phiValue)); + m_result << fmt::format("v{} := {}\\l\\\n", phi.value, formatPhi(m_cfg, *phiValue)); } for (auto const& operation: _block.operations) { @@ -110,7 +166,7 @@ class SSACFGPrinter return _call.function.get().name.str(); }, [&](SSACFG::BuiltinCall const& _call) { - return _call.builtin.get().name.str(); + return _call.builtin.get().name; }, }, operation.kind); if (!operation.outputs.empty()) @@ -120,7 +176,7 @@ class SSACFGPrinter ); m_result << fmt::format( "{}({})\\l\\\n", - label, + escape(label), fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") ); } @@ -128,29 +184,28 @@ class SSACFGPrinter std::visit(GenericVisitor{ [&](SSACFG::BasicBlock::MainExit const&) { - m_result << fmt::format("Block{}_{}Exit [label=\"MainExit\"];\n", _functionIndex, _id.value); - m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit;\n", _id.value, _functionIndex); + m_result << fmt::format("{}Exit [label=\"MainExit\"];\n", formatBlockHandle(_id)); + m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); }, [&](SSACFG::BasicBlock::Jump const& _jump) { - m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit [arrowhead=none];\n", _id.value, _functionIndex); - m_result << fmt::format("Block{}_{}Exit [label=\"Jump\" shape=oval];\n", _functionIndex, _id.value); - m_result << fmt::format("Block{}_{}Exit -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, _jump.target.value); + m_result << fmt::format("{} -> {}Exit [arrowhead=none];\n", formatBlockHandle(_id), formatBlockHandle(_id)); + m_result << fmt::format("{}Exit [label=\"Jump\" shape=oval];\n", formatBlockHandle(_id)); + m_result << formatEdge(_id, _jump.target); }, [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"{ If "; - m_result << varToString(_cfg, _conditionalJump.condition); - m_result << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value; - m_result << "Exit:0 -> Block" << _functionIndex << "_" << _conditionalJump.zero.value << ";\n"; - m_result << "Block" << _functionIndex << "_" << _id.value; - m_result << "Exit:1 -> Block" << _functionIndex << "_" << _conditionalJump.nonZero.value << ";\n"; + m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); + m_result << fmt::format( + "{}Exit [label=\"{{ If {} | {{ <0> Zero | <1> NonZero }}}}\" shape=Mrecord];\n", + formatBlockHandle(_id), varToString(m_cfg, _conditionalJump.condition) + ); + m_result << formatEdge(_id, _conditionalJump.zero, "0"); + m_result << formatEdge(_id, _conditionalJump.nonZero, "1"); }, [&](SSACFG::BasicBlock::JumpTable const& jt) { - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); std::string options; for (auto const& jumpCase: jt.cases) { @@ -161,28 +216,28 @@ class SSACFGPrinter if (!options.empty()) options += " | "; options += " default"; - m_result << fmt::format("Block{}_{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", _functionIndex, _id.value, options); + m_result << fmt::format("{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", formatBlockHandle(_id), options); for (auto const& jumpCase: jt.cases) - m_result << fmt::format("Block{}_{}Exit:{} -> Block{}_{};\n", _functionIndex, _id.value, formatNumber(jumpCase.first), _functionIndex, jumpCase.second.value); - m_result << fmt::format("Block{}_{}Exit:default -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, jt.defaultCase.value); + m_result << formatEdge(_id, jumpCase.second, formatNumber(jumpCase.first)); + m_result << formatEdge(_id, jt.defaultCase, "default"); }, [&](SSACFG::BasicBlock::FunctionReturn const& fr) { - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"FunctionReturn[" + m_result << formatBlockHandle(_id) << "Exit [label=\"FunctionReturn[" << fmt::format("{}", fmt::join(fr.returnValues | ranges::views::transform(valueToString), ", ")) << "]\"];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + m_result << formatBlockHandle(_id) << " -> " << formatBlockHandle(_id) << "Exit;\n"; }, [&](SSACFG::BasicBlock::Terminated const&) { - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"Terminated\"];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + m_result << formatBlockHandle(_id) << "Exit [label=\"Terminated\"];\n"; + m_result << formatBlockHandle(_id) << " -> " << formatBlockHandle(_id) << "Exit;\n"; } }, _block.exit); } } - void printBlock(SSACFG const& _cfg, SSACFG::BlockId const& _rootId, size_t const _functionIndex) + void printBlock(SSACFG::BlockId const& _rootId) { std::set explored{}; explored.insert(_rootId); @@ -194,8 +249,8 @@ class SSACFGPrinter { auto const id = toVisit.front(); toVisit.pop_front(); - auto const& block = _cfg.block(id); - writeBlock(_cfg, id, block, _functionIndex); + auto const& block = m_cfg.block(id); + writeBlock(id, block); block.forEachExit( [&](SSACFG::BlockId const& _exitBlock) { @@ -209,33 +264,40 @@ class SSACFGPrinter } } - void printFunction(SSACFG const& _cfg, size_t const _functionIndex, Scope::Function const& _fun) + void printFunction(Scope::Function const& _fun) { - static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return functionReturnValue.get().name.str(); }; + static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return escape(functionReturnValue.get().name.str()); }; static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value); }; - m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " [label=\""; - if (!_cfg.returns.empty()) - m_result << fmt::format("function {0}:\n {1} := {0}({2})", _fun.name.str(), fmt::join(_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + m_result << "FunctionEntry_" << escape(_fun.name.str()) << "_" << m_cfg.entry.value << " [label=\""; + if (!m_cfg.returns.empty()) + m_result << fmt::format("function {0}:\n {1} := {0}({2})", escape(_fun.name.str()), fmt::join(m_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); else - m_result << fmt::format("function {0}:\n {0}({1})", _fun.name.str(), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + m_result << fmt::format("function {0}:\n {0}({1})", escape(_fun.name.str()), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); m_result << "\"];\n"; - m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " -> Block" << _functionIndex << "_" << _cfg.entry.value << ";\n"; - printBlock(_cfg, _cfg.entry, _functionIndex); + m_result << "FunctionEntry_" << escape(_fun.name.str()) << "_" << m_cfg.entry.value << " -> Block" << m_functionIndex << "_" << m_cfg.entry.value << ";\n"; + printBlock(m_cfg.entry); } + SSACFG const& m_cfg; + size_t m_functionIndex; + SSACFGLiveness const* m_liveness; std::stringstream m_result{}; }; } -std::string SSACFG::toDot(bool _includeDiGraphDefinition, std::optional _functionIndex) const +std::string SSACFG::toDot( + bool _includeDiGraphDefinition, + std::optional _functionIndex, + SSACFGLiveness const* _liveness +) const { std::ostringstream output; if (_includeDiGraphDefinition) output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; if (function) - output << SSACFGPrinter(*this, _functionIndex ? *_functionIndex : static_cast(1), *function); + output << SSACFGPrinter(*this, _functionIndex ? *_functionIndex : static_cast(1), *function, _liveness); else - output << SSACFGPrinter(*this, entry); + output << SSACFGPrinter(*this, entry, _liveness); if (_includeDiGraphDefinition) output << "}\n"; return output.str(); diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/SSAControlFlowGraph.h index fd24f06cbb2b..9397e0e207c1 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.h +++ b/libyul/backends/evm/SSAControlFlowGraph.h @@ -37,6 +37,7 @@ namespace solidity::yul { +class SSACFGLiveness; class SSACFG { @@ -75,7 +76,7 @@ class SSACFG langutil::DebugData::ConstPtr debugData; std::reference_wrapper function; std::reference_wrapper call; - bool const canContinue = true; + bool canContinue; }; struct Operation { @@ -161,6 +162,10 @@ class SSACFG }; struct UnreachableValue {}; using ValueInfo = std::variant; + bool isLiteralValue(ValueId const _var) const + { + return std::holds_alternative(valueInfo(_var)); + } ValueInfo& valueInfo(ValueId const _var) { return m_valueInfos.at(_var.value); @@ -207,7 +212,19 @@ class SSACFG return it->second; } - std::string toDot(bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt) const; + size_t phiArgumentIndex(BlockId const _source, BlockId const _target) const + { + auto const& targetBlock = block(_target); + auto idx = util::findOffset(targetBlock.entries, _source); + yulAssert(idx, fmt::format("Target block {} not found as entry in one of the exits of the current block {}.", _target.value, _source.value)); + return *idx; + } + + std::string toDot( + bool _includeDiGraphDefinition=true, + std::optional _functionIndex=std::nullopt, + SSACFGLiveness const* _liveness=nullptr + ) const; private: std::deque m_valueInfos; std::map m_literals; diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 92b91e8ae1e9..bf8cfd92a802 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -24,11 +24,11 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -196,7 +196,7 @@ void SSAControlFlowGraphBuilder::cleanUnreachable() it = block.entries.erase(it); for (auto phi: block.phis) if (auto* phiInfo = std::get_if(&m_graph.valueInfo(phi))) - cxx20::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { + std::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { if (isUnreachableValue(_arg)) { maybeTrivialPhi.insert(phi); @@ -342,19 +342,21 @@ void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) } else { + std::optional equalityBuiltinHandle = m_dialect.equalityFunctionHandle(); + yulAssert(equalityBuiltinHandle); + auto makeValueCompare = [&](Case const& _case) { FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(FunctionCall{ debugDataOf(_case), - Identifier{{}, "eq"_yulname}, + BuiltinName{{}, *equalityBuiltinHandle}, {*_case.value /* skip second argument */ } }); auto outputValue = m_graph.newVariable(m_currentBlock); - BuiltinFunction const* builtin = m_dialect.builtin(ghostCall.functionName.name); currentBlock().operations.emplace_back(SSACFG::Operation{ {outputValue}, SSACFG::BuiltinCall{ debugDataOf(_case), - *builtin, + m_dialect.builtin(*equalityBuiltinHandle), ghostCall }, {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} @@ -421,6 +423,7 @@ void SSAControlFlowGraphBuilder::operator()(ForLoop const& _loop) if (constantCondition.has_value()) { + std::visit(*this, *_loop.condition); if (*constantCondition) { jump(debugDataOf(*_loop.condition), loopBody); @@ -546,7 +549,7 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct { bool canContinue = true; SSACFG::Operation operation = [&](){ - if (BuiltinFunction const* builtin = m_dialect.builtin(_call.functionName.name)) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_call.functionName, m_dialect)) { SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, *builtin, _call}, {}}; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) @@ -559,7 +562,8 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct } else { - Scope::Function const& function = lookupFunction(_call.functionName.name); + YulName const functionName{resolveFunctionName(_call.functionName, m_dialect)}; + Scope::Function const& function = lookupFunction(functionName); auto const* definition = findFunctionDefinition(&function); yulAssert(definition); canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; diff --git a/libyul/backends/evm/StackHelpers.h b/libyul/backends/evm/StackHelpers.h index dae4352a02c4..c5d63847153a 100644 --- a/libyul/backends/evm/StackHelpers.h +++ b/libyul/backends/evm/StackHelpers.h @@ -20,6 +20,7 @@ #include #include +#include #include @@ -33,29 +34,28 @@ namespace solidity::yul { -inline std::string stackSlotToString(StackSlot const& _slot) +inline std::string stackSlotToString(StackSlot const& _slot, Dialect const& _dialect) { return std::visit(util::GenericVisitor{ - [](FunctionCallReturnLabelSlot const& _ret) -> std::string { return "RET[" + _ret.call.get().functionName.name.str() + "]"; }, + [&](FunctionCallReturnLabelSlot const& _ret) -> std::string { return "RET[" + std::string(resolveFunctionName(_ret.call.get().functionName, _dialect)) + "]"; }, [](FunctionReturnLabelSlot const&) -> std::string { return "RET"; }, [](VariableSlot const& _var) { return _var.variable.get().name.str(); }, [](LiteralSlot const& _lit) { return toCompactHexWithPrefix(_lit.value); }, - [](TemporarySlot const& _tmp) -> std::string { return "TMP[" + _tmp.call.get().functionName.name.str() + ", " + std::to_string(_tmp.index) + "]"; }, + [&](TemporarySlot const& _tmp) -> std::string { return "TMP[" + std::string(resolveFunctionName(_tmp.call.get().functionName, _dialect)) + ", " + std::to_string(_tmp.index) + "]"; }, [](JunkSlot const&) -> std::string { return "JUNK"; } }, _slot); } -inline std::string stackToString(Stack const& _stack) +inline std::string stackToString(Stack const& _stack, Dialect const& _dialect) { std::string result("[ "); for (auto const& slot: _stack) - result += stackSlotToString(slot) + ' '; + result += stackSlotToString(slot, _dialect) + ' '; result += ']'; return result; } -// Abstraction of stack shuffling operations. Can be defined as actual concept once we switch to C++20. // Used as an interface for the stack shuffler below. // The shuffle operation class is expected to internally keep track of a current stack layout (the "source layout") // that the shuffler is supposed to shuffle to a fixed target stack layout. @@ -64,7 +64,6 @@ inline std::string stackToString(Stack const& _stack) // in the interface below. // Based on that information the shuffler decides which is the next optimal operation to perform on the stack // and calls the corresponding entry point in the shuffling operations (swap, pushOrDupTarget or pop). -/* template concept ShuffleOperationConcept = requires(ShuffleOperations ops, size_t sourceOffset, size_t targetOffset, size_t depth) { // Returns true, iff the current slot at sourceOffset in source layout is a suitable slot at targetOffset. @@ -97,11 +96,13 @@ concept ShuffleOperationConcept = requires(ShuffleOperations ops, size_t sourceO { ops.pop() }; // Dups or pushes the slot that is supposed to end up at the given target offset. { ops.pushOrDupTarget(targetOffset) }; + // Maximum reachable depth with swaps and dups. + { ops.reachableStackDepth } -> std::convertible_to; }; -*/ + /// Helper class that can perform shuffling of a source stack layout to a target stack layout via /// abstracted shuffle operations. -template +template class Shuffler { public: @@ -127,10 +128,10 @@ class Shuffler static bool dupDeepSlotIfRequired(ShuffleOperations& _ops) { // Check if the stack is large enough for anything to potentially become unreachable. - if (_ops.sourceSize() < 15) + if (_ops.sourceSize() < (_ops.reachableStackDepth - 1)) return false; // Check whether any deep slot might still be needed later (i.e. we still need to reach it with a DUP or SWAP). - for (size_t sourceOffset: ranges::views::iota(0u, _ops.sourceSize() - 15)) + for (size_t sourceOffset: ranges::views::iota(0u, _ops.sourceSize() - (_ops.reachableStackDepth - 1))) { // This slot needs to be moved. if (!_ops.isCompatible(sourceOffset, sourceOffset)) @@ -255,10 +256,10 @@ class Shuffler ) { // We cannot swap that deep. - if (ops.sourceSize() - offset - 1 > 16) + if (ops.sourceSize() - offset - 1 > ops.reachableStackDepth) { // If there is a reachable slot to be removed, park the current top there. - for (size_t swapDepth: ranges::views::iota(1u, 17u) | ranges::views::reverse) + for (size_t swapDepth: ranges::views::iota(1u, ops.reachableStackDepth + 1u) | ranges::views::reverse) if (ops.sourceMultiplicity(ops.sourceSize() - 1 - swapDepth) < 0) { ops.swap(swapDepth); @@ -326,7 +327,7 @@ class Shuffler yulAssert(ops.sourceMultiplicity(i) == 0 && (ops.targetIsArbitrary(i) || ops.targetMultiplicity(i) == 0), ""); yulAssert(ops.isCompatible(sourceTop, sourceTop), ""); - auto swappableOffsets = ranges::views::iota(size > 17 ? size - 17 : 0u, size); + auto swappableOffsets = ranges::views::iota(size > ops.reachableStackDepth + 1u ? size - (ops.reachableStackDepth + 1u) : 0u, size); // If we find a lower slot that is out of position, but also compatible with the top, swap that up. for (size_t offset: swappableOffsets) @@ -430,7 +431,14 @@ class Multiplicity /// its argument to the stack top. /// @a _pop is a function with signature void() that is called when the top most slot is popped. template -void createStackLayout(Stack& _currentStack, Stack const& _targetStack, Swap _swap, PushOrDup _pushOrDup, Pop _pop) +void createStackLayout( + Stack& _currentStack, + Stack const& _targetStack, + Swap _swap, + PushOrDup _pushOrDup, + Pop _pop, + size_t _reachableStackDepth +) { struct ShuffleOperations { @@ -440,18 +448,21 @@ void createStackLayout(Stack& _currentStack, Stack const& _targetStack, Swap _sw PushOrDup pushOrDupCallback; Pop popCallback; Multiplicity multiplicity; + size_t reachableStackDepth; ShuffleOperations( Stack& _currentStack, Stack const& _targetStack, Swap _swap, PushOrDup _pushOrDup, - Pop _pop + Pop _pop, + size_t _reachableStackDepth ): currentStack(_currentStack), targetStack(_targetStack), swapCallback(_swap), pushOrDupCallback(_pushOrDup), - popCallback(_pop) + popCallback(_pop), + reachableStackDepth(_reachableStackDepth) { for (auto const& slot: currentStack) --multiplicity[slot]; @@ -498,7 +509,7 @@ void createStackLayout(Stack& _currentStack, Stack const& _targetStack, Swap _sw } }; - Shuffler::shuffle(_currentStack, _targetStack, _swap, _pushOrDup, _pop); + Shuffler::shuffle(_currentStack, _targetStack, _swap, _pushOrDup, _pop, _reachableStackDepth); yulAssert(_currentStack.size() == _targetStack.size(), ""); for (auto&& [current, target]: ranges::zip_view(_currentStack, _targetStack)) diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 1a30842aecc8..69045998c859 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -26,8 +26,6 @@ #include #include -#include -#include #include #include @@ -47,30 +45,45 @@ using namespace solidity; using namespace solidity::yul; -StackLayout StackLayoutGenerator::run(CFG const& _cfg) +StackLayout StackLayoutGenerator::run(CFG const& _cfg, EVMDialect const& _evmDialect) { - StackLayout stackLayout; - StackLayoutGenerator{stackLayout, nullptr}.processEntryPoint(*_cfg.entry); + StackLayout stackLayout{{}, {}}; + StackLayoutGenerator{ + stackLayout, + nullptr, + _evmDialect + }.processEntryPoint(*_cfg.entry); for (auto& functionInfo: _cfg.functionInfo | ranges::views::values) - StackLayoutGenerator{stackLayout, &functionInfo}.processEntryPoint(*functionInfo.entry, &functionInfo); + StackLayoutGenerator{ + stackLayout, + &functionInfo, + _evmDialect + }.processEntryPoint(*functionInfo.entry, &functionInfo); return stackLayout; } -std::map> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg) +std::map> StackLayoutGenerator::reportStackTooDeep( + CFG const& _cfg, + EVMDialect const& _evmDialect +) { std::map> stackTooDeepErrors; - stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}); + stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}, _evmDialect); for (auto const& function: _cfg.functions) - if (auto errors = reportStackTooDeep(_cfg, function->name); !errors.empty()) + if (auto errors = reportStackTooDeep(_cfg, function->name, _evmDialect); !errors.empty()) stackTooDeepErrors[function->name] = std::move(errors); return stackTooDeepErrors; } -std::vector StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulName _functionName) +std::vector StackLayoutGenerator::reportStackTooDeep( + CFG const& _cfg, + YulName _functionName, + EVMDialect const& _evmDialect +) { - StackLayout stackLayout; + StackLayout stackLayout{{}, {}}; CFG::FunctionInfo const* functionInfo = nullptr; if (!_functionName.empty()) { @@ -82,22 +95,31 @@ std::vector StackLayoutGenerator::reportStac yulAssert(functionInfo, "Function not found."); } - StackLayoutGenerator generator{stackLayout, functionInfo}; + StackLayoutGenerator generator{stackLayout, functionInfo, _evmDialect}; CFG::BasicBlock const* entry = functionInfo ? functionInfo->entry : _cfg.entry; generator.processEntryPoint(*entry); return generator.reportStackTooDeep(*entry); } -StackLayoutGenerator::StackLayoutGenerator(StackLayout& _layout, CFG::FunctionInfo const* _functionInfo): +StackLayoutGenerator::StackLayoutGenerator( + StackLayout& _layout, + CFG::FunctionInfo const* _functionInfo, + EVMDialect const& _evmDialect +): m_layout(_layout), - m_currentFunctionInfo(_functionInfo) + m_currentFunctionInfo(_functionInfo), + m_evmDialect(_evmDialect) { } namespace { /// @returns all stack too deep errors that would occur when shuffling @a _source to @a _target. -std::vector findStackTooDeep(Stack const& _source, Stack const& _target) +std::vector findStackTooDeep( + Stack const& _source, + Stack const& _target, + size_t _reachableStackDepth +) { Stack currentStack = _source; std::vector stackTooDeepErrors; @@ -114,9 +136,9 @@ std::vector findStackTooDeep(Stack const& _s _target, [&](unsigned _i) { - if (_i > 16) + if (_i > _reachableStackDepth) stackTooDeepErrors.emplace_back(StackLayoutGenerator::StackTooDeep{ - _i - 16, + _i - _reachableStackDepth, getVariableChoices(currentStack | ranges::views::take_last(_i + 1)) }); }, @@ -126,14 +148,15 @@ std::vector findStackTooDeep(Stack const& _s return; if ( auto depth = util::findOffset(currentStack | ranges::views::reverse, _slot); - depth && *depth >= 16 + depth && *depth >= _reachableStackDepth ) stackTooDeepErrors.emplace_back(StackLayoutGenerator::StackTooDeep{ - *depth - 15, + *depth - (_reachableStackDepth - 1), getVariableChoices(currentStack | ranges::views::take_last(*depth + 1)) }); }, - [&]() {} + [&]() {}, + _reachableStackDepth ); return stackTooDeepErrors; } @@ -143,7 +166,7 @@ std::vector findStackTooDeep(Stack const& _s /// If @a _generateSlotOnTheFly returns true for a slot, this slot should not occur in the ideal stack, but /// rather be generated on the fly during shuffling. template -Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Callable _generateSlotOnTheFly) +Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Callable _generateSlotOnTheFly, size_t _reachableStackDepth) { struct PreviousSlot { size_t slot; }; @@ -175,11 +198,13 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla std::set outputs; Multiplicity multiplicity; Callable generateSlotOnTheFly; + size_t const reachableStackDepth; ShuffleOperations( std::vector>& _layout, Stack const& _post, - Callable _generateSlotOnTheFly - ): layout(_layout), post(_post), generateSlotOnTheFly(_generateSlotOnTheFly) + Callable _generateSlotOnTheFly, + size_t _reachableStackDepth + ): layout(_layout), post(_post), generateSlotOnTheFly(_generateSlotOnTheFly), reachableStackDepth(_reachableStackDepth) { for (auto const& layoutSlot: layout) if (StackSlot const* slot = std::get_if(&layoutSlot)) @@ -242,7 +267,7 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla void pop() { layout.pop_back(); } void pushOrDupTarget(size_t _offset) { layout.push_back(post.at(_offset)); } }; - Shuffler::shuffle(layout, _post, _generateSlotOnTheFly); + Shuffler::shuffle(layout, _post, _generateSlotOnTheFly, _reachableStackDepth); // Now we can construct the ideal layout before the operation. // "layout" has shuffled the PreviousSlot{x} to new places using minimal operations to move the operation @@ -281,7 +306,7 @@ Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG // Determine the ideal permutation of the slots in _exitLayout that are not operation outputs (and not to be // generated on the fly), s.t. shuffling the `stack + _operation.output` to _exitLayout is cheap. - Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly); + Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly, reachableStackDepth()); // Make sure the resulting previous slots do not overlap with any assignmed variables. if (auto const* assignment = std::get_if(&_operation.operation)) @@ -305,7 +330,7 @@ Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG stack.pop_back(); else if (auto offset = util::findOffset(stack | ranges::views::reverse | ranges::views::drop(1), stack.back())) { - if (*offset + 2 < 16) + if (*offset + 2 < reachableStackDepth()) stack.pop_back(); else break; @@ -323,7 +348,7 @@ Stack StackLayoutGenerator::propagateStackThroughBlock(Stack _exitStack, CFG::Ba for (auto&& [idx, operation]: _block.operations | ranges::views::enumerate | ranges::views::reverse) { Stack newStack = propagateStackThroughOperation(stack, operation, _aggressiveStackCompression); - if (!_aggressiveStackCompression && !findStackTooDeep(newStack, stack).empty()) + if (!_aggressiveStackCompression && !findStackTooDeep(newStack, stack, reachableStackDepth()).empty()) // If we had stack errors, run again with aggressive stack compression. return propagateStackThroughBlock(std::move(_exitStack), _block, true); stack = std::move(newStack); @@ -444,7 +469,8 @@ std::optional StackLayoutGenerator::getExitLayoutOrStageDependencies( // If the current iteration has already visited both jump targets, start from its entry layout. Stack stack = combineStack( m_layout.blockInfos.at(_conditionalJump.zero).entryLayout, - m_layout.blockInfos.at(_conditionalJump.nonZero).entryLayout + m_layout.blockInfos.at(_conditionalJump.nonZero).entryLayout, + reachableStackDepth() ); // Additionally, the jump condition has to be at the stack top at exit. stack.emplace_back(_conditionalJump.condition); @@ -464,7 +490,9 @@ std::optional StackLayoutGenerator::getExitLayoutOrStageDependencies( Stack stack = _functionReturn.info->returnVariables | ranges::views::transform([](auto const& _varSlot){ return StackSlot{_varSlot}; }) | ranges::to; - stack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); + + if (simulateFunctionsWithJumps()) + stack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); return stack; }, [&](CFG::BasicBlock::Terminated const&) -> std::optional @@ -545,7 +573,7 @@ void StackLayoutGenerator::stitchConditionalJumps(CFG::BasicBlock const& _block) }); } -Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _stack2) +Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _stack2, size_t _reachableStackDepth) { // TODO: it would be nicer to replace this by a constructive algorithm. // Currently it uses a reduced version of the Heap Algorithm to partly brute-force, which seems @@ -563,9 +591,9 @@ Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _sta Stack stack2Tail = _stack2 | ranges::views::drop(commonPrefix.size()) | ranges::to; if (stack1Tail.empty()) - return commonPrefix + compressStack(stack2Tail); + return commonPrefix + compressStack(stack2Tail, _reachableStackDepth); if (stack2Tail.empty()) - return commonPrefix + compressStack(stack1Tail); + return commonPrefix + compressStack(stack1Tail, _reachableStackDepth); Stack candidate; for (auto slot: stack1Tail) @@ -574,25 +602,25 @@ Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _sta for (auto slot: stack2Tail) if (!util::contains(candidate, slot)) candidate.emplace_back(slot); - cxx20::erase_if(candidate, [](StackSlot const& slot) { + std::erase_if(candidate, [](StackSlot const& slot) { return std::holds_alternative(slot) || std::holds_alternative(slot); }); auto evaluate = [&](Stack const& _candidate) -> size_t { size_t numOps = 0; Stack testStack = _candidate; - auto swap = [&](unsigned _swapDepth) { ++numOps; if (_swapDepth > 16) numOps += 1000; }; + auto swap = [&](unsigned _swapDepth) { ++numOps; if (_swapDepth > _reachableStackDepth) numOps += 1000; }; auto dupOrPush = [&](StackSlot const& _slot) { if (canBeFreelyGenerated(_slot)) return; auto depth = util::findOffset(ranges::concat_view(commonPrefix, testStack) | ranges::views::reverse, _slot); - if (depth && *depth >= 16) + if (depth && *depth >= _reachableStackDepth) numOps += 1000; }; - createStackLayout(testStack, stack1Tail, swap, dupOrPush, [&](){}); + createStackLayout(testStack, stack1Tail, swap, dupOrPush, [&](){}, _reachableStackDepth); testStack = _candidate; - createStackLayout(testStack, stack2Tail, swap, dupOrPush, [&](){}); + createStackLayout(testStack, stack2Tail, swap, dupOrPush, [&](){}, _reachableStackDepth); return numOps; }; @@ -643,7 +671,7 @@ std::vector StackLayoutGenerator::reportStac { Stack& operationEntry = m_layout.operationEntryLayout.at(&operation); - stackTooDeepErrors += findStackTooDeep(currentStack, operationEntry); + stackTooDeepErrors += findStackTooDeep(currentStack, operationEntry, reachableStackDepth()); currentStack = operationEntry; for (size_t i = 0; i < operation.input.size(); i++) currentStack.pop_back(); @@ -657,7 +685,7 @@ std::vector StackLayoutGenerator::reportStac [&](CFG::BasicBlock::Jump const& _jump) { Stack const& targetLayout = m_layout.blockInfos.at(_jump.target).entryLayout; - stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout); + stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout, reachableStackDepth()); if (!_jump.backwards) _addChild(_jump.target); @@ -668,7 +696,7 @@ std::vector StackLayoutGenerator::reportStac m_layout.blockInfos.at(_conditionalJump.zero).entryLayout, m_layout.blockInfos.at(_conditionalJump.nonZero).entryLayout }) - stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout); + stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout, reachableStackDepth()); _addChild(_conditionalJump.zero); _addChild(_conditionalJump.nonZero); @@ -680,7 +708,7 @@ std::vector StackLayoutGenerator::reportStac return stackTooDeepErrors; } -Stack StackLayoutGenerator::compressStack(Stack _stack) +Stack StackLayoutGenerator::compressStack(Stack _stack, size_t _reachableStackDepth) { std::optional firstDupOffset; do @@ -698,7 +726,7 @@ Stack StackLayoutGenerator::compressStack(Stack _stack) break; } else if (auto dupDepth = util::findOffset(_stack | ranges::views::reverse | ranges::views::drop(depth + 1), slot)) - if (depth + *dupDepth <= 16) + if (depth + *dupDepth <= _reachableStackDepth) { firstDupOffset = _stack.size() - depth - 1; break; @@ -735,7 +763,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi _addChild(_conditionalJump.zero); _addChild(_conditionalJump.nonZero); }, - [&](CFG::BasicBlock::FunctionReturn const&) { yulAssert(false); }, + [&](CFG::BasicBlock::FunctionReturn const&) { yulAssert(!simulateFunctionsWithJumps()); }, [&](CFG::BasicBlock::Terminated const&) {}, }, _block->exit); }); @@ -745,21 +773,21 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi size_t opGas = 0; auto swap = [&](unsigned _swapDepth) { - if (_swapDepth > 16) + if (_swapDepth > reachableStackDepth()) opGas += 1000; else - opGas += evmasm::GasMeter::runGas(evmasm::swapInstruction(_swapDepth), langutil::EVMVersion()); + opGas += evmasm::GasMeter::swapGas(_swapDepth, m_evmDialect.evmVersion()); }; auto dupOrPush = [&](StackSlot const& _slot) { if (canBeFreelyGenerated(_slot)) - opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32), langutil::EVMVersion()); + opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32), m_evmDialect.evmVersion()); else { if (auto depth = util::findOffset(_source | ranges::views::reverse, _slot)) { - if (*depth < 16) - opGas += evmasm::GasMeter::runGas(evmasm::dupInstruction(static_cast(*depth + 1)), langutil::EVMVersion()); + if (*depth < reachableStackDepth()) + opGas += evmasm::GasMeter::dupGas(*depth + 1, m_evmDialect.evmVersion()); else opGas += 1000; } @@ -771,12 +799,12 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi yulAssert(util::contains(m_currentFunctionInfo->returnVariables, std::get(_slot))); // Strictly speaking the cost of the PUSH0 depends on the targeted EVM version, but the difference // will not matter here. - opGas += evmasm::GasMeter::pushGas(u256(0), langutil::EVMVersion()); + opGas += evmasm::GasMeter::pushGas(u256(0), m_evmDialect.evmVersion()); } } }; - auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP,langutil::EVMVersion()); }; - createStackLayout(_source, _target, swap, dupOrPush, pop); + auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP, m_evmDialect.evmVersion()); }; + createStackLayout(_source, _target, swap, dupOrPush, pop, reachableStackDepth()); return opGas; }; /// @returns the number of junk slots to be prepended to @a _targetLayout for an optimal transition from diff --git a/libyul/backends/evm/StackLayoutGenerator.h b/libyul/backends/evm/StackLayoutGenerator.h index fc846a9deced..bf1b1917ba33 100644 --- a/libyul/backends/evm/StackLayoutGenerator.h +++ b/libyul/backends/evm/StackLayoutGenerator.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include @@ -55,18 +56,29 @@ class StackLayoutGenerator std::vector variableChoices; }; - static StackLayout run(CFG const& _cfg); + static StackLayout run(CFG const& _cfg, EVMDialect const& _evmDialect); /// @returns a map from function names to the stack too deep errors occurring in that function. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// The empty string is mapped to the stack too deep errors of the main entry point. - static std::map> reportStackTooDeep(CFG const& _cfg); + static std::map> reportStackTooDeep( + CFG const& _cfg, + EVMDialect const& _evmDialect + ); /// @returns all stack too deep errors in the function named @a _functionName. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// If @a _functionName is empty, the stack too deep errors of the main entry point are reported instead. - static std::vector reportStackTooDeep(CFG const& _cfg, YulName _functionName); + static std::vector reportStackTooDeep( + CFG const& _cfg, + YulName _functionName, + EVMDialect const& _evmDialect + ); private: - StackLayoutGenerator(StackLayout& _context, CFG::FunctionInfo const* _functionInfo); + StackLayoutGenerator( + StackLayout& _context, + CFG::FunctionInfo const* _functionInfo, + EVMDialect const& _evmDialect + ); /// @returns the optimal entry stack layout, s.t. @a _operation can be applied to it and /// the result can be transformed to @a _exitStack with minimal stack shuffling. @@ -100,7 +112,7 @@ class StackLayoutGenerator /// Calculates the ideal stack layout, s.t. both @a _stack1 and @a _stack2 can be achieved with minimal /// stack shuffling when starting from the returned layout. - static Stack combineStack(Stack const& _stack1, Stack const& _stack2); + static Stack combineStack(Stack const& _stack1, Stack const& _stack2, size_t _reachableStackDepth); /// Walks through the CFG and reports any stack too deep errors that would occur when generating code for it /// without countermeasures. @@ -109,13 +121,24 @@ class StackLayoutGenerator /// @returns a copy of @a _stack stripped of all duplicates and slots that can be freely generated. /// Attempts to create a layout that requires a minimal amount of operations to reconstruct the original /// stack @a _stack. - static Stack compressStack(Stack _stack); + static Stack compressStack(Stack _stack, size_t _reachableStackDepth); //// Fills in junk when entering branches that do not need a clean stack in case the result is cheaper. void fillInJunk(CFG::BasicBlock const& _block, CFG::FunctionInfo const* _functionInfo = nullptr); + /// True if it simulates functions with jumps. False otherwise. True for legacy bytecode. + bool simulateFunctionsWithJumps() const + { + return !m_evmDialect.eofVersion().has_value(); + } + size_t reachableStackDepth() const + { + return m_evmDialect.reachableStackDepth(); + } + StackLayout& m_layout; CFG::FunctionInfo const* m_currentFunctionInfo = nullptr; + EVMDialect const& m_evmDialect; }; } diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index 269c7adeedff..9e85651ad346 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -24,6 +24,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -153,6 +154,15 @@ Case ASTCopier::translate(Case const& _case) return Case{_case.debugData, translate(_case.value), translate(_case.body)}; } +FunctionName ASTCopier::translate(FunctionName const& _functionName) +{ + GenericVisitor visitor{ + [&](Identifier const& _identifier) -> FunctionName { return translate(_identifier); }, + [](BuiltinName const& _builtin) -> FunctionName { return _builtin; } + }; + return std::visit(visitor, _functionName); +} + Identifier ASTCopier::translate(Identifier const& _identifier) { return Identifier{_identifier.debugData, translateIdentifier(_identifier.name)}; diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index 04b1c96cd2e1..e1c3a16aa3ea 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -100,6 +100,7 @@ class ASTCopier: public ExpressionCopier, public StatementCopier Case translate(Case const& _case); virtual Identifier translate(Identifier const& _identifier); Literal translate(Literal const& _literal); + FunctionName translate(FunctionName const& _functionName); NameWithDebugData translate(NameWithDebugData const& _typedName); virtual void enterScope(Block const&) { } diff --git a/libyul/optimiser/BlockHasher.cpp b/libyul/optimiser/BlockHasher.cpp index 5470558ce93a..6e8e8ed62f57 100644 --- a/libyul/optimiser/BlockHasher.cpp +++ b/libyul/optimiser/BlockHasher.cpp @@ -23,6 +23,8 @@ #include #include +#include + using namespace solidity; using namespace solidity::yul; using namespace solidity::util; @@ -51,6 +53,24 @@ void ASTHasherBase::hashLiteral(solidity::yul::Literal const& _literal) hash8(_literal.value.unlimited()); } +void ASTHasherBase::hashFunctionCall(FunctionCall const& _funCall) +{ + hash64(compileTimeLiteralHash("FunctionCall")); + GenericVisitor visitor{ + [&](BuiltinName const& _builtin) + { + hash64(compileTimeLiteralHash("Builtin")); + hash64(_builtin.handle.id); + }, + [&](Identifier const& _identifier) + { + hash64(compileTimeLiteralHash("UserDefined")); + hash64(_identifier.name.hash()); + } + }; + std::visit(visitor, _funCall.functionName); +} + std::map BlockHasher::run(Block const& _block) { std::map result; @@ -85,9 +105,7 @@ void BlockHasher::operator()(Identifier const& _identifier) void BlockHasher::operator()(FunctionCall const& _funCall) { - hash64(compileTimeLiteralHash("FunctionCall")); - hash64(_funCall.functionName.name.hash()); - hash64(_funCall.arguments.size()); + hashFunctionCall(_funCall); ASTWalker::operator()(_funCall); } @@ -218,8 +236,6 @@ void ExpressionHasher::operator()(Identifier const& _identifier) void ExpressionHasher::operator()(FunctionCall const& _funCall) { - hash64(compileTimeLiteralHash("FunctionCall")); - hash64(_funCall.functionName.name.hash()); - hash64(_funCall.arguments.size()); + hashFunctionCall(_funCall); ASTWalker::operator()(_funCall); } diff --git a/libyul/optimiser/BlockHasher.h b/libyul/optimiser/BlockHasher.h index 427161b3c784..12c1c5e72b19 100644 --- a/libyul/optimiser/BlockHasher.h +++ b/libyul/optimiser/BlockHasher.h @@ -62,6 +62,7 @@ class ASTHasherBase: public HasherBase { protected: void hashLiteral(solidity::yul::Literal const& _literal); + void hashFunctionCall(FunctionCall const& _functionCall); }; /** diff --git a/libyul/optimiser/CallGraphGenerator.cpp b/libyul/optimiser/CallGraphGenerator.cpp index f457f55838d3..9b69835dc4f1 100644 --- a/libyul/optimiser/CallGraphGenerator.cpp +++ b/libyul/optimiser/CallGraphGenerator.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include using namespace solidity; @@ -35,11 +37,11 @@ namespace struct CallGraphCycleFinder { CallGraph const& callGraph; - std::set containedInCycle{}; - std::set visited{}; - std::vector currentPath{}; + std::set containedInCycle{}; + std::set visited{}; + std::vector currentPath{}; - void visit(YulName _function) + void visit(FunctionHandle const& _function) { if (visited.count(_function)) return; @@ -61,7 +63,7 @@ struct CallGraphCycleFinder }; } -std::set CallGraph::recursiveFunctions() const +std::set CallGraph::recursiveFunctions() const { CallGraphCycleFinder cycleFinder{*this}; // Visiting the root only is not enough, since there may be disconnected recursive functions. @@ -80,8 +82,12 @@ CallGraph CallGraphGenerator::callGraph(Block const& _ast) void CallGraphGenerator::operator()(FunctionCall const& _functionCall) { auto& functionCalls = m_callGraph.functionCalls[m_currentFunction]; - if (!util::contains(functionCalls, _functionCall.functionName.name)) - functionCalls.emplace_back(_functionCall.functionName.name); + FunctionHandle identifier = std::visit(GenericVisitor{ + [](BuiltinName const& _builtin) -> FunctionHandle { return _builtin.handle; }, + [](Identifier const& _identifier) -> FunctionHandle { return _identifier.name; }, + }, _functionCall.functionName); + if (!util::contains(functionCalls, identifier)) + functionCalls.emplace_back(identifier); ASTWalker::operator()(_functionCall); } diff --git a/libyul/optimiser/CallGraphGenerator.h b/libyul/optimiser/CallGraphGenerator.h index 23e9a2511588..722cbba4a796 100644 --- a/libyul/optimiser/CallGraphGenerator.h +++ b/libyul/optimiser/CallGraphGenerator.h @@ -22,9 +22,9 @@ #pragma once #include +#include #include -#include #include namespace solidity::yul @@ -32,12 +32,13 @@ namespace solidity::yul struct CallGraph { - std::map> functionCalls; + /// Map function definition name -> function name + std::map> functionCalls; std::set functionsWithLoops; /// @returns the set of functions contained in cycles in the call graph, i.e. /// functions that are part of a (mutual) recursion. /// Note that this does not include functions that merely call recursive functions. - std::set recursiveFunctions() const; + std::set recursiveFunctions() const; }; /** diff --git a/libyul/optimiser/CircularReferencesPruner.cpp b/libyul/optimiser/CircularReferencesPruner.cpp index a34f3f4e2aa3..d238f8da2148 100644 --- a/libyul/optimiser/CircularReferencesPruner.cpp +++ b/libyul/optimiser/CircularReferencesPruner.cpp @@ -57,7 +57,7 @@ std::set CircularReferencesPruner::functionsCalledFromOutermostContext( [&_callGraph](YulName _function, auto&& _addChild) { if (_callGraph.functionCalls.count(_function)) for (auto const& callee: _callGraph.functionCalls.at(_function)) - if (_callGraph.functionCalls.count(callee)) - _addChild(callee); + if (std::holds_alternative(callee) && _callGraph.functionCalls.count(std::get(callee))) + _addChild(std::get(callee)); }).visited; } diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index 073d621cc2cf..87a14d259070 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -46,7 +46,7 @@ void CommonSubexpressionEliminator::run(OptimiserStepContext& _context, Block& _ CommonSubexpressionEliminator::CommonSubexpressionEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ): DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore, std::move(_functionSideEffects)) { @@ -72,7 +72,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e) { FunctionCall& funCall = std::get(_e); - if (BuiltinFunction const* builtin = m_dialect.builtin(funCall.functionName.name)) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(funCall.functionName, m_dialect)) { for (size_t i = funCall.arguments.size(); i > 0; i--) // We should not modify function arguments that have to be literals diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index d7dc42596ca4..713c35f0229c 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -32,7 +32,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct SideEffects; /** @@ -53,7 +53,7 @@ class CommonSubexpressionEliminator: public DataFlowAnalyzer private: CommonSubexpressionEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ); protected: diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index c078885e8ba4..53afb5e77785 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -37,13 +37,13 @@ namespace ExpressionStatement makeDiscardCall( langutil::DebugData::ConstPtr const& _debugData, - BuiltinFunction const& _discardFunction, + BuiltinHandle const& _discardFunction, Expression&& _expression ) { return {_debugData, FunctionCall{ _debugData, - Identifier{_debugData, _discardFunction.name}, + BuiltinName{_debugData, _discardFunction}, {std::move(_expression)} }}; } @@ -136,12 +136,12 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) GenericVisitor visitor{ VisitorFallback{}, [&](If& _ifStmt) -> OptionalStatements { - if (_ifStmt.body.statements.empty() && m_dialect.discardFunction()) + if (_ifStmt.body.statements.empty() && m_dialect.discardFunctionHandle()) { OptionalStatements s = std::vector{}; s->emplace_back(makeDiscardCall( _ifStmt.debugData, - *m_dialect.discardFunction(), + *m_dialect.discardFunctionHandle(), std::move(*_ifStmt.condition) )); return s; @@ -177,14 +177,14 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt) const { yulAssert(_switchStmt.cases.empty(), "Expected no case!"); - BuiltinFunction const* discardFunction = - m_dialect.discardFunction(); - if (!discardFunction) + std::optional discardFunctionHandle = + m_dialect.discardFunctionHandle(); + if (!discardFunctionHandle) return {}; return make_vector(makeDiscardCall( debugDataOf(*_switchStmt.expression), - *discardFunction, + *discardFunctionHandle, std::move(*_switchStmt.expression) )); } @@ -197,13 +197,14 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch langutil::DebugData::ConstPtr debugData = debugDataOf(*_switchStmt.expression); if (switchCase.value) { - if (!m_dialect.equalityFunction()) + if (!m_dialect.equalityFunctionHandle()) return {}; + BuiltinName const builtinName{debugData, *m_dialect.equalityFunctionHandle()}; return make_vector(If{ std::move(_switchStmt.debugData), std::make_unique(FunctionCall{ debugData, - Identifier{debugData, m_dialect.equalityFunction()->name}, + builtinName, {std::move(*switchCase.value), std::move(*_switchStmt.expression)} }), std::move(switchCase.body) @@ -211,13 +212,13 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch } else { - if (!m_dialect.discardFunction()) + if (!m_dialect.discardFunctionHandle()) return {}; return make_vector( makeDiscardCall( debugData, - *m_dialect.discardFunction(), + *m_dialect.discardFunctionHandle(), std::move(*_switchStmt.expression) ), std::move(switchCase.body) diff --git a/libyul/optimiser/ControlFlowSimplifier.h b/libyul/optimiser/ControlFlowSimplifier.h index 86ebf296c290..829138471752 100644 --- a/libyul/optimiser/ControlFlowSimplifier.h +++ b/libyul/optimiser/ControlFlowSimplifier.h @@ -22,7 +22,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index bf8952355d1f..2407781354d0 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -32,7 +32,6 @@ #include #include -#include #include @@ -45,23 +44,19 @@ using namespace solidity::yul; DataFlowAnalyzer::DataFlowAnalyzer( Dialect const& _dialect, MemoryAndStorage _analyzeStores, - std::map _functionSideEffects + std::map _functionSideEffects ): m_dialect(_dialect), m_functionSideEffects(std::move(_functionSideEffects)), - m_knowledgeBase([this](YulName _var) { return variableValue(_var); }), + m_knowledgeBase([this](YulName _var) { return variableValue(_var); }, _dialect), m_analyzeStores(_analyzeStores == MemoryAndStorage::Analyze) { if (m_analyzeStores) { - if (auto const* builtin = _dialect.memoryStoreFunction()) - m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.memoryLoadFunction()) - m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.storageStoreFunction()) - m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; - if (auto const* builtin = _dialect.storageLoadFunction()) - m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; + m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = _dialect.memoryStoreFunctionHandle(); + m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = _dialect.memoryLoadFunctionHandle(); + m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = _dialect.storageStoreFunctionHandle(); + m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = _dialect.storageLoadFunctionHandle(); } } @@ -72,7 +67,7 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement) if (auto vars = isSimpleStore(StoreLoadLocation::Storage, _statement)) { ASTModifier::operator()(_statement); - cxx20::erase_if(m_state.environment.storage, mapTuple([&](auto&& key, auto&& value) { + std::erase_if(m_state.environment.storage, mapTuple([&](auto&& key, auto&& value) { return !m_knowledgeBase.knownToBeDifferent(vars->first, key) && vars->second != value; @@ -83,7 +78,7 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement) else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, _statement)) { ASTModifier::operator()(_statement); - cxx20::erase_if(m_state.environment.memory, mapTuple([&](auto&& key, auto&& /* value */) { + std::erase_if(m_state.environment.memory, mapTuple([&](auto&& key, auto&& /* value */) { return !m_knowledgeBase.knownToBeDifferentByAtLeast32(vars->first, key); })); // TODO erase keccak knowledge, but in a more clever way @@ -268,22 +263,23 @@ void DataFlowAnalyzer::handleAssignment(std::set const& _variables, Exp } auto const& referencedVariables = movableChecker.referencedVariables(); + std::vector const referencedVariablesSorted(referencedVariables.begin(), referencedVariables.end()); for (auto const& name: _variables) { - m_state.references[name] = referencedVariables; + m_state.sortedReferences[name] = referencedVariablesSorted; if (!_isDeclaration) { // assignment to slot denoted by "name" m_state.environment.storage.erase(name); // assignment to slot contents denoted by "name" - cxx20::erase_if(m_state.environment.storage, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; })); + std::erase_if(m_state.environment.storage, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; })); // assignment to slot denoted by "name" m_state.environment.memory.erase(name); // assignment to slot contents denoted by "name" - cxx20::erase_if(m_state.environment.keccak, [&name](auto&& _item) { + std::erase_if(m_state.environment.keccak, [&name](auto&& _item) { return _item.first.first == name || _item.first.second == name || _item.second == name; }); - cxx20::erase_if(m_state.environment.memory, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; })); + std::erase_if(m_state.environment.memory, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; })); } } @@ -315,12 +311,12 @@ void DataFlowAnalyzer::popScope() for (auto const& name: m_variableScopes.back().variables) { m_state.value.erase(name); - m_state.references.erase(name); + m_state.sortedReferences.erase(name); } m_variableScopes.pop_back(); } -void DataFlowAnalyzer::clearValues(std::set _variables) +void DataFlowAnalyzer::clearValues(std::set const& _variablesToClear) { // All variables that reference variables to be cleared also have to be // cleared, but not recursively, since only the value of the original @@ -338,30 +334,32 @@ void DataFlowAnalyzer::clearValues(std::set _variables) // First clear storage knowledge, because we do not have to clear // storage knowledge of variables whose expression has changed, // since the value is still unchanged. - auto eraseCondition = mapTuple([&_variables](auto&& key, auto&& value) { - return _variables.count(key) || _variables.count(value); + auto eraseCondition = mapTuple([&_variablesToClear](auto&& key, auto&& value) { + return _variablesToClear.count(key) || _variablesToClear.count(value); }); - cxx20::erase_if(m_state.environment.storage, eraseCondition); - cxx20::erase_if(m_state.environment.memory, eraseCondition); - cxx20::erase_if(m_state.environment.keccak, [&_variables](auto&& _item) { + std::erase_if(m_state.environment.storage, eraseCondition); + std::erase_if(m_state.environment.memory, eraseCondition); + std::erase_if(m_state.environment.keccak, [&_variablesToClear](auto&& _item) { return - _variables.count(_item.first.first) || - _variables.count(_item.first.second) || - _variables.count(_item.second); + _variablesToClear.count(_item.first.first) || + _variablesToClear.count(_item.first.second) || + _variablesToClear.count(_item.second); }); // Also clear variables that reference variables to be cleared. - std::set referencingVariables; - for (auto const& variableToClear: _variables) - for (auto const& [ref, names]: m_state.references) - if (names.count(variableToClear)) - referencingVariables.emplace(ref); + std::set referencingVariablesToClear; + std::vector const sortedVariablesToClear(_variablesToClear.begin(), _variablesToClear.end()); + for (auto const& [referencingVariable, referencedVariables]: m_state.sortedReferences) + // instead of checking each variable in `referencedVariables`, we check if there is any intersection making use of the + // sortedness of the vectors, which can increase performance by up to 50% in pathological cases + if (hasNonemptyIntersectionSorted(referencedVariables, sortedVariablesToClear)) + referencingVariablesToClear.emplace(referencingVariable); // Clear the value and update the reference relation. - for (auto const& name: _variables + referencingVariables) + for (auto const& name: _variablesToClear + referencingVariablesToClear) { m_state.value.erase(name); - m_state.references.erase(name); + m_state.sortedReferences.erase(name); } } @@ -424,7 +422,10 @@ std::optional> DataFlowAnalyzer::isSimpleStore( ) const { if (FunctionCall const* funCall = std::get_if(&_statement.expression)) - if (funCall->functionName.name == m_storeFunctionName[static_cast(_location)]) + if ( + std::holds_alternative(funCall->functionName) && + std::get(funCall->functionName).handle == m_storeFunctionName[static_cast(_location)] + ) if (Identifier const* key = std::get_if(&funCall->arguments.front())) if (Identifier const* value = std::get_if(&funCall->arguments.back())) return std::make_pair(key->name, value->name); @@ -437,7 +438,10 @@ std::optional DataFlowAnalyzer::isSimpleLoad( ) const { if (FunctionCall const* funCall = std::get_if(&_expression)) - if (funCall->functionName.name == m_loadFunctionName[static_cast(_location)]) + if ( + std::holds_alternative(funCall->functionName) && + std::get(funCall->functionName).handle == m_loadFunctionName[static_cast(_location)] + ) if (Identifier const* key = std::get_if(&funCall->arguments.front())) return key->name; return {}; @@ -446,7 +450,10 @@ std::optional DataFlowAnalyzer::isSimpleLoad( std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const { if (FunctionCall const* funCall = std::get_if(&_expression)) - if (funCall->functionName.name == m_dialect.hashFunction()) + if ( + std::holds_alternative(funCall->functionName) && + std::get(funCall->functionName).handle == m_dialect.hashFunctionHandle() + ) if (Identifier const* start = std::get_if(&funCall->arguments.at(0))) if (Identifier const* length = std::get_if(&funCall->arguments.at(1))) return std::make_pair(start->name, length->name); @@ -459,7 +466,7 @@ void DataFlowAnalyzer::joinKnowledge(Environment const& _olderEnvironment) return; joinKnowledgeHelper(m_state.environment.storage, _olderEnvironment.storage); joinKnowledgeHelper(m_state.environment.memory, _olderEnvironment.memory); - cxx20::erase_if(m_state.environment.keccak, mapTuple([&_olderEnvironment](auto&& key, auto&& currentValue) { + std::erase_if(m_state.environment.keccak, mapTuple([&_olderEnvironment](auto&& key, auto&& currentValue) { YulName const* oldValue = valueOrNullptr(_olderEnvironment.keccak, key); return !oldValue || *oldValue != currentValue; })); @@ -474,7 +481,7 @@ void DataFlowAnalyzer::joinKnowledgeHelper( // This also works for memory because _older is an "older version" // of m_state.environment.memory and thus any overlapping write would have cleared the keys // that are not known to be different inside m_state.environment.memory already. - cxx20::erase_if(_this, mapTuple([&_older](auto&& key, auto&& currentValue){ + std::erase_if(_this, mapTuple([&_older](auto&& key, auto&& currentValue){ YulName const* oldValue = valueOrNullptr(_older, key); return !oldValue || *oldValue != currentValue; })); diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 5a4b199caefd..7b731a4eb877 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -37,7 +37,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct SideEffects; class KnowledgeBase; @@ -89,7 +89,7 @@ class DataFlowAnalyzer: public ASTModifier explicit DataFlowAnalyzer( Dialect const& _dialect, MemoryAndStorage _analyzeStores, - std::map _functionSideEffects = {} + std::map _functionSideEffects = {} ); using ASTModifier::operator(); @@ -104,7 +104,7 @@ class DataFlowAnalyzer: public ASTModifier /// @returns the current value of the given variable, if known - always movable. AssignedValue const* variableValue(YulName _variable) const { return util::valueOrNullptr(m_state.value, _variable); } - std::set const* references(YulName _variable) const { return util::valueOrNullptr(m_state.references, _variable); } + std::vector const* sortedReferences(YulName _variable) const { return util::valueOrNullptr(m_state.sortedReferences, _variable); } std::map const& allValues() const { return m_state.value; } std::optional storageValue(YulName _key) const; std::optional memoryValue(YulName _key) const; @@ -122,7 +122,7 @@ class DataFlowAnalyzer: public ASTModifier /// Clears information about the values assigned to the given variables, /// for example at points where control flow is merged. - void clearValues(std::set _names); + void clearValues(std::set const& _variablesToClear); virtual void assignValue(YulName _variable, Expression const* _value); @@ -165,7 +165,7 @@ class DataFlowAnalyzer: public ASTModifier Dialect const& m_dialect; /// Side-effects of user-defined functions. Worst-case side-effects are assumed /// if this is not provided or the function is not found. - std::map m_functionSideEffects; + std::map m_functionSideEffects; private: struct Environment @@ -180,7 +180,8 @@ class DataFlowAnalyzer: public ASTModifier /// Current values of variables, always movable. std::map value; /// m_references[a].contains(b) <=> the current expression assigned to a references b - std::unordered_map> references; + /// The mapped vectors _must always_ be sorted + std::unordered_map> sortedReferences; Environment environment; }; @@ -203,8 +204,8 @@ class DataFlowAnalyzer: public ASTModifier /// If true, analyzes memory and storage content via mload/mstore and sload/sstore. bool m_analyzeStores = true; - YulName m_storeFunctionName[static_cast(StoreLoadLocation::Last) + 1]; - YulName m_loadFunctionName[static_cast(StoreLoadLocation::Last) + 1]; + std::optional m_storeFunctionName[static_cast(StoreLoadLocation::Last) + 1]; + std::optional m_loadFunctionName[static_cast(StoreLoadLocation::Last) + 1]; /// Current nesting depth of loops. size_t m_loopDepth{0}; diff --git a/libyul/optimiser/DeadCodeEliminator.h b/libyul/optimiser/DeadCodeEliminator.h index f252536c599e..701af3ad1561 100644 --- a/libyul/optimiser/DeadCodeEliminator.h +++ b/libyul/optimiser/DeadCodeEliminator.h @@ -30,7 +30,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index 11325936c7c6..55219f6eae37 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -32,7 +32,7 @@ using namespace solidity::util; YulName Disambiguator::translateIdentifier(YulName _originalName) { - if (m_dialect.builtin(_originalName) || m_externallyUsedIdentifiers.count(_originalName)) + if (m_dialect.findBuiltin(_originalName.str()) || m_externallyUsedIdentifiers.count(_originalName)) return _originalName; assertThrow(!m_scopes.empty() && m_scopes.back(), OptimizerException, ""); diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 08d8d158f699..36d178b086c1 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Creates a copy of a Yul AST replacing all identifiers by unique names. diff --git a/libyul/optimiser/EqualStoreEliminator.h b/libyul/optimiser/EqualStoreEliminator.h index a0b54c590ff5..87f8cae161a6 100644 --- a/libyul/optimiser/EqualStoreEliminator.h +++ b/libyul/optimiser/EqualStoreEliminator.h @@ -45,7 +45,7 @@ class EqualStoreEliminator: public DataFlowAnalyzer private: EqualStoreEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ): DataFlowAnalyzer(_dialect, MemoryAndStorage::Analyze, std::move(_functionSideEffects)) {} diff --git a/libyul/optimiser/EquivalentFunctionCombiner.cpp b/libyul/optimiser/EquivalentFunctionCombiner.cpp index 10d15126e645..bbbf039d56ed 100644 --- a/libyul/optimiser/EquivalentFunctionCombiner.cpp +++ b/libyul/optimiser/EquivalentFunctionCombiner.cpp @@ -33,8 +33,13 @@ void EquivalentFunctionCombiner::run(OptimiserStepContext&, Block& _ast) void EquivalentFunctionCombiner::operator()(FunctionCall& _funCall) { - auto it = m_duplicates.find(_funCall.functionName.name); - if (it != m_duplicates.end()) - _funCall.functionName.name = it->second->name; + if (!isBuiltinFunctionCall(_funCall)) + { + auto* identifier = std::get_if(&_funCall.functionName); + yulAssert(identifier); + auto it = m_duplicates.find(identifier->name); + if (it != m_duplicates.end()) + identifier->name = it->second->name; + } ASTModifier::operator()(_funCall); } diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index ab4bbcfa43a8..0d59dab2d2e7 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -29,6 +29,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -52,9 +53,10 @@ void ExpressionInliner::visit(Expression& _expression) if (std::holds_alternative(_expression)) { FunctionCall& funCall = std::get(_expression); - if (!m_inlinableFunctions.count(funCall.functionName.name)) + YulString const functionName{resolveFunctionName(funCall.functionName, m_dialect)}; + if (!m_inlinableFunctions.count(functionName)) return; - FunctionDefinition const& fun = *m_inlinableFunctions.at(funCall.functionName.name); + FunctionDefinition const& fun = *m_inlinableFunctions.at(functionName); std::map substitutions; for (size_t i = 0; i < funCall.arguments.size(); i++) diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index 08ff08648428..f8cf70d56e13 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 598d2e90037d..4aa7be1bb556 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -46,10 +47,14 @@ void ExpressionSimplifier::visit(Expression& _expression) m_dialect, [this](YulName _var) { return variableValue(_var); } )) - _expression = match->action().toExpression(debugDataOf(_expression), evmVersionFromDialect(m_dialect)); + { + auto const* evmDialect = dynamic_cast(&m_dialect); + yulAssert(evmDialect); + _expression = match->action().toExpression(debugDataOf(_expression), *evmDialect); + } if (auto* functionCall = std::get_if(&_expression)) - if (std::optional instruction = toEVMInstruction(m_dialect, functionCall->functionName.name)) + if (std::optional instruction = toEVMInstruction(m_dialect, functionCall->functionName)) for (auto op: evmasm::SemanticInformation::readWriteOperations(*instruction)) if (op.startParameter && op.lengthParameter) { diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index 662c8c389936..b004c9b5211a 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -27,7 +27,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 9f9bf958f129..649bd85834d2 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -26,6 +26,7 @@ #include #include +#include #include @@ -34,6 +35,13 @@ using namespace solidity::yul; using namespace solidity::util; using namespace solidity::langutil; +ExpressionSplitter::ExpressionSplitter(Dialect const& _dialect, NameDispenser& _nameDispenser): + m_dialect(_dialect), + m_nameDispenser(_nameDispenser) +{} + +ExpressionSplitter::~ExpressionSplitter() = default; + void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast) { ExpressionSplitter{_context.dialect, _context.dispenser}(_ast); @@ -41,7 +49,7 @@ void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast) void ExpressionSplitter::operator()(FunctionCall& _funCall) { - BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name); + BuiltinFunction const* builtin = resolveBuiltinFunction(_funCall.functionName, m_dialect); for (size_t i = _funCall.arguments.size(); i > 0; i--) if (!builtin || !builtin->literalArgument(i - 1)) diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index 0b223e9859b2..739916317765 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** @@ -68,13 +68,11 @@ class ExpressionSplitter: public ASTModifier void operator()(Block& _block) override; private: - explicit ExpressionSplitter( + ExpressionSplitter( Dialect const& _dialect, NameDispenser& _nameDispenser - ): - m_dialect(_dialect), - m_nameDispenser(_nameDispenser) - { } + ); + ~ExpressionSplitter() override; /// Replaces the expression by a variable if it is a function call or functional /// instruction. The declaration of the variable is appended to m_statementsToPrefix. diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index d0839e765ee8..b3c78129aa47 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -32,8 +32,9 @@ void ForLoopConditionIntoBody::run(OptimiserStepContext& _context, Block& _ast) void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) { + std::optional booleanNegationFunctionHandle = m_dialect.booleanNegationFunctionHandle(); if ( - m_dialect.booleanNegationFunction() && + booleanNegationFunctionHandle && !std::holds_alternative(*_forLoop.condition) && !std::holds_alternative(*_forLoop.condition) ) @@ -47,7 +48,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) std::make_unique( FunctionCall { debugData, - {debugData, m_dialect.booleanNegationFunction()->name}, + BuiltinName{debugData, *booleanNegationFunctionHandle}, util::make_vector(std::move(*_forLoop.condition)) } ), diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index afd005b719d5..111f26fec5f3 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -36,7 +36,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) ASTModifier::operator()(_forLoop); if ( - !m_dialect.booleanNegationFunction() || + !m_dialect.booleanNegationFunctionHandle() || !std::holds_alternative(*_forLoop.condition) || std::get(*_forLoop.condition).value.value() == 0 || _forLoop.body.statements.empty() || @@ -53,18 +53,21 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable()) return; - YulName iszero = m_dialect.booleanNegationFunction()->name; + std::optional iszero = m_dialect.booleanNegationFunctionHandle(); + yulAssert(iszero.has_value()); + auto const& isZeroHandle = *iszero; langutil::DebugData::ConstPtr debugData = debugDataOf(*firstStatement.condition); if ( std::holds_alternative(*firstStatement.condition) && - std::get(*firstStatement.condition).functionName.name == iszero + std::holds_alternative(std::get(*firstStatement.condition).functionName) && + std::get(std::get(*firstStatement.condition).functionName).handle == isZeroHandle ) _forLoop.condition = std::make_unique(std::move(std::get(*firstStatement.condition).arguments.front())); else _forLoop.condition = std::make_unique(FunctionCall{ debugData, - Identifier{debugData, iszero}, + BuiltinName{debugData, isZeroHandle}, util::make_vector( std::move(*firstStatement.condition) ) diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index c6387f808e0e..894ada60962e 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -67,7 +67,7 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& // Store size of global statements. m_functionSizes[YulName{}] = CodeSize::codeSize(_ast); - std::map references = ReferencesCounter::countReferences(m_ast); + std::map references = ReferencesCounter::countReferences(m_ast); for (auto& statement: m_ast.statements) { if (!std::holds_alternative(statement)) @@ -83,10 +83,13 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& } // Check for memory guard. - std::vector memoryGuardCalls = findFunctionCalls(_ast, "memoryguard"_yulname); - // We will perform less aggressive inlining, if no ``memoryguard`` call is found. - if (!memoryGuardCalls.empty()) - m_hasMemoryGuard = true; + if (auto const memoryGuard = m_dialect.findBuiltin("memoryguard")) + { + std::vector memoryGuardCalls = findFunctionCalls(_ast, *memoryGuard); + // We will perform less aggressive inlining, if no ``memoryguard`` call is found. + if (!memoryGuardCalls.empty()) + m_hasMemoryGuard = true; + } } void FullInliner::run(Pass _pass) @@ -101,7 +104,7 @@ void FullInliner::run(Pass _pass) // function name) order. // We use stable_sort below to keep the inlining order of two functions // with the same depth. - std::map depths = callDepths(); + std::map depths = callDepths(); std::vector functions; for (auto& statement: m_ast.statements) if (std::holds_alternative(statement)) @@ -123,7 +126,7 @@ void FullInliner::run(Pass _pass) handleBlock({}, std::get(statement)); } -std::map FullInliner::callDepths() const +std::map FullInliner::callDepths() const { CallGraph cg = CallGraphGenerator::callGraph(m_ast); cg.functionCalls.erase(""_yulname); @@ -131,17 +134,17 @@ std::map FullInliner::callDepths() const // Remove calls to builtin functions. for (auto& call: cg.functionCalls) for (auto it = call.second.begin(); it != call.second.end();) - if (m_dialect.builtin(*it)) + if (std::holds_alternative(*it)) it = call.second.erase(it); else ++it; - std::map depths; + std::map depths; size_t currentDepth = 0; while (true) { - std::vector removed; + std::vector removed; for (auto it = cg.functionCalls.begin(); it != cg.functionCalls.end();) { auto const& [fun, callees] = *it; @@ -156,7 +159,7 @@ std::map FullInliner::callDepths() const } for (auto& call: cg.functionCalls) - for (YulName toBeRemoved: removed) + for (FunctionHandle toBeRemoved: removed) ranges::actions::remove(call.second, toBeRemoved); currentDepth++; @@ -174,15 +177,19 @@ std::map FullInliner::callDepths() const bool FullInliner::shallInline(FunctionCall const& _funCall, YulName _callSite) { + if (isBuiltinFunctionCall(_funCall)) + return false; + yulAssert(std::holds_alternative(_funCall.functionName)); + auto const& functionName = std::get(_funCall.functionName).name; // No recursive inlining - if (_funCall.functionName.name == _callSite) + if (functionName == _callSite) return false; - FunctionDefinition* calledFunction = function(_funCall.functionName.name); + FunctionDefinition* calledFunction = function(functionName); if (!calledFunction) return false; - if (m_noInlineFunctions.count(_funCall.functionName.name) || recursive(*calledFunction)) + if (m_noInlineFunctions.count(functionName) || recursive(*calledFunction)) return false; // No inlining of calls where argument expressions may have side-effects. @@ -251,7 +258,7 @@ void FullInliner::handleBlock(YulName _currentFunctionName, Block& _block) bool FullInliner::recursive(FunctionDefinition const& _fun) const { - std::map references = ReferencesCounter::countReferences(_fun); + std::map references = ReferencesCounter::countReferences(_fun); return references[_fun.name] > 0; } @@ -291,7 +298,8 @@ std::vector InlineModifier::performInline(Statement& _statement, Func std::vector newStatements; std::map variableReplacements; - FunctionDefinition* function = m_driver.function(_funCall.functionName.name); + yulAssert(std::holds_alternative(_funCall.functionName)); + FunctionDefinition* function = m_driver.function(std::get(_funCall.functionName).name); assertThrow(!!function, OptimizerException, "Attempt to inline invalid function."); m_driver.tentativelyUpdateCodeSize(function->name, m_currentFunction); @@ -363,8 +371,5 @@ Statement BodyCopier::operator()(FunctionDefinition const&) YulName BodyCopier::translateIdentifier(YulName _name) { - if (m_variableReplacements.count(_name)) - return m_variableReplacements.at(_name); - else - return _name; + return util::valueOrDefault(m_variableReplacements, _name, _name); } diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index e939070238e5..4620194a4e51 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -98,7 +98,7 @@ class FullInliner: public ASTModifier /// @returns a map containing the maximum depths of a call chain starting at each /// function. For recursive functions, the value is one larger than for all others. - std::map callDepths() const; + std::map callDepths() const; void updateCodeSize(FunctionDefinition const& _fun); void handleBlock(YulName _currentFunctionName, Block& _block); @@ -114,7 +114,7 @@ class FullInliner: public ASTModifier /// True, if the code contains a ``memoryguard`` and we can expect to be able to move variables to memory later. bool m_hasMemoryGuard = false; /// Set of recursive functions. - std::set m_recursiveFunctions; + std::set m_recursiveFunctions; /// Names of functions to always inline. std::set m_singleUse; /// Variables that are constants (used for inlining heuristic) diff --git a/libyul/optimiser/FunctionCallFinder.cpp b/libyul/optimiser/FunctionCallFinder.cpp index aaf8b9f68232..9f5c75b43749 100644 --- a/libyul/optimiser/FunctionCallFinder.cpp +++ b/libyul/optimiser/FunctionCallFinder.cpp @@ -19,6 +19,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -30,32 +31,34 @@ class MaybeConstFunctionCallFinder: Base { public: using MaybeConstBlock = std::conditional_t, Block const, Block>; - static std::vector run(MaybeConstBlock& _block, YulName const _functionName) + static std::vector run(MaybeConstBlock& _block, FunctionHandle const& _functionHandle) { - MaybeConstFunctionCallFinder functionCallFinder(_functionName); + MaybeConstFunctionCallFinder functionCallFinder(_functionHandle); functionCallFinder(_block); return functionCallFinder.m_calls; } private: - explicit MaybeConstFunctionCallFinder(YulName const _functionName): m_functionName(_functionName), m_calls() {} + explicit MaybeConstFunctionCallFinder(FunctionHandle const& _functionHandle): + m_functionHandle(_functionHandle), m_calls() {} + using Base::operator(); void operator()(ResultType& _functionCall) override { Base::operator()(_functionCall); - if (_functionCall.functionName.name == m_functionName) + if (functionNameToHandle(_functionCall.functionName) == m_functionHandle) m_calls.emplace_back(&_functionCall); } - YulName m_functionName; + FunctionHandle const& m_functionHandle; std::vector m_calls; }; } -std::vector solidity::yul::findFunctionCalls(Block& _block, YulName _functionName) +std::vector yul::findFunctionCalls(Block& _block, FunctionHandle const& _functionHandle) { - return MaybeConstFunctionCallFinder::run(_block, _functionName); + return MaybeConstFunctionCallFinder::run(_block, _functionHandle); } -std::vector solidity::yul::findFunctionCalls(Block const& _block, YulName _functionName) +std::vector yul::findFunctionCalls(Block const& _block, FunctionHandle const& _functionHandle) { - return MaybeConstFunctionCallFinder::run(_block, _functionName); + return MaybeConstFunctionCallFinder::run(_block, _functionHandle); } diff --git a/libyul/optimiser/FunctionCallFinder.h b/libyul/optimiser/FunctionCallFinder.h index 41a19fe99fc7..560ecfc38bfa 100644 --- a/libyul/optimiser/FunctionCallFinder.h +++ b/libyul/optimiser/FunctionCallFinder.h @@ -20,8 +20,7 @@ #pragma once -#include -#include +#include #include @@ -33,13 +32,13 @@ namespace solidity::yul * * Prerequisite: Disambiguator */ -std::vector findFunctionCalls(Block& _block, YulName _functionName); +std::vector findFunctionCalls(Block& _block, FunctionHandle const& _functionHandle); /** * Finds all calls to a function of a given name using an ASTWalker. * * Prerequisite: Disambiguator */ -std::vector findFunctionCalls(Block const& _block, YulName _functionName); +std::vector findFunctionCalls(Block const& _block, FunctionHandle const& _functionHandle); } diff --git a/libyul/optimiser/FunctionHoister.cpp b/libyul/optimiser/FunctionHoister.cpp index 32df3b121a61..356056a99abd 100644 --- a/libyul/optimiser/FunctionHoister.cpp +++ b/libyul/optimiser/FunctionHoister.cpp @@ -30,6 +30,9 @@ using namespace solidity; using namespace solidity::yul; +FunctionHoister::FunctionHoister() = default; +FunctionHoister::~FunctionHoister() = default; + void FunctionHoister::operator()(Block& _block) { bool topLevel = m_isTopLevel; diff --git a/libyul/optimiser/FunctionHoister.h b/libyul/optimiser/FunctionHoister.h index 04d7f64e3d73..8242c9f4792f 100644 --- a/libyul/optimiser/FunctionHoister.h +++ b/libyul/optimiser/FunctionHoister.h @@ -46,7 +46,8 @@ class FunctionHoister: public ASTModifier void operator()(Block& _block) override; private: - FunctionHoister() = default; + FunctionHoister(); + ~FunctionHoister() override; bool m_isTopLevel = true; std::vector m_functions; diff --git a/libyul/optimiser/FunctionSpecializer.cpp b/libyul/optimiser/FunctionSpecializer.cpp index cb7cd4164b03..cbbf14e8f84a 100644 --- a/libyul/optimiser/FunctionSpecializer.cpp +++ b/libyul/optimiser/FunctionSpecializer.cpp @@ -55,21 +55,23 @@ void FunctionSpecializer::operator()(FunctionCall& _f) // TODO When backtracking is implemented, the restriction of recursive functions can be lifted. if ( - m_dialect.builtin(_f.functionName.name) || - m_recursiveFunctions.count(_f.functionName.name) + isBuiltinFunctionCall(_f) || + (std::holds_alternative(_f.functionName) && m_recursiveFunctions.count(std::get(_f.functionName).name)) ) return; + yulAssert(std::holds_alternative(_f.functionName)); + auto& identifier = std::get(_f.functionName); LiteralArguments arguments = specializableArguments(_f); if (ranges::any_of(arguments, [](auto& _a) { return _a.has_value(); })) { - YulName oldName = std::move(_f.functionName.name); + YulName oldName = std::move(identifier.name); auto newName = m_nameDispenser.newName(oldName); m_oldToNewMap[oldName].emplace_back(std::make_pair(newName, arguments)); - _f.functionName.name = newName; + identifier.name = newName; _f.arguments = util::filter( _f.arguments, applyMap(arguments, [](auto& _a) { return !_a; }) @@ -128,8 +130,7 @@ void FunctionSpecializer::run(OptimiserStepContext& _context, Block& _ast) { FunctionSpecializer f{ CallGraphGenerator::callGraph(_ast).recursiveFunctions(), - _context.dispenser, - _context.dialect + _context.dispenser }; f(_ast); diff --git a/libyul/optimiser/FunctionSpecializer.h b/libyul/optimiser/FunctionSpecializer.h index 784ec4311e0f..4df59b354c45 100644 --- a/libyul/optimiser/FunctionSpecializer.h +++ b/libyul/optimiser/FunctionSpecializer.h @@ -22,8 +22,7 @@ #include #include -#include -#include +#include #include #include @@ -67,13 +66,11 @@ class FunctionSpecializer: public ASTModifier private: explicit FunctionSpecializer( - std::set _recursiveFunctions, - NameDispenser& _nameDispenser, - Dialect const& _dialect + std::set _recursiveFunctions, + NameDispenser& _nameDispenser ): m_recursiveFunctions(std::move(_recursiveFunctions)), - m_nameDispenser(_nameDispenser), - m_dialect(_dialect) + m_nameDispenser(_nameDispenser) {} /// Returns a vector of Expressions, where the index `i` is an expression if the function's /// `i`-th argument can be specialized, nullopt otherwise. @@ -104,10 +101,9 @@ class FunctionSpecializer: public ASTModifier /// Note that at least one of the argument will have a literal value. std::map>> m_oldToNewMap; /// We skip specializing recursive functions. Need backtracking to properly deal with them. - std::set const m_recursiveFunctions; + std::set const m_recursiveFunctions; NameDispenser& m_nameDispenser; - Dialect const& m_dialect; }; } diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp index d719302dcbc2..6061fa3e9725 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp @@ -29,13 +29,13 @@ using namespace solidity::yul; void InlinableExpressionFunctionFinder::operator()(Identifier const& _identifier) { - checkAllowed(_identifier.name); + checkAllowed(_identifier); ASTWalker::operator()(_identifier); } void InlinableExpressionFunctionFinder::operator()(FunctionCall const& _funCall) { - checkAllowed(_funCall.functionName.name); + checkAllowed(_funCall.functionName); ASTWalker::operator()(_funCall); } @@ -67,3 +67,9 @@ void InlinableExpressionFunctionFinder::operator()(FunctionDefinition const& _fu } ASTWalker::operator()(_function.body); } +void InlinableExpressionFunctionFinder::checkAllowed(FunctionName const& _name) +{ + // disallowed function names can only ever be user-defined `yul::Identifier`s, not builtins + if (std::holds_alternative(_name) && m_disallowedIdentifiers.count(std::get(_name).name) != 0) + m_foundDisallowedIdentifier = true; +} diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.h b/libyul/optimiser/InlinableExpressionFunctionFinder.h index e7210da69a0a..c6897c173529 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.h +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.h @@ -53,11 +53,7 @@ class InlinableExpressionFunctionFinder: public ASTWalker void operator()(FunctionDefinition const& _function) override; private: - void checkAllowed(YulName _name) - { - if (m_disallowedIdentifiers.count(_name)) - m_foundDisallowedIdentifier = true; - } + void checkAllowed(FunctionName const& _name); bool m_foundDisallowedIdentifier = false; std::set m_disallowedIdentifiers; diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 731f4b3b8195..ceaa8f06b359 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -32,9 +32,11 @@ using namespace solidity; using namespace solidity::yul; -KnowledgeBase::KnowledgeBase(std::map const& _ssaValues): +KnowledgeBase::KnowledgeBase(std::map const& _ssaValues, Dialect const& _dialect): m_valuesAreSSA(true), - m_variableValues([_ssaValues](YulName _var) { return util::valueOrNullptr(_ssaValues, _var); }) + m_variableValues([_ssaValues](YulName _var) { return util::valueOrNullptr(_ssaValues, _var); }), + m_addBuiltinHandle(_dialect.findBuiltin("add")), + m_subBuiltinHandle(_dialect.findBuiltin("sub")) {} bool KnowledgeBase::knownToBeDifferent(YulName _a, YulName _b) @@ -116,9 +118,12 @@ std::optional KnowledgeBase::explore(Expression c return VariableOffset{YulName{}, literal->value.value()}; else if (Identifier const* identifier = std::get_if(&_value)) return explore(identifier->name); - else if (FunctionCall const* f = std::get_if(&_value)) + else if ( + FunctionCall const* f = std::get_if(&_value); + f && isBuiltinFunctionCall(*f) + ) { - if (f->functionName.name == "add"_yulname) + if (std::get(f->functionName).handle == m_addBuiltinHandle) { if (std::optional a = explore(f->arguments[0])) if (std::optional b = explore(f->arguments[1])) @@ -132,7 +137,7 @@ std::optional KnowledgeBase::explore(Expression c return VariableOffset{a->reference, offset}; } } - else if (f->functionName.name == "sub"_yulname) + else if (std::get(f->functionName).handle == m_subBuiltinHandle) if (std::optional a = explore(f->arguments[0])) if (std::optional b = explore(f->arguments[1])) { diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index 46ea7b96af66..0852f8902592 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include @@ -33,7 +34,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct AssignedValue; /** @@ -62,11 +63,13 @@ class KnowledgeBase public: /// Constructor for arbitrary value callback that allows for variable values /// to change in between calls to functions of this class. - explicit KnowledgeBase(std::function _variableValues): - m_variableValues(std::move(_variableValues)) + explicit KnowledgeBase(std::function _variableValues, Dialect const& _dialect): + m_variableValues(std::move(_variableValues)), + m_addBuiltinHandle(_dialect.findBuiltin("add")), + m_subBuiltinHandle(_dialect.findBuiltin("sub")) {} /// Constructor to use if source code is in SSA form and values are constant. - explicit KnowledgeBase(std::map const& _ssaValues); + explicit KnowledgeBase(std::map const& _ssaValues, Dialect const& _dialect); bool knownToBeDifferent(YulName _a, YulName _b); std::optional differenceIfKnownConstant(YulName _a, YulName _b); @@ -115,6 +118,8 @@ class KnowledgeBase bool m_valuesAreSSA = false; /// Callback to retrieve the current value of a variable. std::function m_variableValues; + std::optional m_addBuiltinHandle; + std::optional m_subBuiltinHandle; /// Offsets for each variable to one representative per group. /// The empty string is the representative of the constant value zero. diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 98d938a3621e..36163c6c5f21 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -56,13 +56,17 @@ void LoadResolver::visit(Expression& _e) { DataFlowAnalyzer::visit(_e); - if (FunctionCall const* funCall = std::get_if(&_e)) + if ( + FunctionCall const* funCall = std::get_if(&_e); + funCall && std::holds_alternative(funCall->functionName) + ) { - if (funCall->functionName.name == m_loadFunctionName[static_cast(StoreLoadLocation::Memory)]) + auto const& builtinHandle = std::get(funCall->functionName).handle; + if (builtinHandle == m_loadFunctionName[static_cast(StoreLoadLocation::Memory)]) tryResolve(_e, StoreLoadLocation::Memory, funCall->arguments); - else if (funCall->functionName.name == m_loadFunctionName[static_cast(StoreLoadLocation::Storage)]) + else if (builtinHandle == m_loadFunctionName[static_cast(StoreLoadLocation::Storage)]) tryResolve(_e, StoreLoadLocation::Storage, funCall->arguments); - else if (!m_containsMSize && funCall->functionName.name == m_dialect.hashFunction()) + else if (!m_containsMSize && builtinHandle == m_dialect.hashFunctionHandle()) { Identifier const* start = std::get_if(&funCall->arguments.at(0)); Identifier const* length = std::get_if(&funCall->arguments.at(1)); diff --git a/libyul/optimiser/LoadResolver.h b/libyul/optimiser/LoadResolver.h index b4a496303373..d878076929a6 100644 --- a/libyul/optimiser/LoadResolver.h +++ b/libyul/optimiser/LoadResolver.h @@ -49,7 +49,7 @@ class LoadResolver: public DataFlowAnalyzer private: LoadResolver( Dialect const& _dialect, - std::map _functionSideEffects, + std::map _functionSideEffects, bool _containsMSize, std::optional _expectedExecutionsPerDeployment ): diff --git a/libyul/optimiser/LoopInvariantCodeMotion.cpp b/libyul/optimiser/LoopInvariantCodeMotion.cpp index 2a196a68f956..f2e7d040802e 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.cpp +++ b/libyul/optimiser/LoopInvariantCodeMotion.cpp @@ -32,7 +32,7 @@ using namespace solidity::yul; void LoopInvariantCodeMotion::run(OptimiserStepContext& _context, Block& _ast) { - std::map functionSideEffects = + std::map functionSideEffects = SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)); bool containsMSize = MSizeFinder::containsMSize(_context.dialect, _ast); std::set ssaVars = SSAValueTracker::ssaVariables(_ast); diff --git a/libyul/optimiser/LoopInvariantCodeMotion.h b/libyul/optimiser/LoopInvariantCodeMotion.h index c85b87a01c32..d03a91eeeba9 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.h +++ b/libyul/optimiser/LoopInvariantCodeMotion.h @@ -49,7 +49,7 @@ class LoopInvariantCodeMotion: public ASTModifier explicit LoopInvariantCodeMotion( Dialect const& _dialect, std::set const& _ssaVariables, - std::map const& _functionSideEffects, + std::map const& _functionSideEffects, bool _containsMSize ): m_containsMSize(_containsMSize), @@ -69,7 +69,7 @@ class LoopInvariantCodeMotion: public ASTModifier bool m_containsMSize = true; Dialect const& m_dialect; std::set const& m_ssaVariables; - std::map const& m_functionSideEffects; + std::map const& m_functionSideEffects; }; } diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 546c465b5c43..04bfe9a7a06d 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -137,7 +137,7 @@ void CodeCost::operator()(FunctionCall const& _funCall) { ASTWalker::operator()(_funCall); - if (auto instruction = toEVMInstruction(m_dialect, _funCall.functionName.name)) + if (auto instruction = toEVMInstruction(m_dialect, _funCall.functionName)) { addInstructionCost(*instruction); return; diff --git a/libyul/optimiser/Metrics.h b/libyul/optimiser/Metrics.h index 01ab1adbd7e3..cdcc28822d94 100644 --- a/libyul/optimiser/Metrics.h +++ b/libyul/optimiser/Metrics.h @@ -27,8 +27,8 @@ namespace solidity::yul { -struct Dialect; -struct EVMDialect; +class Dialect; +class EVMDialect; /** * Weights to be assigned to specific yul statements and expressions by a metric. diff --git a/libyul/optimiser/NameCollector.cpp b/libyul/optimiser/NameCollector.cpp index d6db837f8485..cde9b64f67d1 100644 --- a/libyul/optimiser/NameCollector.cpp +++ b/libyul/optimiser/NameCollector.cpp @@ -22,6 +22,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -55,25 +56,25 @@ void ReferencesCounter::operator()(Identifier const& _identifier) void ReferencesCounter::operator()(FunctionCall const& _funCall) { - ++m_references[_funCall.functionName.name]; + ++m_references[functionNameToHandle(_funCall.functionName)]; ASTWalker::operator()(_funCall); } -std::map ReferencesCounter::countReferences(Block const& _block) +std::map ReferencesCounter::countReferences(Block const& _block) { ReferencesCounter counter; counter(_block); return std::move(counter.m_references); } -std::map ReferencesCounter::countReferences(FunctionDefinition const& _function) +std::map ReferencesCounter::countReferences(FunctionDefinition const& _function) { ReferencesCounter counter; counter(_function); return std::move(counter.m_references); } -std::map ReferencesCounter::countReferences(Expression const& _expression) +std::map ReferencesCounter::countReferences(Expression const& _expression) { ReferencesCounter counter; counter.visit(_expression); diff --git a/libyul/optimiser/NameCollector.h b/libyul/optimiser/NameCollector.h index 0fc2e311ca50..2adc73ced8e3 100644 --- a/libyul/optimiser/NameCollector.h +++ b/libyul/optimiser/NameCollector.h @@ -76,12 +76,12 @@ class ReferencesCounter: public ASTWalker void operator()(Identifier const& _identifier) override; void operator()(FunctionCall const& _funCall) override; - static std::map countReferences(Block const& _block); - static std::map countReferences(FunctionDefinition const& _function); - static std::map countReferences(Expression const& _expression); + static std::map countReferences(Block const& _block); + static std::map countReferences(FunctionDefinition const& _function); + static std::map countReferences(Expression const& _expression); private: - std::map m_references; + std::map m_references; }; /** diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index c2b6b9847f3c..3493c36682df 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -58,7 +58,7 @@ YulName NameDispenser::newName(YulName _nameHint) bool NameDispenser::illegalName(YulName _name) { - return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); + return isRestrictedIdentifier(m_dialect, _name.str()) || m_usedNames.contains(_name); } void NameDispenser::reset(Block const& _ast) diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h index 3da50359a764..ec936d39af1b 100644 --- a/libyul/optimiser/NameDispenser.h +++ b/libyul/optimiser/NameDispenser.h @@ -28,7 +28,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Optimizer component that can be used to generate new names that diff --git a/libyul/optimiser/NameDisplacer.cpp b/libyul/optimiser/NameDisplacer.cpp index c68d52f9a7bb..7430c26c3046 100644 --- a/libyul/optimiser/NameDisplacer.cpp +++ b/libyul/optimiser/NameDisplacer.cpp @@ -54,7 +54,8 @@ void NameDisplacer::operator()(FunctionDefinition& _function) void NameDisplacer::operator()(FunctionCall& _funCall) { - checkAndReplace(_funCall.functionName.name); + if (std::holds_alternative(_funCall.functionName)) + checkAndReplace(std::get(_funCall.functionName).name); ASTModifier::operator()(_funCall); } diff --git a/libyul/optimiser/NameDisplacer.h b/libyul/optimiser/NameDisplacer.h index 3312e203d7ae..cfe297d4d7a4 100644 --- a/libyul/optimiser/NameDisplacer.h +++ b/libyul/optimiser/NameDisplacer.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Optimiser component that renames identifiers to free up certain names. diff --git a/libyul/optimiser/NameSimplifier.cpp b/libyul/optimiser/NameSimplifier.cpp index d57a61332e3e..0572a9003523 100644 --- a/libyul/optimiser/NameSimplifier.cpp +++ b/libyul/optimiser/NameSimplifier.cpp @@ -67,8 +67,11 @@ void NameSimplifier::operator()(Identifier& _identifier) void NameSimplifier::operator()(FunctionCall& _funCall) { // The visitor on its own does not visit the function name. - if (!m_context.dialect.builtin(_funCall.functionName.name)) - (*this)(_funCall.functionName); + if (!isBuiltinFunctionCall(_funCall)) + { + yulAssert(std::holds_alternative(_funCall.functionName)); + (*this)(std::get(_funCall.functionName)); + } ASTModifier::operator()(_funCall); } diff --git a/libyul/optimiser/NameSimplifier.h b/libyul/optimiser/NameSimplifier.h index 0ff5077cc694..f3426d60f8f8 100644 --- a/libyul/optimiser/NameSimplifier.h +++ b/libyul/optimiser/NameSimplifier.h @@ -30,7 +30,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Pass to "simplify" all identifier names. diff --git a/libyul/optimiser/OptimiserStep.h b/libyul/optimiser/OptimiserStep.h index 89bfcef814d0..7425a1906532 100644 --- a/libyul/optimiser/OptimiserStep.h +++ b/libyul/optimiser/OptimiserStep.h @@ -27,7 +27,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct Block; class NameDispenser; diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index 19f262060fc0..3001d43f8e85 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -23,8 +23,9 @@ #include -#include #include +#include +#include #include #include @@ -55,15 +56,15 @@ void yul::removeEmptyBlocks(Block& _block) ranges::actions::remove_if(_block.statements, isEmptyBlock); } -bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identifier) +bool yul::isRestrictedIdentifier(Dialect const& _dialect, std::string_view const _identifier) { - return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); + return _identifier.empty() || hasLeadingOrTrailingDot(_identifier) || TokenTraits::isYulKeyword(_identifier) || _dialect.reservedIdentifier(_identifier); } -std::optional yul::toEVMInstruction(Dialect const& _dialect, YulName const& _name) +std::optional yul::toEVMInstruction(Dialect const& _dialect, FunctionName const& _name) { if (auto const* dialect = dynamic_cast(&_dialect)) - if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name)) + if (BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_name, *dialect)) return builtin->instruction; return std::nullopt; } diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index 911a1be0a812..d302b4aebba8 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -24,11 +24,11 @@ #include #include #include -#include #include #include #include +#include namespace solidity::evmasm { @@ -45,10 +45,10 @@ void removeEmptyBlocks(Block& _block); /// Returns true if a given literal can not be used as an identifier. /// This includes Yul keywords and builtins of the given dialect. -bool isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identifier); +bool isRestrictedIdentifier(Dialect const& _dialect, std::string_view _identifier); /// Helper function that returns the instruction, if the `_name` is a BuiltinFunction -std::optional toEVMInstruction(Dialect const& _dialect, YulName const& _name); +std::optional toEVMInstruction(Dialect const& _dialect, FunctionName const& _name); /// Helper function that returns the EVM version from a dialect. /// It returns the default EVM version if dialect is not an EVMDialect. diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index fe33b10a2245..bfcd9d8f630f 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -71,7 +71,7 @@ void Rematerialiser::visit(Expression& _e) ) { assertThrow(m_referenceCounts[name] > 0, OptimizerException, ""); - auto variableReferences = references(name); + auto variableReferences = sortedReferences(name); if (!variableReferences || ranges::all_of(*variableReferences, [&](auto const& ref) { return inScope(ref); })) { // update reference counts diff --git a/libyul/optimiser/SSATransform.h b/libyul/optimiser/SSATransform.h index 64181bf208d3..4b46d7169f80 100644 --- a/libyul/optimiser/SSATransform.h +++ b/libyul/optimiser/SSATransform.h @@ -67,7 +67,7 @@ class NameDispenser; * The current value mapping is cleared for a variable a at the end of each block * in which it was assigned. We compensate that by appending a declaration * of the form of "let a_1 := a" right after the location where control flow joins so - * variable references can use the SSA variable. The only exception to this rule are + * variable references can use the SSA variable. The only exception to this rule is * for loop conditions, as we cannot insert a variable declaration there. * * After this stage, UnusedAssignmentEliminator is recommended to remove the unnecessary diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index d945dbcac7f5..a505126ae9f1 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -40,7 +41,7 @@ using namespace solidity::yul; SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, Expression const& _expression, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -56,7 +57,7 @@ SideEffectsCollector::SideEffectsCollector(Dialect const& _dialect, Statement co SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, Block const& _ast, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -66,7 +67,7 @@ SideEffectsCollector::SideEffectsCollector( SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, ForLoop const& _ast, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -77,11 +78,11 @@ void SideEffectsCollector::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); - YulName functionName = _functionCall.functionName.name; - if (BuiltinFunction const* f = m_dialect.builtin(functionName)) - m_sideEffects += f->sideEffects; - else if (m_functionSideEffects && m_functionSideEffects->count(functionName)) - m_sideEffects += m_functionSideEffects->at(functionName); + FunctionHandle functionHandle = functionNameToHandle(_functionCall.functionName); + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) + m_sideEffects += builtin->sideEffects; + else if (m_functionSideEffects && m_functionSideEffects->count(functionHandle)) + m_sideEffects += m_functionSideEffects->at(functionHandle); else m_sideEffects += SideEffects::worst(); } @@ -93,14 +94,15 @@ bool MSizeFinder::containsMSize(Dialect const& _dialect, Block const& _ast) return finder.m_msizeFound; } -bool MSizeFinder::containsMSize(Dialect const& _dialect, Object const& _object) +bool MSizeFinder::containsMSize(Object const& _object) { - if (containsMSize(_dialect, _object.code()->root())) + yulAssert(_object.dialect()); + if (containsMSize(*_object.dialect(), _object.code()->root())) return true; for (std::shared_ptr const& node: _object.subObjects) if (auto const* object = dynamic_cast(node.get())) - if (containsMSize(_dialect, *object)) + if (containsMSize(*object)) return true; return false; @@ -110,12 +112,12 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); - if (BuiltinFunction const* f = m_dialect.builtin(_functionCall.functionName.name)) - if (f->isMSize) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) + if (builtin->isMSize) m_msizeFound = true; } -std::map SideEffectsPropagator::sideEffects( +std::map SideEffectsPropagator::sideEffects( Dialect const& _dialect, CallGraph const& _directCallGraph ) @@ -126,8 +128,16 @@ std::map SideEffectsPropagator::sideEffects( // In the future, we should refine that, because the property // is actually a bit different from "not movable". - std::map ret; - for (auto const& function: _directCallGraph.functionsWithLoops + _directCallGraph.recursiveFunctions()) + std::map ret; + for (auto const& function: _directCallGraph.functionsWithLoops) + { + ret[function].movable = false; + ret[function].canBeRemoved = false; + ret[function].canBeRemovedIfNoMSize = false; + ret[function].cannotLoop = false; + } + + for (auto const& function: _directCallGraph.recursiveFunctions()) { ret[function].movable = false; ret[function].canBeRemoved = false; @@ -137,20 +147,20 @@ std::map SideEffectsPropagator::sideEffects( for (auto const& call: _directCallGraph.functionCalls) { - YulName funName = call.first; + FunctionHandle funName = call.first; SideEffects sideEffects; - auto _visit = [&, visited = std::set{}](YulName _function, auto&& _recurse) mutable { + auto _visit = [&, visited = std::set{}](FunctionHandle _function, auto&& _recurse) mutable { if (!visited.insert(_function).second) return; if (sideEffects == SideEffects::worst()) return; - if (BuiltinFunction const* f = _dialect.builtin(_function)) - sideEffects += f->sideEffects; + if (BuiltinHandle const* builtinHandle = std::get_if(&_function)) + sideEffects += _dialect.builtin(*builtinHandle).sideEffects; else { if (ret.count(_function)) sideEffects += ret[_function]; - for (YulName callee: _directCallGraph.functionCalls.at(_function)) + for (FunctionHandle const& callee: _directCallGraph.functionCalls.at(_function)) _recurse(callee, _recurse); } }; @@ -227,10 +237,13 @@ bool TerminationFinder::containsNonContinuingFunctionCall(Expression const& _exp if (containsNonContinuingFunctionCall(arg)) return true; - if (auto builtin = m_dialect.builtin(functionCall->functionName.name)) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(functionCall->functionName, m_dialect)) return !builtin->controlFlowSideEffects.canContinue; - else if (m_functionSideEffects && m_functionSideEffects->count(functionCall->functionName.name)) - return !m_functionSideEffects->at(functionCall->functionName.name).canContinue; + + yulAssert(std::holds_alternative(functionCall->functionName)); + auto const& name = std::get(functionCall->functionName).name; + if (m_functionSideEffects && m_functionSideEffects->count(name)) + return !m_functionSideEffects->at(name).canContinue; } return false; } diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index 1d0018897c00..9d3c724af2d7 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Specific AST walker that determines side-effect free-ness and movability of code. @@ -42,23 +42,23 @@ class SideEffectsCollector: public ASTWalker public: explicit SideEffectsCollector( Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ): m_dialect(_dialect), m_functionSideEffects(_functionSideEffects) {} SideEffectsCollector( Dialect const& _dialect, Expression const& _expression, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); SideEffectsCollector(Dialect const& _dialect, Statement const& _statement); SideEffectsCollector( Dialect const& _dialect, Block const& _ast, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); SideEffectsCollector( Dialect const& _dialect, ForLoop const& _ast, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); using ASTWalker::operator(); @@ -117,7 +117,7 @@ class SideEffectsCollector: public ASTWalker private: Dialect const& m_dialect; - std::map const* m_functionSideEffects = nullptr; + std::map const* m_functionSideEffects = nullptr; SideEffects m_sideEffects; }; @@ -130,7 +130,7 @@ class SideEffectsCollector: public ASTWalker class SideEffectsPropagator { public: - static std::map sideEffects( + static std::map sideEffects( Dialect const& _dialect, CallGraph const& _directCallGraph ); @@ -149,7 +149,7 @@ class MSizeFinder: public ASTWalker { public: static bool containsMSize(Dialect const& _dialect, Block const& _ast); - static bool containsMSize(Dialect const& _dialect, Object const& _object); + static bool containsMSize(Object const& _object); using ASTWalker::operator(); void operator()(FunctionCall const& _funCall) override; @@ -195,7 +195,7 @@ class MovableChecker: public SideEffectsCollector public: explicit MovableChecker( Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ): SideEffectsCollector(_dialect, _functionSideEffects) {} MovableChecker(Dialect const& _dialect, Expression const& _expression); diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 72c0f70ca281..8a7549cc125a 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -79,7 +79,7 @@ std::optional const*>> { if (std::holds_alternative(_expr)) if (auto const* dialect = dynamic_cast(&_dialect)) - if (auto const* builtin = dialect->builtin(std::get(_expr).functionName.name)) + if (auto const* builtin = resolveBuiltinFunctionForEVM(std::get(_expr).functionName, *dialect)) if (builtin->instruction) return std::make_pair(*builtin->instruction, &std::get(_expr).arguments); @@ -234,7 +234,7 @@ evmasm::Instruction Pattern::instruction() const return m_instruction; } -Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const +Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData, EVMDialect const& _dialect) const { if (matchGroup()) return ASTCopier().translate(matchGroupValue()); @@ -247,12 +247,18 @@ Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData { std::vector arguments; for (auto const& arg: m_arguments) - arguments.emplace_back(arg.toExpression(_debugData, _evmVersion)); + arguments.emplace_back(arg.toExpression(_debugData, _dialect)); - std::string name = util::toLower(instructionInfo(m_instruction, _evmVersion).name); + if (!m_instructionBuiltinHandle) + { + std::string name = util::toLower(instructionInfo(m_instruction, _dialect.evmVersion()).name); + std::optional handle = _dialect.findBuiltin(name); + yulAssert(handle); + m_instructionBuiltinHandle = *handle; + } return FunctionCall{_debugData, - Identifier{_debugData, YulName{name}}, + BuiltinName{_debugData, *m_instructionBuiltinHandle}, std::move(arguments) }; } diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 9362ee8557ec..f4b584b99ca4 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -38,8 +39,9 @@ namespace solidity::yul { -struct Dialect; struct AssignedValue; +class Dialect; +class EVMDialect; class Pattern; using DebugData = langutil::DebugData; @@ -133,13 +135,14 @@ class Pattern /// Turns this pattern into an actual expression. Should only be called /// for patterns resulting from an action, i.e. with match groups assigned. - Expression toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const; + Expression toExpression(langutil::DebugData::ConstPtr const& _debugData, EVMDialect const& _dialect) const; private: Expression const& matchGroupValue() const; PatternKind m_kind = PatternKind::Any; evmasm::Instruction m_instruction; ///< Only valid if m_kind is Operation + std::optional mutable m_instructionBuiltinHandle; ///< Builtin handle cache for instructions std::shared_ptr m_data; ///< Only valid if m_kind is Constant std::vector m_arguments; unsigned m_matchGroup = 0; diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 2c2ef4272904..97d2c054700d 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -15,7 +15,7 @@ along with solidity. If not, see . */ /** - * Optimisation stage that aggressively rematerializes certain variables ina a function to free + * Optimisation stage that aggressively rematerializes certain variables in a function to free * space on the stack until it is compilable. */ @@ -237,32 +237,41 @@ void eliminateVariablesOptimizedCodegen( } std::tuple StackCompressor::run( - Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation, size_t _maxIterations) { yulAssert(_object.hasCode()); + yulAssert(_object.dialect(), "No dialect"); yulAssert( !_object.code()->root().statements.empty() && std::holds_alternative(_object.code()->root().statements.at(0)), "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; - if (auto evmDialect = dynamic_cast(&_dialect)) + auto evmDialect = dynamic_cast(_object.dialect()); + if (evmDialect) + { + yulAssert(!evmDialect->eofVersion().has_value(), "StackCompressor does not support EOF."); usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _object.code()->root()); + } + bool allowMSizeOptimization = !MSizeFinder::containsMSize(*_object.dialect(), _object.code()->root()); Block astRoot = std::get(ASTCopier{}(_object.code()->root())); if (usesOptimizedCodeGenerator) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, astRoot, _object.qualifiedDataNames()); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, astRoot); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( + *_object.dialect(), + astRoot, + _object.summarizeStructure() + ); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *_object.dialect(), astRoot); + yulAssert(evmDialect); eliminateVariablesOptimizedCodegen( - _dialect, + *_object.dialect(), astRoot, - StackLayoutGenerator::reportStackTooDeep(*cfg), + StackLayoutGenerator::reportStackTooDeep(*cfg, *evmDialect), allowMSizeOptimization ); } @@ -271,12 +280,12 @@ std::tuple StackCompressor::run( for (size_t iterations = 0; iterations < _maxIterations; iterations++) { Object object(_object); - object.setCode(std::make_shared(std::get(ASTCopier{}(astRoot)))); - std::map stackSurplus = CompilabilityChecker(_dialect, object, _optimizeStackAllocation).stackDeficit; + object.setCode(std::make_shared(*_object.dialect(), std::get(ASTCopier{}(astRoot)))); + std::map stackSurplus = CompilabilityChecker(object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) return std::make_tuple(true, std::move(astRoot)); eliminateVariables( - _dialect, + *object.dialect(), astRoot, stackSurplus, allowMSizeOptimization diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index 15d057455ac8..728acb813001 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Optimisation stage that aggressively rematerializes certain variables ina a function to free + * Optimisation stage that aggressively rematerializes certain variables in a function to free * space on the stack until it is compilable. */ @@ -29,8 +29,8 @@ namespace solidity::yul { -struct Dialect; -struct Object; +class Dialect; +class Object; struct FunctionDefinition; /** @@ -47,7 +47,6 @@ class StackCompressor /// Try to remove local variables until the AST is compilable. /// @returns tuple with true if it was successful as first element, second element is the modified AST. static std::tuple run( - Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation, size_t _maxIterations diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index d3cb6418fd30..f70bc0c1d2a7 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -57,7 +57,7 @@ namespace */ struct MemoryOffsetAllocator { - uint64_t run(YulName _function = YulName{}) + uint64_t run(FunctionHandle _function = YulName{}) { if (slotsRequiredForFunction.count(_function)) return slotsRequiredForFunction[_function]; @@ -65,14 +65,17 @@ struct MemoryOffsetAllocator // Assign to zero early to guard against recursive calls. slotsRequiredForFunction[_function] = 0; + if (!std::holds_alternative(_function)) + return 0; + uint64_t requiredSlots = 0; - if (callGraph.count(_function)) - for (YulName child: callGraph.at(_function)) + if (callGraph.count(std::get(_function))) + for (FunctionHandle const& child: callGraph.at(std::get(_function))) requiredSlots = std::max(run(child), requiredSlots); - if (auto const* unreachables = util::valueOrNullptr(unreachableVariables, _function)) + if (auto const* unreachables = util::valueOrNullptr(unreachableVariables, std::get(_function))) { - if (FunctionDefinition const* functionDefinition = util::valueOrDefault(functionDefinitions, _function, nullptr, util::allow_copy)) + if (FunctionDefinition const* functionDefinition = util::valueOrDefault(functionDefinitions, std::get(_function), nullptr, util::allow_copy)) if ( size_t totalArgCount = functionDefinition->returnVariables.size() + functionDefinition->parameters.size(); totalArgCount > 16 @@ -99,14 +102,14 @@ struct MemoryOffsetAllocator /// An empty variable name means that the function has too many arguments or return variables. std::map> const& unreachableVariables; /// The graph of immediate function calls of all functions. - std::map> const& callGraph; + std::map> const& callGraph; /// Maps the name of each user-defined function to its definition. std::map const& functionDefinitions; /// Maps variable names to the memory slot the respective variable is assigned. std::map slotAllocations{}; /// Maps function names to the number of memory slots the respective function requires. - std::map slotsRequiredForFunction{}; + std::map slotsRequiredForFunction{}; }; u256 literalArgumentValue(FunctionCall const& _call) @@ -129,17 +132,24 @@ Block StackLimitEvader::run( evmDialect && evmDialect->providesObjectAccess(), "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); + yulAssert( + !evmDialect->eofVersion().has_value(), + "StackLimitEvader does not support EOF." + ); auto astRoot = std::get(ASTCopier{}(_object.code()->root())); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, astRoot, _object.qualifiedDataNames()); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( + *evmDialect, + astRoot, + _object.summarizeStructure() + ); std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, astRoot); - run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg)); + run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg, *evmDialect)); } else { run(_context, astRoot, CompilabilityChecker{ - _context.dialect, _object, true, }.unreachableVariables); @@ -153,6 +163,15 @@ void StackLimitEvader::run( std::map> const& _stackTooDeepErrors ) { + auto const* evmDialect = dynamic_cast(&_context.dialect); + yulAssert( + evmDialect && evmDialect->providesObjectAccess(), + "StackLimitEvader can only be run on objects using the EVMDialect with object access." + ); + yulAssert( + !evmDialect->eofVersion().has_value(), + "StackLimitEvader does not support EOF." + ); std::map> unreachableVariables; for (auto&& [function, stackTooDeepErrors]: _stackTooDeepErrors) { @@ -177,8 +196,14 @@ void StackLimitEvader::run( evmDialect && evmDialect->providesObjectAccess(), "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); + yulAssert( + !evmDialect->eofVersion().has_value(), + "StackLimitEvader does not support EOF." + ); - std::vector memoryGuardCalls = findFunctionCalls(_astRoot, "memoryguard"_yulname); + auto const memoryGuardHandle = evmDialect->findBuiltin("memoryguard"); + yulAssert(memoryGuardHandle, "Compiling with object access, memoryguard should be available as builtin."); + std::vector const memoryGuardCalls = findFunctionCalls(_astRoot, *memoryGuardHandle); // Do not optimise, if no ``memoryguard`` call is found. if (memoryGuardCalls.empty()) return; @@ -194,9 +219,12 @@ void StackLimitEvader::run( CallGraph callGraph = CallGraphGenerator::callGraph(_astRoot); // We cannot move variables in recursive functions to fixed memory offsets. - for (YulName function: callGraph.recursiveFunctions()) - if (_unreachableVariables.count(function)) + for (FunctionHandle function: callGraph.recursiveFunctions()) + { + yulAssert(std::holds_alternative(function), "Builtins are not recursive."); + if (_unreachableVariables.count(std::get(function))) return; + } std::map functionDefinitions = allFunctionDefinitions(_astRoot); @@ -207,7 +235,7 @@ void StackLimitEvader::run( StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, _astRoot); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: findFunctionCalls(_astRoot, "memoryguard"_yulname)) + for (FunctionCall* memoryGuardCall: findFunctionCalls(_astRoot, *memoryGuardHandle)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/libyul/optimiser/StackLimitEvader.h b/libyul/optimiser/StackLimitEvader.h index a5871f7f111d..d63c3287dd41 100644 --- a/libyul/optimiser/StackLimitEvader.h +++ b/libyul/optimiser/StackLimitEvader.h @@ -27,7 +27,7 @@ namespace solidity::yul { -struct Object; +class Object; /** * Optimisation stage that assigns memory offsets to variables that would become unreachable if diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index 7e3f93475f80..15df64b3f252 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -42,12 +42,12 @@ std::vector generateMemoryStore( Expression _value ) { - BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(); - yulAssert(memoryStoreFunction, ""); + std::optional memoryStoreFunctionHandle = _dialect.memoryStoreFunctionHandle(); + yulAssert(memoryStoreFunctionHandle); std::vector result; result.emplace_back(ExpressionStatement{_debugData, FunctionCall{ _debugData, - Identifier{_debugData, memoryStoreFunction->name}, + BuiltinName{_debugData, *memoryStoreFunctionHandle}, { Literal{_debugData, LiteralKind::Number, _mpos}, std::move(_value) @@ -58,11 +58,11 @@ std::vector generateMemoryStore( FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, LiteralValue const& _mpos) { - BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(); - yulAssert(memoryLoadFunction, ""); + std::optional const& memoryLoadHandle = _dialect.memoryLoadFunctionHandle(); + yulAssert(memoryLoadHandle); return FunctionCall{ _debugData, - Identifier{_debugData, memoryLoadFunction->name}, { + BuiltinName{_debugData, *memoryLoadHandle}, { Literal{ _debugData, LiteralKind::Number, @@ -223,13 +223,16 @@ void StackToMemoryMover::operator()(Block& _block) { FunctionCall const* functionCall = std::get_if(_stmt.value.get()); yulAssert(functionCall, ""); - if (m_context.dialect.builtin(functionCall->functionName.name)) + if (isBuiltinFunctionCall(*functionCall)) rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); else + { + yulAssert(std::holds_alternative(functionCall->functionName)); rhsMemorySlots = - m_functionReturnVariables.at(functionCall->functionName.name) | + m_functionReturnVariables.at(std::get(functionCall->functionName).name) | ranges::views::transform(m_memoryOffsetTracker) | ranges::to>>; + } } else rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 0233a1cf078a..17698d74e2a0 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -72,6 +72,7 @@ #include #include +#include #include @@ -83,58 +84,11 @@ #include #include -#ifdef PROFILE_OPTIMIZER_STEPS -#include -#include -#endif - using namespace solidity; using namespace solidity::yul; -#ifdef PROFILE_OPTIMIZER_STEPS -using namespace std::chrono; -#endif using namespace std::string_literals; -namespace -{ - -#ifdef PROFILE_OPTIMIZER_STEPS -void outputPerformanceMetrics(std::map const& _metrics) -{ - std::vector> durations(_metrics.begin(), _metrics.end()); - sort( - durations.begin(), - durations.end(), - [](std::pair const& _lhs, std::pair const& _rhs) -> bool - { - return _lhs.second < _rhs.second; - } - ); - - int64_t totalDurationInMicroseconds = 0; - for (auto&& [step, durationInMicroseconds]: durations) - totalDurationInMicroseconds += durationInMicroseconds; - - std::cerr << "Performance metrics of optimizer steps" << std::endl; - std::cerr << "======================================" << std::endl; - constexpr double microsecondsInSecond = 1000000; - for (auto&& [step, durationInMicroseconds]: durations) - { - double percentage = 100.0 * static_cast(durationInMicroseconds) / static_cast(totalDurationInMicroseconds); - double sec = static_cast(durationInMicroseconds) / microsecondsInSecond; - std::cerr << fmt::format("{:>7.3f}% ({} s): {}", percentage, sec, step) << std::endl; - } - double totalDurationInSeconds = static_cast(totalDurationInMicroseconds) / microsecondsInSecond; - std::cerr << "--------------------------------------" << std::endl; - std::cerr << fmt::format("{:>7}% ({:.3f} s)", 100, totalDurationInSeconds) << std::endl; -} -#endif - -} - - void OptimiserSuite::run( - Dialect const& _dialect, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, @@ -144,23 +98,28 @@ void OptimiserSuite::run( std::set const& _externallyUsedIdentifiers ) { - EVMDialect const* evmDialect = dynamic_cast(&_dialect); + yulAssert(_object.dialect()); + auto const& dialect = *_object.dialect(); + EVMDialect const* evmDialect = dynamic_cast(_object.dialect()); bool usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); std::set reservedIdentifiers = _externallyUsedIdentifiers; - reservedIdentifiers += _dialect.fixedFunctionNames(); - auto astRoot = std::get(Disambiguator( - _dialect, - *_object.analysisInfo, - reservedIdentifiers - )(_object.code()->root())); + Block astRoot; + { + PROFILER_PROBE("Disambiguator", probe); + astRoot = std::get(Disambiguator( + dialect, + *_object.analysisInfo, + reservedIdentifiers + )(_object.code()->root())); + } - NameDispenser dispenser{_dialect, astRoot, reservedIdentifiers}; - OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; + NameDispenser dispenser{dialect, astRoot, reservedIdentifiers}; + OptimiserStepContext context{dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; OptimiserSuite suite(context, Debug::None); @@ -168,7 +127,6 @@ void OptimiserSuite::run( // ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely. suite.runSequence("hgfo", astRoot); - NameSimplifier::run(suite.m_context, astRoot); // Now the user-supplied part suite.runSequence(_optimisationSequence, astRoot); @@ -180,9 +138,9 @@ void OptimiserSuite::run( // message once we perform code generation. if (!usesOptimizedCodeGenerator) { - _object.setCode(std::make_shared(std::move(astRoot))); + PROFILER_PROBE("StackCompressor", probe); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( - _dialect, _object, _optimizeStackAllocation, stackCompressorMaxIterations @@ -199,39 +157,52 @@ void OptimiserSuite::run( if (evmDialect) { yulAssert(_meter, ""); - ConstantOptimiser{*evmDialect, *_meter}(astRoot); + { + PROFILER_PROBE("ConstantOptimiser", probe); + ConstantOptimiser{*evmDialect, *_meter}(astRoot); + } if (usesOptimizedCodeGenerator) { - _object.setCode(std::make_shared(std::move(astRoot))); - astRoot = std::get<1>(StackCompressor::run( - _dialect, - _object, - _optimizeStackAllocation, - stackCompressorMaxIterations - )); - if (evmDialect->providesObjectAccess()) + if (!evmDialect->eofVersion().has_value()) { - _object.setCode(std::make_shared(std::move(astRoot))); - astRoot = StackLimitEvader::run(suite.m_context, _object); + { + PROFILER_PROBE("StackCompressor", probe); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); + astRoot = std::get<1>(StackCompressor::run( + _object, + _optimizeStackAllocation, + stackCompressorMaxIterations + )); + } + if (evmDialect->providesObjectAccess()) + { + PROFILER_PROBE("StackLimitEvader", probe); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); + astRoot = StackLimitEvader::run(suite.m_context, _object); + } } } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) { - _object.setCode(std::make_shared(std::move(astRoot))); + PROFILER_PROBE("StackLimitEvader", probe); + yulAssert(!evmDialect->eofVersion().has_value(), ""); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } dispenser.reset(astRoot); - NameSimplifier::run(suite.m_context, astRoot); - VarNameCleaner::run(suite.m_context, astRoot); - -#ifdef PROFILE_OPTIMIZER_STEPS - outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds); -#endif + { + PROFILER_PROBE("NameSimplifier", probe); + NameSimplifier::run(suite.m_context, astRoot); + } + { + PROFILER_PROBE("VarNameCleaner", probe); + VarNameCleaner::run(suite.m_context, astRoot); + } - _object.setCode(std::make_shared(std::move(astRoot))); - _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object)); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); + _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_object)); } namespace @@ -504,14 +475,12 @@ void OptimiserSuite::runSequence(std::vector const& _steps, Block& { if (m_debug == Debug::PrintStep) std::cout << "Running " << step << std::endl; -#ifdef PROFILE_OPTIMIZER_STEPS - steady_clock::time_point startTime = steady_clock::now(); -#endif - allSteps().at(step)->run(m_context, _ast); -#ifdef PROFILE_OPTIMIZER_STEPS - steady_clock::time_point endTime = steady_clock::now(); - m_durationPerStepInMicroseconds[step] += duration_cast(endTime - startTime).count(); -#endif + + { + PROFILER_PROBE(step, probe); + allSteps().at(step)->run(m_context, _ast); + } + if (m_debug == Debug::PrintChanges) { // TODO should add switch to also compare variable names! @@ -520,7 +489,7 @@ void OptimiserSuite::runSequence(std::vector const& _steps, Block& else { std::cout << "== Running " << step << " changed the AST." << std::endl; - std::cout << AsmPrinter{}(_ast) << std::endl; + std::cout << AsmPrinter{m_context.dialect}(_ast) << std::endl; copy = std::make_unique(std::get(ASTCopier{}(_ast))); } } diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 15a41cb9f3dc..b0c3314089b7 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -36,9 +36,9 @@ namespace solidity::yul { struct AsmAnalysisInfo; -struct Dialect; +class Dialect; class GasMeter; -struct Object; +class Object; /** * Optimiser suite that combines all steps and also provides the settings for the heuristics. @@ -63,7 +63,6 @@ class OptimiserSuite /// The value nullopt for `_expectedExecutionsPerDeployment` represents creation code. static void run( - Dialect const& _dialect, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, @@ -91,9 +90,6 @@ class OptimiserSuite private: OptimiserStepContext& m_context; Debug m_debug; -#ifdef PROFILE_OPTIMIZER_STEPS - std::map m_durationPerStepInMicroseconds; -#endif }; } diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index 0f4aa6e337e1..e233b57e9e2d 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -25,6 +25,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -54,6 +55,14 @@ bool SyntacticallyEqual::expressionEqual(FunctionCall const& _lhs, FunctionCall }); } +bool SyntacticallyEqual::expressionEqual(FunctionName const& _lhs, FunctionName const& _rhs) +{ + return std::visit(util::GenericVisitor{ + [&](BuiltinName const& _builtin) { return std::holds_alternative(_rhs) && _builtin.handle == std::get(_rhs).handle; }, + [&](Identifier const& _identifier) { return std::holds_alternative(_rhs) && expressionEqual(_identifier, std::get(_rhs)); }, + }, _lhs); +} + bool SyntacticallyEqual::expressionEqual(Identifier const& _lhs, Identifier const& _rhs) { auto lhsIt = m_identifiersLHS.find(_lhs.name); @@ -64,9 +73,8 @@ bool SyntacticallyEqual::expressionEqual(Identifier const& _lhs, Identifier cons } bool SyntacticallyEqual::expressionEqual(Literal const& _lhs, Literal const& _rhs) { - yulAssert(validLiteral(_lhs), "Invalid lhs literal during syntactical equality check"); - yulAssert(validLiteral(_rhs), "Invalid rhs literal during syntactical equality check"); - + assert(validLiteral(_lhs)); + assert(validLiteral(_rhs)); return _lhs.value == _rhs.value; } diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index 1fd888f7af8c..0db52c9690df 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -48,6 +48,7 @@ class SyntacticallyEqual bool expressionEqual(FunctionCall const& _lhs, FunctionCall const& _rhs); bool expressionEqual(Identifier const& _lhs, Identifier const& _rhs); + bool expressionEqual(FunctionName const& _lhs, FunctionName const& _rhs); bool expressionEqual(Literal const& _lhs, Literal const& _rhs); bool statementEqual(ExpressionStatement const& _lhs, ExpressionStatement const& _rhs); diff --git a/libyul/optimiser/UnusedAssignEliminator.cpp b/libyul/optimiser/UnusedAssignEliminator.cpp index 13a6ba9ee526..6de2ebf4cacd 100644 --- a/libyul/optimiser/UnusedAssignEliminator.cpp +++ b/libyul/optimiser/UnusedAssignEliminator.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -79,10 +80,13 @@ void UnusedAssignEliminator::operator()(FunctionCall const& _functionCall) UnusedStoreBase::operator()(_functionCall); ControlFlowSideEffects sideEffects; - if (auto builtin = m_dialect.builtin(_functionCall.functionName.name)) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) sideEffects = builtin->controlFlowSideEffects; else - sideEffects = m_controlFlowSideEffects.at(_functionCall.functionName.name); + { + yulAssert(std::holds_alternative(_functionCall.functionName)); + sideEffects = m_controlFlowSideEffects.at(std::get(_functionCall.functionName).name); + } if (!sideEffects.canContinue) // We do not return from the current function, so it is OK to also diff --git a/libyul/optimiser/UnusedAssignEliminator.h b/libyul/optimiser/UnusedAssignEliminator.h index 9c3b1e4bcabf..73628c929671 100644 --- a/libyul/optimiser/UnusedAssignEliminator.h +++ b/libyul/optimiser/UnusedAssignEliminator.h @@ -33,7 +33,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Optimiser component that removes assignments to variables that are not used @@ -113,7 +113,7 @@ struct Dialect; * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ -class UnusedAssignEliminator: public UnusedStoreBase +class UnusedAssignEliminator: public UnusedStoreBase { public: static constexpr char const* name{"UnusedAssignEliminator"}; diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index a3b6c0708b6a..5d50e4599bfd 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -43,7 +43,7 @@ UnusedPruner::UnusedPruner( Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects, + std::map const* _functionSideEffects, std::set const& _externallyUsedFunctions ): m_dialect(_dialect), @@ -55,20 +55,6 @@ UnusedPruner::UnusedPruner( ++m_references[f]; } -UnusedPruner::UnusedPruner( - Dialect const& _dialect, - FunctionDefinition& _function, - bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions -): - m_dialect(_dialect), - m_allowMSizeOptimization(_allowMSizeOptimization) -{ - m_references = ReferencesCounter::countReferences(_function); - for (auto const& f: _externallyUsedFunctions) - ++m_references[f]; -} - void UnusedPruner::operator()(Block& _block) { for (auto&& statement: _block.statements) @@ -95,6 +81,7 @@ void UnusedPruner::operator()(Block& _block) [&](NameWithDebugData const& _typedName) { return used(_typedName.name); } )) { + std::optional discardFunctionHandle = m_dialect.discardFunctionHandle(); if (!varDecl.value) statement = Block{std::move(varDecl.debugData), {}}; else if ( @@ -105,10 +92,10 @@ void UnusedPruner::operator()(Block& _block) subtractReferences(ReferencesCounter::countReferences(*varDecl.value)); statement = Block{std::move(varDecl.debugData), {}}; } - else if (varDecl.variables.size() == 1 && m_dialect.discardFunction()) + else if (varDecl.variables.size() == 1 && discardFunctionHandle) statement = ExpressionStatement{varDecl.debugData, FunctionCall{ varDecl.debugData, - {varDecl.debugData, m_dialect.discardFunction()->name}, + BuiltinName{varDecl.debugData, *discardFunctionHandle}, {*std::move(varDecl.value)} }}; } @@ -135,15 +122,19 @@ void UnusedPruner::runUntilStabilised( Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects, + std::map const* _functionSideEffects, std::set const& _externallyUsedFunctions ) { while (true) { UnusedPruner pruner( - _dialect, _ast, _allowMSizeOptimization, _functionSideEffects, - _externallyUsedFunctions); + _dialect, + _ast, + _allowMSizeOptimization, + _functionSideEffects, + _externallyUsedFunctions + ); pruner(_ast); if (!pruner.shouldRunAgain()) return; @@ -156,34 +147,18 @@ void UnusedPruner::runUntilStabilisedOnFullAST( std::set const& _externallyUsedFunctions ) { - std::map functionSideEffects = + std::map functionSideEffects = SideEffectsPropagator::sideEffects(_dialect, CallGraphGenerator::callGraph(_ast)); bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _ast); runUntilStabilised(_dialect, _ast, allowMSizeOptimization, &functionSideEffects, _externallyUsedFunctions); } -void UnusedPruner::runUntilStabilised( - Dialect const& _dialect, - FunctionDefinition& _function, - bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions -) -{ - while (true) - { - UnusedPruner pruner(_dialect, _function, _allowMSizeOptimization, _externallyUsedFunctions); - pruner(_function); - if (!pruner.shouldRunAgain()) - return; - } -} - bool UnusedPruner::used(YulName _name) const { return m_references.count(_name) && m_references.at(_name) > 0; } -void UnusedPruner::subtractReferences(std::map const& _subtrahend) +void UnusedPruner::subtractReferences(std::map const& _subtrahend) { for (auto const& ref: _subtrahend) { diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index b0ba53bce95c..cd9a7e341d7f 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -30,7 +30,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct SideEffects; /** @@ -52,7 +52,6 @@ class UnusedPruner: public ASTModifier static constexpr char const* name{"UnusedPruner"}; static void run(OptimiserStepContext& _context, Block& _ast); - using ASTModifier::operator(); void operator()(Block& _block) override; @@ -64,19 +63,10 @@ class UnusedPruner: public ASTModifier Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects = nullptr, + std::map const* _functionSideEffects = nullptr, std::set const& _externallyUsedFunctions = {} ); - static void run( - Dialect const& _dialect, - Block& _ast, - std::set const& _externallyUsedFunctions = {} - ) - { - runUntilStabilisedOnFullAST(_dialect, _ast, _externallyUsedFunctions); - } - /// Run the pruner until the code does not change anymore. /// The provided block has to be a full AST. /// The pruner itself determines if msize is used and which user-defined functions @@ -87,41 +77,23 @@ class UnusedPruner: public ASTModifier std::set const& _externallyUsedFunctions = {} ); - // Run the pruner until the code does not change anymore. - // Only run on the given function. - // @param _allowMSizeOptimization if true, allows to remove instructions - // whose only side-effect is a potential change of the return value of - // the msize instruction. - static void runUntilStabilised( - Dialect const& _dialect, - FunctionDefinition& _functionDefinition, - bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions = {} - ); - private: UnusedPruner( Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects = nullptr, - std::set const& _externallyUsedFunctions = {} - ); - UnusedPruner( - Dialect const& _dialect, - FunctionDefinition& _function, - bool _allowMSizeOptimization, + std::map const* _functionSideEffects = nullptr, std::set const& _externallyUsedFunctions = {} ); bool used(YulName _name) const; - void subtractReferences(std::map const& _subtrahend); + void subtractReferences(std::map const& _subtrahend); Dialect const& m_dialect; bool m_allowMSizeOptimization = false; - std::map const* m_functionSideEffects = nullptr; + std::map const* m_functionSideEffects = nullptr; bool m_shouldRunAgain = false; - std::map m_references; + std::map m_references; }; } diff --git a/libyul/optimiser/UnusedStoreBase.cpp b/libyul/optimiser/UnusedStoreBase.cpp index 977db11c4c12..4159b875f39d 100644 --- a/libyul/optimiser/UnusedStoreBase.cpp +++ b/libyul/optimiser/UnusedStoreBase.cpp @@ -32,7 +32,8 @@ using namespace solidity; using namespace solidity::yul; -void UnusedStoreBase::operator()(If const& _if) +template +void UnusedStoreBase::operator()(If const& _if) { visit(*_if.condition); @@ -42,7 +43,8 @@ void UnusedStoreBase::operator()(If const& _if) merge(m_activeStores, std::move(skipBranch)); } -void UnusedStoreBase::operator()(Switch const& _switch) +template +void UnusedStoreBase::operator()(Switch const& _switch) { visit(*_switch.expression); @@ -68,7 +70,8 @@ void UnusedStoreBase::operator()(Switch const& _switch) merge(m_activeStores, std::move(branch)); } -void UnusedStoreBase::operator()(FunctionDefinition const& _functionDefinition) +template +void UnusedStoreBase::operator()(FunctionDefinition const& _functionDefinition) { ScopedSaveAndRestore allStores(m_allStores, {}); ScopedSaveAndRestore usedStores(m_usedStores, {}); @@ -82,7 +85,8 @@ void UnusedStoreBase::operator()(FunctionDefinition const& _functionDefinition) m_storesToRemove += m_allStores - m_usedStores; } -void UnusedStoreBase::operator()(ForLoop const& _forLoop) +template +void UnusedStoreBase::operator()(ForLoop const& _forLoop) { ScopedSaveAndRestore outerForLoopInfo(m_forLoopInfo, {}); ScopedSaveAndRestore forLoopNestingDepth(m_forLoopNestingDepth, m_forLoopNestingDepth + 1); @@ -130,19 +134,22 @@ void UnusedStoreBase::operator()(ForLoop const& _forLoop) m_forLoopInfo.pendingBreakStmts.clear(); } -void UnusedStoreBase::operator()(Break const&) +template +void UnusedStoreBase::operator()(Break const&) { m_forLoopInfo.pendingBreakStmts.emplace_back(std::move(m_activeStores)); m_activeStores.clear(); } -void UnusedStoreBase::operator()(Continue const&) +template +void UnusedStoreBase::operator()(Continue const&) { m_forLoopInfo.pendingContinueStmts.emplace_back(std::move(m_activeStores)); m_activeStores.clear(); } -void UnusedStoreBase::merge(ActiveStores& _target, ActiveStores&& _other) +template +void UnusedStoreBase::merge(ActiveStores& _target, ActiveStores&& _other) { util::joinMap(_target, std::move(_other), []( std::set& _storesHere, @@ -153,9 +160,13 @@ void UnusedStoreBase::merge(ActiveStores& _target, ActiveStores&& _other) }); } -void UnusedStoreBase::merge(ActiveStores& _target, std::vector&& _source) +template +void UnusedStoreBase::merge(ActiveStores& _target, std::vector&& _source) { for (ActiveStores& ts: _source) merge(_target, std::move(ts)); _source.clear(); } + +template class solidity::yul::UnusedStoreBase; +template class solidity::yul::UnusedStoreBase; diff --git a/libyul/optimiser/UnusedStoreBase.h b/libyul/optimiser/UnusedStoreBase.h index b6dde8c5511f..2c51224c0f39 100644 --- a/libyul/optimiser/UnusedStoreBase.h +++ b/libyul/optimiser/UnusedStoreBase.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Base class for both UnusedAssignEliminator and UnusedStoreEliminator. @@ -46,6 +46,7 @@ struct Dialect; * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ +template class UnusedStoreBase: public ASTWalker { public: @@ -60,7 +61,7 @@ class UnusedStoreBase: public ASTWalker void operator()(Continue const&) override; protected: - using ActiveStores = std::map>; + using ActiveStores = std::map>; /// This function is called for a loop that is nested too deep to avoid /// horrible runtime and should just resolve the situation in a pragmatic @@ -98,4 +99,7 @@ class UnusedStoreBase: public ASTWalker size_t m_forLoopNestingDepth = 0; }; +enum class UnusedStoreEliminatorKey { Memory, Storage }; +extern template class UnusedStoreBase; +extern template class UnusedStoreBase; } diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index c50ddac14412..6f2f1ee938f8 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -43,15 +44,9 @@ using namespace solidity; using namespace solidity::yul; -/// Variable names for special constants that can never appear in actual Yul code. -static std::string const zero{"@ 0"}; -static std::string const one{"@ 1"}; -static std::string const thirtyTwo{"@ 32"}; - - void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) { - std::map functionSideEffects = SideEffectsPropagator::sideEffects( + std::map functionSideEffects = SideEffectsPropagator::sideEffects( _context.dialect, CallGraphGenerator::callGraph(_ast) ); @@ -61,12 +56,6 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) std::map values; for (auto const& [name, expression]: ssaValues.values()) values[name] = AssignedValue{expression, {}}; - Expression const zeroLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{0})}}; - Expression const oneLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{1})}}; - Expression const thirtyTwoLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{32})}}; - values[YulName{zero}] = AssignedValue{&zeroLiteral, {}}; - values[YulName{one}] = AssignedValue{&oneLiteral, {}}; - values[YulName{thirtyTwo}] = AssignedValue{&thirtyTwoLiteral, {}}; bool const ignoreMemory = MSizeFinder::containsMSize(_context.dialect, _ast); UnusedStoreEliminator rse{ @@ -93,7 +82,7 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) UnusedStoreEliminator::UnusedStoreEliminator( Dialect const& _dialect, - std::map const& _functionSideEffects, + std::map const& _functionSideEffects, std::map _controlFlowSideEffects, std::map const& _ssaValues, bool _ignoreMemory @@ -101,9 +90,9 @@ UnusedStoreEliminator::UnusedStoreEliminator( UnusedStoreBase(_dialect), m_ignoreMemory(_ignoreMemory), m_functionSideEffects(_functionSideEffects), - m_controlFlowSideEffects(_controlFlowSideEffects), + m_controlFlowSideEffects(std::move(_controlFlowSideEffects)), m_ssaValues(_ssaValues), - m_knowledgeBase(_ssaValues) + m_knowledgeBase(_ssaValues, _dialect) {} void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) @@ -114,10 +103,13 @@ void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) applyOperation(op); ControlFlowSideEffects sideEffects; - if (auto builtin = m_dialect.builtin(_functionCall.functionName.name)) + if (auto builtin = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) sideEffects = builtin->controlFlowSideEffects; else - sideEffects = m_controlFlowSideEffects.at(_functionCall.functionName.name); + { + yulAssert(std::holds_alternative(_functionCall.functionName)); + sideEffects = m_controlFlowSideEffects.at(std::get(_functionCall.functionName).name); + } if (sideEffects.canTerminate) markActiveAsUsed(Location::Storage); @@ -153,7 +145,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement) FunctionCall const* funCall = std::get_if(&exprStatement->expression); yulAssert(funCall); - std::optional instruction = toEVMInstruction(m_dialect, funCall->functionName.name); + std::optional instruction = toEVMInstruction(m_dialect, funCall->functionName); if (!instruction) return; @@ -201,7 +193,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement) if ( m_knowledgeBase.knownToBeZero(*startOffset) && lengthCall && - toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE + toEVMInstruction(m_dialect, lengthCall->functionName) == Instruction::RETURNDATASIZE ) allowReturndatacopyToBeRemoved = true; } @@ -228,14 +220,16 @@ std::vector UnusedStoreEliminator::operationsF { using evmasm::Instruction; - YulName functionName = _functionCall.functionName.name; SideEffects sideEffects; - if (BuiltinFunction const* f = m_dialect.builtin(functionName)) + if (BuiltinFunction const* f = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) sideEffects = f->sideEffects; else - sideEffects = m_functionSideEffects.at(functionName); + { + yulAssert(std::holds_alternative(_functionCall.functionName)); + sideEffects = m_functionSideEffects.at(std::get(_functionCall.functionName).name); + } - std::optional instruction = toEVMInstruction(m_dialect, functionName); + std::optional instruction = toEVMInstruction(m_dialect, _functionCall.functionName); if (!instruction) { std::vector result; @@ -263,8 +257,8 @@ std::vector UnusedStoreEliminator::operationsF if (_op.lengthConstant) switch (*_op.lengthConstant) { - case 1: ourOp.length = YulName(one); break; - case 32: ourOp.length = YulName(thirtyTwo); break; + case 1: ourOp.length = u256(1); break; + case 32: ourOp.length = u256(32); break; default: yulAssert(false); } return ourOp; @@ -312,8 +306,8 @@ bool UnusedStoreEliminator::knownUnrelated( yulAssert( _op1.length && _op2.length && - m_knowledgeBase.valueIfKnownConstant(*_op1.length) == 1 && - m_knowledgeBase.valueIfKnownConstant(*_op2.length) == 1 + lengthValue(*_op1.length) == 1 && + lengthValue(*_op2.length) == 1 ); return m_knowledgeBase.knownToBeDifferent(*_op1.start, *_op2.start); } @@ -322,14 +316,14 @@ bool UnusedStoreEliminator::knownUnrelated( { yulAssert(_op1.location == Location::Memory, ""); if ( - (_op1.length && m_knowledgeBase.knownToBeZero(*_op1.length)) || - (_op2.length && m_knowledgeBase.knownToBeZero(*_op2.length)) + (_op1.length && lengthValue(*_op1.length) == 0) || + (_op2.length && lengthValue(*_op2.length) == 0) ) return true; if (_op1.start && _op1.length && _op2.start) { - std::optional length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length); + std::optional length1 = lengthValue(*_op1.length); std::optional start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start); std::optional start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start); if ( @@ -341,7 +335,7 @@ bool UnusedStoreEliminator::knownUnrelated( } if (_op2.start && _op2.length && _op1.start) { - std::optional length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length); + std::optional length2 = lengthValue(*_op2.length); std::optional start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start); std::optional start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start); if ( @@ -354,8 +348,8 @@ bool UnusedStoreEliminator::knownUnrelated( if (_op1.start && _op1.length && _op2.start && _op2.length) { - std::optional length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length); - std::optional length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length); + std::optional length1 = lengthValue(*_op1.length); + std::optional length2 = lengthValue(*_op2.length); if ( (length1 && *length1 <= 32) && (length2 && *length2 <= 32) && @@ -382,15 +376,15 @@ bool UnusedStoreEliminator::knownCovered( return true; if (_covered.location == Location::Memory) { - if (_covered.length && m_knowledgeBase.knownToBeZero(*_covered.length)) + if (_covered.length && lengthValue(*_covered.length) == 0) return true; // Condition (i = cover_i_ng, e = cover_e_d): // i.start <= e.start && e.start + e.length <= i.start + i.length if (!_covered.start || !_covering.start || !_covered.length || !_covering.length) return false; - std::optional coveredLength = m_knowledgeBase.valueIfKnownConstant(*_covered.length); - std::optional coveringLength = m_knowledgeBase.valueIfKnownConstant(*_covering.length); + std::optional coveredLength = lengthValue(*_covered.length); + std::optional coveringLength = lengthValue(*_covering.length); if (*_covered.start == *_covering.start) if (coveredLength && coveringLength && *coveredLength <= *coveringLength) return true; diff --git a/libyul/optimiser/UnusedStoreEliminator.h b/libyul/optimiser/UnusedStoreEliminator.h index 98023b64cfc6..45d363dfc9fc 100644 --- a/libyul/optimiser/UnusedStoreEliminator.h +++ b/libyul/optimiser/UnusedStoreEliminator.h @@ -36,7 +36,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct AssignedValue; /** @@ -50,13 +50,11 @@ struct AssignedValue; * to sstore, as we don't know whether the memory location will be read once we leave the function's scope, * so the statement will be removed only if all code code paths lead to a memory overwrite. * - * The m_store member of UnusedStoreBase uses the key "m" for memory and "s" for storage stores. - * * Best run in SSA form. * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ -class UnusedStoreEliminator: public UnusedStoreBase +class UnusedStoreEliminator: public UnusedStoreBase { public: static constexpr char const* name{"UnusedStoreEliminator"}; @@ -64,7 +62,7 @@ class UnusedStoreEliminator: public UnusedStoreBase explicit UnusedStoreEliminator( Dialect const& _dialect, - std::map const& _functionSideEffects, + std::map const& _functionSideEffects, std::map _controlFlowSideEffects, std::map const& _ssaValues, bool _ignoreMemory @@ -80,6 +78,7 @@ class UnusedStoreEliminator: public UnusedStoreBase using Location = evmasm::SemanticInformation::Location; using Effect = evmasm::SemanticInformation::Effect; + using OperationLength = std::variant; struct Operation { Location location; @@ -88,12 +87,19 @@ class UnusedStoreEliminator: public UnusedStoreBase std::optional start; /// Length of affected area, unknown if not provided. /// Unused for storage. - std::optional length; + std::optional length; }; private: - std::set& activeMemoryStores() { return m_activeStores["m"_yulname]; } - std::set& activeStorageStores() { return m_activeStores["s"_yulname]; } + std::set& activeMemoryStores() { return m_activeStores[UnusedStoreEliminatorKey::Memory]; } + std::set& activeStorageStores() { return m_activeStores[UnusedStoreEliminatorKey::Storage]; } + std::optional lengthValue(OperationLength const& _length) const + { + if (YulName const* length = std::get_if(&_length)) + return m_knowledgeBase.valueIfKnownConstant(*length); + else + return std::get(_length); + } void shortcutNestedLoop(ActiveStores const&) override { @@ -116,7 +122,7 @@ class UnusedStoreEliminator: public UnusedStoreBase std::optional identifierNameIfSSA(Expression const& _expression) const; bool const m_ignoreMemory; - std::map const& m_functionSideEffects; + std::map const& m_functionSideEffects; std::map m_controlFlowSideEffects; std::map const& m_ssaValues; diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index b3a34d283e7e..8d34ce85e408 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -111,7 +111,7 @@ YulName VarNameCleaner::findCleanName(YulName const& _name) const bool VarNameCleaner::isUsedName(YulName const& _name) const { - return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); + return isRestrictedIdentifier(m_dialect, _name.str()) || m_usedNames.contains(_name); } YulName VarNameCleaner::stripSuffix(YulName const& _name) const diff --git a/libyul/optimiser/VarNameCleaner.h b/libyul/optimiser/VarNameCleaner.h index 7f8bb842e9e1..47f3aca48db9 100644 --- a/libyul/optimiser/VarNameCleaner.h +++ b/libyul/optimiser/VarNameCleaner.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Pass to normalize identifier suffixes. diff --git a/scripts/Dockerfile b/scripts/Dockerfile index 3a1c6a5a7cf9..6df9337ec862 100644 --- a/scripts/Dockerfile +++ b/scripts/Dockerfile @@ -6,7 +6,7 @@ MAINTAINER chriseth WORKDIR /solidity # Build dependencies -RUN apk update && apk add boost-dev boost-static build-base cmake git +RUN apk update && apk add boost-dev boost-static build-base cmake git clang #Copy working directory on travis to the image COPY / $WORKDIR @@ -17,7 +17,7 @@ ARG BUILD_CONCURRENCY="0" #Install dependencies, eliminate annoying warnings RUN sed -i -E -e 's/include /include /' /usr/include/boost/asio/detail/socket_types.hpp -RUN cmake -DCMAKE_BUILD_TYPE=Release -DTESTS=0 -DSOLC_LINK_STATIC=1 +RUN cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DTESTS=0 -DSOLC_LINK_STATIC=1 RUN make solc \ -j$(awk "BEGIN { \ if (${BUILD_CONCURRENCY} != 0) { \ diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index dc862b1f7efc..93556a557e09 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -33,9 +33,9 @@ if (( $# != 0 )); then params="$(printf "%q " "${@}")" fi -# solbuildpackpusher/solidity-buildpack-deps:emscripten-17 +# solbuildpackpusher/solidity-buildpack-deps:emscripten-20` # NOTE: Without `safe.directory` git would assume it's not safe to operate on /root/project since it's owned by a different user. # See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run -v "$(pwd):/root/project" -w /root/project \ - solbuildpackpusher/solidity-buildpack-deps@sha256:c57f2bfb8c15d70fe290629358dd1c73dc126e3760f443b54764797556b887d4 \ + solbuildpackpusher/solidity-buildpack-deps@sha256:98f963ed799a0d206ef8e7b5475f847e0dea53b7fdea9618bbc6106a62730bd2 \ /bin/bash -c "git config --global --add safe.directory /root/project && ./scripts/ci/build_emscripten.sh ${params}" diff --git a/scripts/bytecodecompare/prepare_report.js b/scripts/bytecodecompare/prepare_report.js index 821b5cb750eb..96bd3c1eebfa 100755 --- a/scripts/bytecodecompare/prepare_report.js +++ b/scripts/bytecodecompare/prepare_report.js @@ -4,7 +4,7 @@ const fs = require('fs') const compiler = require('solc') -SETTINGS_PRESETS = { +const SETTINGS_PRESETS = { 'legacy-optimize': {optimize: true, viaIR: false}, 'legacy-no-optimize': {optimize: false, viaIR: false}, 'via-ir-optimize': {optimize: true, viaIR: true}, diff --git a/scripts/ci/build_emscripten.sh b/scripts/ci/build_emscripten.sh index 04e16293fd96..e4d25f195fb7 100755 --- a/scripts/ci/build_emscripten.sh +++ b/scripts/ci/build_emscripten.sh @@ -37,12 +37,13 @@ set -ev SCRIPT_DIR="$(realpath "$(dirname "$0")/..")" # shellcheck source=scripts/common.sh source "${SCRIPT_DIR}/common.sh" +ROOT_DIR="${SCRIPT_DIR}/.." function build() { local build_dir="$1" local prerelease_source="${2:-ci}" - cd /root/project + cd "${ROOT_DIR}" # shellcheck disable=SC2166 if [[ "$CIRCLE_BRANCH" = release || -n "$CIRCLE_TAG" || -n "$FORCE_RELEASE" || "$(git tag --points-at HEAD 2>/dev/null)" == v* ]] diff --git a/scripts/ci/build_ossfuzz.sh b/scripts/ci/build_ossfuzz.sh index 1240b6877f1a..64d992994ed6 100755 --- a/scripts/ci/build_ossfuzz.sh +++ b/scripts/ci/build_ossfuzz.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -ex -ROOTDIR="/root/project" +ROOTDIR="$(realpath "$(dirname "$0")/../..")" BUILDDIR="${ROOTDIR}/build" mkdir -p "${BUILDDIR}" && mkdir -p "$BUILDDIR/deps" @@ -18,7 +18,7 @@ function generate_protobuf_bindings function build_fuzzers { cd "${BUILDDIR}" - cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" \ + cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" -DCCACHE=OFF \ -DCMAKE_TOOLCHAIN_FILE="${ROOTDIR}"/cmake/toolchains/libfuzzer.cmake make ossfuzz ossfuzz_proto ossfuzz_abiv2 -j 4 } diff --git a/scripts/ci/buildpack-deps_test_ubuntu2004.sh b/scripts/ci/buildpack-deps_test_ubuntu2004.sh deleted file mode 120000 index feb6a5927fc0..000000000000 --- a/scripts/ci/buildpack-deps_test_ubuntu2004.sh +++ /dev/null @@ -1 +0,0 @@ -./build.sh \ No newline at end of file diff --git a/scripts/ci/buildpack-deps_test_ubuntu2204.sh b/scripts/ci/buildpack-deps_test_ubuntu2204.sh new file mode 120000 index 000000000000..c07a74de4fb4 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu2204.sh @@ -0,0 +1 @@ +build.sh \ No newline at end of file diff --git a/scripts/ci/docker_upgrade.sh b/scripts/ci/docker_upgrade.sh index a6b59e157e90..c2077239a5b6 100755 --- a/scripts/ci/docker_upgrade.sh +++ b/scripts/ci/docker_upgrade.sh @@ -51,17 +51,12 @@ docker build "scripts/docker/${IMAGE_NAME}" --file "scripts/docker/${IMAGE_NAME} echo "-- test_docker @ '${PWD}'" -# NOTE: Since /root/project/ is a dir from outside the container and the owner of the files is different, -# git show in the script refuses to work. It must be marked as safe to use first. -# See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run \ --rm \ - --volume "${PWD}:/root/project" \ + --volume "${PWD}:/project" \ + -u "$(id -u "${USER}"):$(id -g "${USER}")" \ "${IMAGE_NAME}" \ - bash -c " - git config --global --add safe.directory /root/project && - /root/project/scripts/ci/${IMAGE_NAME}_test_${IMAGE_VARIANT}.sh - " + bash -c "/project/scripts/ci/${IMAGE_NAME}_test_${IMAGE_VARIANT}.sh" echo "-- push_docker" diff --git a/scripts/codespell_ignored_lines.txt b/scripts/codespell_ignored_lines.txt index b7987cc001aa..fe99c9f24651 100644 --- a/scripts/codespell_ignored_lines.txt +++ b/scripts/codespell_ignored_lines.txt @@ -18,3 +18,5 @@ docker run --rm -v "${OUTPUTDIR}":/tmp/output -v "${SCRIPTDIR}":/tmp/scripts:ro templ("assignEnd", "end := pos"); templ("assignEnd", "end := tail"); templ("assignEnd", ""); + self.assertIn('401 Client Error: Unauthorized', str(manager.exception)) + a = abd; diff --git a/scripts/codespell_whitelist.txt b/scripts/codespell_whitelist.txt index 7de8a42fe521..7bcbf6ad14fb 100644 --- a/scripts/codespell_whitelist.txt +++ b/scripts/codespell_whitelist.txt @@ -1,3 +1,4 @@ nd compilability keypair +wast diff --git a/scripts/common_cmdline.sh b/scripts/common_cmdline.sh index 819a4b1c8eaf..51d30ae5d191 100644 --- a/scripts/common_cmdline.sh +++ b/scripts/common_cmdline.sh @@ -152,6 +152,7 @@ function stripCLIDecorations -e '/^IR:$/d' \ -e '/^Optimized IR:$/d' \ -e '/^EVM assembly:$/d' \ + -e '/^Yul Control Flow Graph:$/d' \ -e '/^JSON AST (compact format):$/d' \ -e '/^Function signatures:$/d' \ -e '/^Contract Storage Layout:$/d' \ diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh index 9e273188cf62..140c40c6abb3 100755 --- a/scripts/deps-ppa/static_z3.sh +++ b/scripts/deps-ppa/static_z3.sh @@ -41,7 +41,7 @@ sourcePPAConfig # Sanity check checkDputEntries "\[cpp-build-deps\]" -DISTRIBUTIONS="focal jammy noble oracular" +DISTRIBUTIONS="jammy noble oracular" for distribution in $DISTRIBUTIONS do diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index c63c2a116174..d8eb9a903f52 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -37,12 +37,19 @@ LABEL version="20" ADD emscripten.jam /usr/src RUN set -ex && \ - \ apt-get update && \ - apt-get install lz4 sudo --no-install-recommends && \ - \ + apt-get install -qqy --no-install-recommends \ + lsof \ + lz4 \ + python3 \ + python3-pip \ + sudo && \ + pip3 install requests; + +# Install Z3 +RUN set -ex && \ cd /usr/src && \ - git clone https://github.com/Z3Prover/z3.git -b z3-4.12.1 --depth 1 && \ + git clone https://github.com/Z3Prover/z3.git -b z3-4.13.3 --depth 1 && \ cd z3 && \ mkdir build && \ cd build && \ @@ -58,7 +65,10 @@ RUN set -ex && \ .. && \ make && \ make install && \ - rm -r /usr/src/z3 && \ + rm -r /usr/src/z3 + +# Install Boost +RUN set -ex && \ cd /usr/src && \ wget -q 'https://archives.boost.io/release/1.75.0/source/boost_1_75_0.tar.bz2' -O boost.tar.bz2 && \ test "$(sha256sum boost.tar.bz2)" = "953db31e016db7bb207f11432bef7df100516eeb746843fa0486a222e3fd49cb boost.tar.bz2" && \ @@ -73,3 +83,12 @@ RUN set -ex && \ cxxflags="-s DISABLE_EXCEPTION_CATCHING=0 -Wno-unused-local-typedef -Wno-variadic-macros -Wno-c99-extensions -Wno-all" \ --prefix=$(em-config CACHE)/sysroot/usr install && \ rm -r /usr/src/boost_1_75_0 + +# CVC5 +RUN set -ex; \ + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 7a20bdbc5e66..bf228d6176fb 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -21,68 +21,118 @@ # # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ -FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="8" +FROM gcr.io/oss-fuzz-base/base-builder AS base +LABEL version="10" ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update; \ apt-get -qqy install --no-install-recommends \ - build-essential sudo \ + automake \ + bison \ + build-essential \ + curl \ + git \ + jq \ + libbz2-dev \ + libc++-18-dev \ + libc++abi-18-dev \ + liblzma-dev \ + libtool \ + lsof \ + m4 \ + mlton \ + ninja-build \ + openjdk-8-jdk \ + pkg-config \ + python3-pip \ + python3-dev \ 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 jq; \ - apt-get install -qy python3-pip; + sudo \ + texinfo \ + unzip \ + uuid-dev \ + wget \ + zlib1g-dev; \ + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate; -# Install cmake 3.21.2 (minimum requirement is cmake 3.10) -RUN wget https://github.com/Kitware/CMake/releases/download/v3.21.2/cmake-3.21.2-Linux-x86_64.sh; \ - test "$(sha256sum cmake-3.21.2-Linux-x86_64.sh)" = "3310362c6fe4d4b2dc00823835f3d4a7171bbd73deb7d059738494761f1c908c cmake-3.21.2-Linux-x86_64.sh"; \ - chmod +x cmake-3.21.2-Linux-x86_64.sh; \ - ./cmake-3.21.2-Linux-x86_64.sh --skip-license --prefix="/usr" +# Ensure that the expected version of Clang is installed, as the base image may update it in the future: +# https://github.com/google/oss-fuzz/blob/5e96edbdf285045cc82dbca5600cbe994a3b1a74/infra/base-images/base-clang/checkout_build_install_llvm.sh#L57 +RUN test "$(clang -dumpversion | cut -d. -f1)" = "18" || (echo "Error: Clang 18 not found!" && exit 1) FROM base AS libraries # Boost RUN set -ex; \ - cd /usr/src; \ - wget -q 'https://archives.boost.io/release/1.74.0/source/boost_1_74_0.tar.bz2' -O boost.tar.bz2; \ - test "$(sha256sum boost.tar.bz2)" = "83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1 boost.tar.bz2" && \ - tar -xf boost.tar.bz2; \ - rm boost.tar.bz2; \ - cd boost_1_74_0; \ - CXXFLAGS="-stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ - ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" headers; \ - ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" \ - link=static variant=release runtime-link=static \ - system filesystem unit_test_framework program_options \ - install -j $(($(nproc)/2)); \ - rm -rf /usr/src/boost_1_74_0 + cd /usr/src; \ + wget -q 'https://archives.boost.io/release/1.83.0/source/boost_1_83_0.tar.bz2' -O boost.tar.bz2; \ + test "$(sha256sum boost.tar.bz2)" = "6478edfe2f3305127cffe8caf73ea0176c53769f4bf1585be237eb30798c3b8e boost.tar.bz2" && \ + tar -xf boost.tar.bz2; \ + rm boost.tar.bz2; \ + cd boost_1_83_0; \ + export CXXFLAGS="-std=c++20 -nostdinc++ -I/usr/lib/llvm-18/include/c++/v1 -pthread"; \ + export LDFLAGS="-stdlib=libc++ -L/usr/lib/llvm-18/lib"; \ + ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ + ./b2 toolset=clang \ + cxxflags="${CXXFLAGS}" \ + linkflags="${LDFLAGS}" \ + headers; \ + ./b2 toolset=clang \ + cxxflags="${CXXFLAGS}" \ + linkflags="${LDFLAGS}" \ + link=static variant=release runtime-link=static \ + system filesystem unit_test_framework program_options \ + install -j $(($(nproc)/2)); \ + rm -rf /usr/src/boost_1_83_0 # Z3 RUN set -ex; \ - git clone --depth 1 -b z3-4.12.1 https://github.com/Z3Prover/z3.git \ - /usr/src/z3; \ - cd /usr/src/z3; \ - mkdir build; \ - cd build; \ - LDFLAGS=$CXXFLAGS cmake -DZ3_BUILD_LIBZ3_SHARED=OFF -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_BUILD_TYPE=Release ..; \ - make libz3 -j; \ - make install; \ - rm -rf /usr/src/z3 + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; + +# Eldarica +RUN set -ex; \ + apt-get update; \ + apt-get install -qqy openjdk-11-jre; \ + eldarica_version="2.1"; \ + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ + unzip /opt/eld_binaries.zip -d /opt; \ + rm -f /opt/eld_binaries.zip; + +# CVC5 +RUN set -ex; \ + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; # OSSFUZZ: libprotobuf-mutator +# Use commit prior to libprotobuf upgrade that broke solidity build +# See https://github.com/google/oss-fuzz/issues/10237 RUN set -ex; \ - git clone https://github.com/google/libprotobuf-mutator.git \ - /usr/src/libprotobuf-mutator; \ + git clone https://github.com/google/libprotobuf-mutator.git /usr/src/libprotobuf-mutator; \ cd /usr/src/libprotobuf-mutator; \ - git checkout 3521f47a2828da9ace403e4ecc4aece1a84feb36; \ + git reset --hard 212a7be1eb08e7f9c79732d2aab9b2097085d936; \ mkdir build; \ cd build; \ cmake .. -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON \ - -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX="/usr"; \ + -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="/usr"; \ ninja; \ cp -vpr external.protobuf/bin/* /usr/bin/; \ cp -vpr external.protobuf/include/* /usr/include/; \ @@ -93,46 +143,54 @@ RUN set -ex; \ # EVMONE RUN set -ex; \ cd /usr/src; \ - git clone --branch="v0.10.0" --recurse-submodules https://github.com/ethereum/evmone.git; \ + git clone --branch="v0.13.0" --recurse-submodules https://github.com/ethereum/evmone.git; \ cd evmone; \ mkdir build; \ cd build; \ - CXX=clang++ cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="/usr" ..; \ + CXX=clang++ cmake .. -G Ninja \ + -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-stdlib=libc++" \ + -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="/usr"; \ ninja; \ ninja install/strip; \ rm -rf /usr/src/evmone # gmp RUN set -ex; \ - # Replace system installed libgmp static library - # with sanitized version. Do not perform apt - # remove because it removes mlton as well that - # we need for building libabicoder - rm -f /usr/lib/x86_64-linux-gnu/libgmp.*; \ - rm -f /usr/include/x86_64-linux-gnu/gmp.h; \ - cd /usr/src; \ - wget -q 'https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz' -O gmp.tar.xz; \ - test "$(sha256sum gmp.tar.xz)" = "fd4829912cddd12f84181c3451cc752be224643e87fac497b69edddadc49b4f2 gmp.tar.xz"; \ - tar -xf gmp.tar.xz; \ - cd gmp-6.2.1; \ - ./configure --prefix=/usr --enable-static=yes; \ - make -j; \ - make install; \ - rm -rf /usr/src/gmp-6.2.1; \ - rm -f /usr/src/gmp.tar.xz + # Replace system installed libgmp static library + # with sanitized version. Do not perform apt + # remove because it removes mlton as well that + # we need for building libabicoder + cd /usr/src/; \ + git clone --depth 1 --branch gmp-6.2.1 https://github.com/gmp-mirror/gmp-6.2 gmp/; \ + rm -r gmp/.git/; \ + test \ + "$(tar --create gmp/ --sort=name --mtime=1970-01-01Z --owner=0 --group=0 --numeric-owner | sha256sum)" = \ + "d606ff6a4ce98692f9920031e85ea8fcf4a65ce1426f6f0048b8794aefed174b -"; \ + # NOTE: This removes also libgmp.so, which git depends on + rm -f /usr/lib/x86_64-linux-gnu/libgmp.*; \ + rm -f /usr/include/x86_64-linux-gnu/gmp.h; \ + cd gmp/; \ + autoreconf -i; \ + ./configure --prefix=/usr --enable-static=yes --enable-maintainer-mode; \ + make -j; \ + make check; \ + make install; \ + rm -rf /usr/src/gmp/ # libabicoder RUN set -ex; \ - cd /usr/src; \ - git clone https://github.com/ekpyron/Yul-Isabelle; \ - cd Yul-Isabelle; \ - cd libabicoder; \ - CXX=clang++ CXXFLAGS="-stdlib=libc++ -pthread" make; \ - cp libabicoder.a /usr/lib; \ - cp abicoder.hpp /usr/include; \ - rm -rf /usr/src/Yul-Isabelle + cd /usr/src; \ + git clone https://github.com/ekpyron/Yul-Isabelle; \ + cd Yul-Isabelle; \ + cd libabicoder; \ + CXX=clang++ CXXFLAGS="-stdlib=libc++ -pthread" make; \ + cp libabicoder.a /usr/lib; \ + cp abicoder.hpp /usr/include; \ + rm -rf /usr/src/Yul-Isabelle FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 similarity index 69% rename from scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 rename to scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 723192e2d0c4..f66c1d8fd07f 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -1,7 +1,7 @@ # vim:syntax=dockerfile #------------------------------------------------------------------------------ # Dockerfile for building and testing Solidity Compiler on CI -# Target: Ubuntu 19.04 (Disco Dingo) +# Target: Ubuntu 22.04 (Jammy Jellyfish) # URL: https://hub.docker.com/r/ethereum/solidity-buildpack-deps # # This file is part of solidity. @@ -19,10 +19,10 @@ # You should have received a copy of the GNU General Public License # along with solidity. If not, see # -# (c) 2016-2019 solidity contributors. +# (c) 2016-2025 solidity contributors. #------------------------------------------------------------------------------ -FROM buildpack-deps:focal AS base -LABEL version="25" +FROM buildpack-deps:jammy AS base +LABEL version="2" ARG DEBIAN_FRONTEND=noninteractive @@ -35,11 +35,13 @@ RUN set -ex; \ build-essential \ cmake \ jq \ + clang \ libboost-filesystem-dev \ libboost-program-options-dev \ libboost-system-dev \ libboost-test-dev \ - libz3-static-dev \ + libcln-dev \ + locales-all \ lsof \ ninja-build \ python3-pip \ @@ -47,7 +49,7 @@ RUN set -ex; \ software-properties-common \ sudo \ unzip \ - z3-static; \ + zip; \ pip3 install \ codecov \ colorama \ @@ -59,10 +61,6 @@ RUN set -ex; \ tabulate \ z3-solver; -# TODO: we could eliminate duplication by using a Dockerfile extension like: -# https://github.com/edrevo/dockerfile-plus?tab=readme-ov-file#dockerfile -# or mult-stage builds, then we could define a base image which would be included/used by all the other Dockerfiles. -# Or we could move the common parts to a shell script, copying and calling it from the Dockerfiles. # Eldarica RUN set -ex; \ apt-get update; \ @@ -76,21 +74,28 @@ RUN set -ex; \ # CVC5 RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; + +# Z3 +RUN set -ex; \ + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; FROM base AS libraries # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 index c7ad4594aab8..fc372c709ae2 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="1" +LABEL version="3" ARG DEBIAN_FRONTEND=noninteractive @@ -44,7 +44,6 @@ RUN set -ex; \ libboost-system-dev \ libboost-test-dev \ libcln-dev \ - libz3-static-dev \ locales-all \ lsof \ ninja-build \ @@ -53,7 +52,6 @@ RUN set -ex; \ software-properties-common \ sudo \ unzip \ - z3-static \ zip; \ pip3 install \ codecov \ @@ -79,21 +77,28 @@ RUN set -ex; \ # CVC5 RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; + +# Z3 +RUN set -ex; \ + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; FROM base AS libraries # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index 21092e312a7c..91a31c26300a 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="2" +LABEL version="4" ARG DEBIAN_FRONTEND=noninteractive @@ -46,13 +46,11 @@ RUN set -ex; \ libboost-test-dev \ libclang-rt-dev \ libcln-dev \ - libz3-static-dev \ lsof \ ninja-build \ python3-pip \ software-properties-common \ - sudo \ - z3-static; \ + sudo; \ pip3 install \ codecov \ colorama \ @@ -78,14 +76,21 @@ RUN set -ex; \ # CVC5 RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; + +# Z3 +RUN set -ex; \ + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; FROM base AS libraries @@ -94,8 +99,8 @@ ENV CXX clang++ # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz diff --git a/scripts/docker/buildpack-deps/README.md b/scripts/docker/buildpack-deps/README.md index 15cb71f5be8c..9cfcafd4bf27 100644 --- a/scripts/docker/buildpack-deps/README.md +++ b/scripts/docker/buildpack-deps/README.md @@ -4,7 +4,7 @@ The `buildpack-deps` docker images are used to compile and test solidity within ## GitHub Workflow -The creation of the images are triggered by a single workflow, defined in `.github/workflows/buildpack-deps.yml`. +The creation of the images is triggered by a single workflow, defined in `.github/workflows/buildpack-deps.yml`. For each resulting `buildpack-deps` docker image a strategy is defined in the workflow file - the image variant. The workflow gets triggered, if any Dockerfile defined in `scripts/docker/buildpack-deps/Dockerfile.*` were changed within the PR. diff --git a/scripts/docker/buildpack-deps/emscripten.jam b/scripts/docker/buildpack-deps/emscripten.jam index bc8f0fa00eb4..21768524f5d0 100644 --- a/scripts/docker/buildpack-deps/emscripten.jam +++ b/scripts/docker/buildpack-deps/emscripten.jam @@ -25,7 +25,7 @@ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # -# Boost.Build support for Emscipten. +# Boost.Build support for Emscripten. # # @todo add support for dynamic linking # @todo add support for --js-library, --pre-js, and --post-js options diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 8753d59c9a2d..1386bcfa177e 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -47,13 +47,13 @@ function tag_and_push } rm -rf .git -docker build -t "$image":build -f scripts/Dockerfile . --progress plain +docker buildx build -t "$image":build -f scripts/Dockerfile . --progress=plain tmp_container=$(docker create "$image":build sh) # Alpine image mkdir -p upload docker cp "${tmp_container}":/usr/bin/solc upload/solc-static-linux -docker build -t "$image":build-alpine -f scripts/Dockerfile_alpine . --progress plain +docker buildx build -t "$image":build-alpine -f scripts/Dockerfile_alpine . --progress=plain if [ "$branch" = "develop" ] then diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 813d08330e31..71206ac43f8f 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -205,8 +205,10 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "7053", # Unimplemented feature error (parsing stage), currently has no tests "2339", # SMTChecker, covered by CL tests "6240", # SMTChecker, covered by CL tests + "2788", # SMTChecker: BMC: verification condition(s) could not be proved "1733", # AsmAnalysis: expecting bool expression (everything is implicitly bool without types in Yul) "9547", # AsmAnalysis: assigning incompatible types in Yul (whitelisted as there are currently no types) + "5026", # ContractLevelChecker: too difficult to exceed transient storage max size due to only value types supported. } assert len(test_ids & white_ids) == 0, "The sets are not supposed to intersect" test_ids |= white_ids @@ -245,7 +247,6 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "4802", "4902", "5272", - "5622", "5798", "5840", "7128", diff --git a/scripts/install_evmone.ps1 b/scripts/install_evmone.ps1 index 7295afa01ee3..53fc7b6eee9e 100644 --- a/scripts/install_evmone.ps1 +++ b/scripts/install_evmone.ps1 @@ -3,6 +3,6 @@ $ErrorActionPreference = "Stop" # Needed for Invoke-WebRequest to work via CI. $progressPreference = "silentlyContinue" -Invoke-WebRequest -URI "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-windows-amd64.zip" -OutFile "evmone.zip" +Invoke-WebRequest -URI "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip" -OutFile "evmone.zip" tar -xf evmone.zip "bin/evmone.dll" mv bin/evmone.dll deps/ diff --git a/scripts/pylintrc b/scripts/pylintrc index 5ef5a6eff333..191e803861e2 100644 --- a/scripts/pylintrc +++ b/scripts/pylintrc @@ -29,6 +29,7 @@ disable= too-many-branches, too-many-instance-attributes, too-many-locals, + too-many-positional-arguments, too-many-public-methods, too-many-statements, ungrouped-imports diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 773c43cc9968..cf8df3d6c47d 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -66,9 +66,9 @@ sourcePPAConfig packagename=solc # This needs to be a still active release -static_build_distribution=focal +static_build_distribution=noble -DISTRIBUTIONS="focal jammy noble oracular" +DISTRIBUTIONS="jammy noble oracular" if is_release then diff --git a/scripts/tests.sh b/scripts/tests.sh index dfbc0477342d..3d2849369eca 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -105,7 +105,7 @@ EVM_VERSIONS="homestead byzantium" if [ -z "$CI" ] then - EVM_VERSIONS+=" constantinople petersburg istanbul berlin london paris shanghai cancun prague" + EVM_VERSIONS+=" constantinople petersburg istanbul berlin london paris shanghai cancun prague osaka" fi # And then run the Solidity unit-tests in the matrix combination of optimizer / no optimizer diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 442fbecd2e3b..913accd8bde1 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -43,6 +43,7 @@ #include +#include #include #include @@ -118,7 +119,6 @@ std::ostream& CommandLineInterface::serr(bool _markAsUsed) static std::string const g_stdinFileName = ""; static std::string const g_strAbi = "abi"; static std::string const g_strAsm = "asm"; -static std::string const g_strAst = "ast"; static std::string const g_strBinary = "bin"; static std::string const g_strBinaryRuntime = "bin-runtime"; static std::string const g_strContracts = "contracts"; @@ -148,8 +148,11 @@ static bool needsHumanTargetedStdout(CommandLineOptions const& _options) _options.compiler.outputs.abi || _options.compiler.outputs.asm_ || _options.compiler.outputs.asmJson || + _options.compiler.outputs.yulCFGJson || _options.compiler.outputs.binary || _options.compiler.outputs.binaryRuntime || + _options.compiler.outputs.ethdebug || + _options.compiler.outputs.ethdebugRuntime || _options.compiler.outputs.metadata || _options.compiler.outputs.natspecUser || _options.compiler.outputs.natspecDev || @@ -257,12 +260,13 @@ void CommandLineInterface::handleIR(std::string const& _contractName) if (!m_options.compiler.outputs.ir) return; + std::optional const& ir = m_compiler->yulIR(_contractName); if (!m_options.output.dir.empty()) - createFile(m_compiler->filesystemFriendlyName(_contractName) + ".yul", m_compiler->yulIR(_contractName)); + createFile(m_compiler->filesystemFriendlyName(_contractName) + ".yul", ir.value_or("")); else { - sout() << "IR:" << std::endl; - sout() << m_compiler->yulIR(_contractName) << std::endl; + sout() << "IR:\n"; + sout() << ir.value_or("") << std::endl; } } @@ -273,11 +277,12 @@ void CommandLineInterface::handleIRAst(std::string const& _contractName) if (!m_options.compiler.outputs.irAstJson) return; + std::optional const& yulIRAst = m_compiler->yulIRAst(_contractName); if (!m_options.output.dir.empty()) createFile( m_compiler->filesystemFriendlyName(_contractName) + "_yul_ast.json", util::jsonPrint( - m_compiler->yulIRAst(_contractName), + yulIRAst.value_or(Json{}), m_options.formatting.json ) ); @@ -285,7 +290,7 @@ void CommandLineInterface::handleIRAst(std::string const& _contractName) { sout() << "IR AST:" << std::endl; sout() << util::jsonPrint( - m_compiler->yulIRAst(_contractName), + yulIRAst.value_or(Json{}), m_options.formatting.json ) << std::endl; } @@ -298,18 +303,20 @@ void CommandLineInterface::handleYulCFGExport(std::string const& _contractName) if (!m_options.compiler.outputs.yulCFGJson) return; + std::optional const& yulCFGJson = m_compiler->yulCFGJson(_contractName); if (!m_options.output.dir.empty()) createFile( m_compiler->filesystemFriendlyName(_contractName) + "_yul_cfg.json", util::jsonPrint( - m_compiler->yulCFGJson(_contractName), + yulCFGJson.value_or(Json{}), m_options.formatting.json ) ); else { + sout() << "Yul Control Flow Graph:" << std::endl; sout() << util::jsonPrint( - m_compiler->yulCFGJson(_contractName), + yulCFGJson.value_or(Json{}), m_options.formatting.json ) << std::endl; } @@ -322,15 +329,16 @@ void CommandLineInterface::handleIROptimized(std::string const& _contractName) if (!m_options.compiler.outputs.irOptimized) return; + std::optional const& irOptimized = m_compiler->yulIROptimized(_contractName); if (!m_options.output.dir.empty()) createFile( m_compiler->filesystemFriendlyName(_contractName) + "_opt.yul", - m_compiler->yulIROptimized(_contractName) + irOptimized.value_or("") ); else { sout() << "Optimized IR:" << std::endl; - sout() << m_compiler->yulIROptimized(_contractName) << std::endl; + sout() << irOptimized.value_or("") << std::endl; } } @@ -341,11 +349,12 @@ void CommandLineInterface::handleIROptimizedAst(std::string const& _contractName if (!m_options.compiler.outputs.irOptimizedAstJson) return; + std::optional const& yulIROptimizedAst = m_compiler->yulIROptimizedAst(_contractName); if (!m_options.output.dir.empty()) createFile( m_compiler->filesystemFriendlyName(_contractName) + "_opt_yul_ast.json", util::jsonPrint( - m_compiler->yulIROptimizedAst(_contractName), + yulIROptimizedAst.value_or(Json{}), m_options.formatting.json ) ); @@ -353,7 +362,7 @@ void CommandLineInterface::handleIROptimizedAst(std::string const& _contractName { sout() << "Optimized IR AST:" << std::endl; sout() << util::jsonPrint( - m_compiler->yulIROptimizedAst(_contractName), + yulIROptimizedAst.value_or(Json{}), m_options.formatting.json ) << std::endl; } @@ -544,6 +553,44 @@ void CommandLineInterface::handleGasEstimation(std::string const& _contract) } } +void CommandLineInterface::handleEthdebug() +{ + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + { + std::string ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug()), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile("ethdebug.json", ethdebug); + else + sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl << ethdebug << std::endl; + } +} + +void CommandLineInterface::handleEthdebug(std::string const& _contract) +{ + solAssert(CompilerInputModes.count(m_options.input.mode) == 1); + + if (!(m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime)) + return; + + if (m_options.compiler.outputs.ethdebug) + { + std::string ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug(_contract)), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile(m_compiler->filesystemFriendlyName(_contract) + "_ethdebug.json", ethdebug); + else + sout() << "Debug Data (ethdebug/format/program):" << std::endl << ethdebug << std::endl; + } + + if (m_options.compiler.outputs.ethdebugRuntime) + { + std::string ethdebugRuntime{jsonPrint(removeNullMembers(m_compiler->ethdebugRuntime(_contract)), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile(m_compiler->filesystemFriendlyName(_contract) + "_ethdebug-runtime.json", ethdebugRuntime); + else + sout() << "Debug Data of the runtime part (ethdebug/format/program):" << std::endl << ethdebugRuntime << std::endl; + } +} + void CommandLineInterface::readInputFiles() { solAssert(!m_standardJsonInput.has_value()); @@ -843,7 +890,13 @@ void CommandLineInterface::assembleFromEVMAssemblyJSON() solAssert(m_fileReader.sourceUnits().size() == 1); auto&& [sourceUnitName, source] = *m_fileReader.sourceUnits().begin(); - auto evmAssemblyStack = std::make_unique(m_options.output.evmVersion, m_options.output.eofVersion); + auto evmAssemblyStack = std::make_unique( + m_options.output.evmVersion, + m_options.output.eofVersion, + evmasm::Assembly::OptimiserSettings::translateSettings( + m_options.optimiserSettings() + ) + ); try { evmAssemblyStack->parseAndAnalyze(sourceUnitName, source); @@ -905,6 +958,8 @@ void CommandLineInterface::compile() m_options.compiler.outputs.opcodes || m_options.compiler.outputs.binary || m_options.compiler.outputs.binaryRuntime || + m_options.compiler.outputs.ethdebug || + m_options.compiler.outputs.ethdebugRuntime || (m_options.compiler.combinedJsonRequests && ( m_options.compiler.combinedJsonRequests->binary || m_options.compiler.combinedJsonRequests->binaryRuntime || @@ -955,6 +1010,7 @@ void CommandLineInterface::compile() if (!successful) solThrow(CommandLineExecutionError, ""); } + // NOTE: This includes langutil::StackTooDeepError. catch (CompilerError const& _exception) { m_hasOutput = true; @@ -964,6 +1020,15 @@ void CommandLineInterface::compile() ); solThrow(CommandLineExecutionError, ""); } + catch (yul::StackTooDeepError const& _exception) + { + m_hasOutput = true; + formatter.printExceptionInformation( + _exception, + Error::errorSeverity(Error::Type::YulException) + ); + solThrow(CommandLineExecutionError, ""); + } } void CommandLineInterface::handleCombinedJSON() @@ -1225,9 +1290,10 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y bool successful = true; std::map yulStacks; - for (auto const& src: m_fileReader.sourceUnits()) + std::map objects; + for (auto const& [sourceUnitName, yulSource]: m_fileReader.sourceUnits()) { - auto& stack = yulStacks[src.first] = yul::YulStack( + auto& stack = yulStacks[sourceUnitName] = yul::YulStack( m_options.output.evmVersion, m_options.output.eofVersion, _language, @@ -1237,20 +1303,28 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y DebugInfoSelection::Default() ); - if (!stack.parseAndAnalyze(src.first, src.second)) - successful = false; + successful = successful && stack.parseAndAnalyze(sourceUnitName, yulSource); + if (!successful) + solAssert(stack.hasErrors(), "No error reported, but parsing/analysis failed."); else - stack.optimize(); - - if (successful && m_options.compiler.outputs.asmJson) { - std::shared_ptr result = stack.parserResult(); - if (result && !result->hasContiguousSourceIndices()) + if ( + m_options.compiler.outputs.asmJson && + stack.parserResult() && + !stack.parserResult()->hasContiguousSourceIndices() + ) solThrow( CommandLineExecutionError, "Generating the assembly JSON output was not possible. " "Source indices provided in the @use-src annotation in the Yul input do not start at 0 or are not contiguous." ); + + stack.optimize(); + + yul::MachineAssemblyObject object = stack.assemble(_targetMachine); + if (object.bytecode) + object.bytecode->link(m_options.linker.libraries); + objects.insert({sourceUnitName, std::move(object)}); } } @@ -1274,13 +1348,24 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y solThrow(CommandLineExecutionError, ""); } - for (auto const& src: m_fileReader.sourceUnits()) + for (auto const& [sourceUnitName, yulSource]: m_fileReader.sourceUnits()) { solAssert(_targetMachine == yul::YulStack::Machine::EVM); - std::string machine = "EVM"; - sout() << std::endl << "======= " << src.first << " (" << machine << ") =======" << std::endl; - yul::YulStack& stack = yulStacks[src.first]; + yul::YulStack const& stack = yulStacks[sourceUnitName]; + yul::MachineAssemblyObject const& object = objects[sourceUnitName]; + + if (m_options.compiler.outputs.ethdebug) + { + sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl; + sout() << util::jsonPrint( + evmasm::ethdebug::resources({{sourceUnitName}}, VersionString), + m_options.formatting.json + ) << std::endl; + } + + std::string machine = "EVM"; + sout() << std::endl << "======= " << sourceUnitName << " (" << machine << ") =======" << std::endl; if (m_options.compiler.outputs.irOptimized) { @@ -1290,10 +1375,6 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y sout() << stack.print() << std::endl; } - yul::MachineAssemblyObject object; - object = stack.assemble(_targetMachine); - object.bytecode->link(m_options.linker.libraries); - if (m_options.compiler.outputs.binary) { sout() << std::endl << "Binary representation:" << std::endl; @@ -1332,6 +1413,14 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y m_options.formatting.json ) << std::endl; } + if (m_options.compiler.outputs.ethdebug) + { + sout() << std::endl << "Debug Data (ethdebug/format/program):" << std::endl; + sout() << util::jsonPrint( + object.ethdebug, + m_options.formatting.json + ) << std::endl; + } } } @@ -1344,6 +1433,8 @@ void CommandLineInterface::outputCompilationResults() // do we need AST output? handleAst(); + handleEthdebug(); + CompilerOutputs astOutputSelection; astOutputSelection.astCompactJson = true; if (m_options.compiler.outputs != CompilerOutputs() && m_options.compiler.outputs != astOutputSelection) @@ -1375,6 +1466,7 @@ void CommandLineInterface::outputCompilationResults() handleTransientStorageLayout(contract); handleNatspec(true, contract); handleNatspec(false, contract); + handleEthdebug(contract); } // end of contracts iteration } diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index ce30a4d71db7..b8a10c372db2 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -101,6 +101,7 @@ class CommandLineInterface void handleCombinedJSON(); void handleAst(); + void handleEthdebug(); void handleEVMAssembly(std::string const& _contract); void handleBinary(std::string const& _contract); void handleOpcode(std::string const& _contract); @@ -117,6 +118,7 @@ class CommandLineInterface void handleGasEstimation(std::string const& _contract); void handleStorageLayout(std::string const& _contract); void handleTransientStorageLayout(std::string const& _contract); + void handleEthdebug(std::string const& _contract); /// Tries to read @ m_sourceCodes as a JSONs holding ASTs /// such that they can be imported into the compiler (importASTs()) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 1b29033f0014..484cffa08fab 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -91,7 +91,6 @@ static std::string const g_strOutputDir = "output-dir"; static std::string const g_strOverwrite = "overwrite"; static std::string const g_strRevertStrings = "revert-strings"; static std::string const g_strStopAfter = "stop-after"; -static std::string const g_strParsing = "parsing"; /// Possible arguments to for --revert-strings static std::set const g_revertStringsArgs @@ -102,8 +101,6 @@ static std::set const g_revertStringsArgs revertStringsToString(RevertStrings::VerboseDebug) }; -static std::string const g_strSources = "sources"; -static std::string const g_strSourceList = "sourceList"; static std::string const g_strStandardJSON = "standard-json"; static std::string const g_strStrictAssembly = "strict-assembly"; static std::string const g_strSwarm = "swarm"; @@ -267,7 +264,10 @@ OptimiserSettings CommandLineOptions::optimiserSettings() const if (optimizer.optimizeEvmasm) settings = OptimiserSettings::standard(); else - settings = OptimiserSettings::minimal(); + if (input.mode == InputMode::EVMAssemblerJSON) + settings = OptimiserSettings::none(); + else + settings = OptimiserSettings::minimal(); settings.runYulOptimiser = optimizer.optimizeYul; if (optimizer.optimizeYul) @@ -474,6 +474,7 @@ void CommandLineParser::parseOutputSelection() CompilerOutputs::componentName(&CompilerOutputs::astCompactJson), CompilerOutputs::componentName(&CompilerOutputs::asmJson), CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson), + CompilerOutputs::componentName(&CompilerOutputs::ethdebug), }; static std::set const evmAssemblyJsonImportModeOutputs = { CompilerOutputs::componentName(&CompilerOutputs::asm_), @@ -592,6 +593,16 @@ General Information)").c_str(), ; desc.add(inputOptions); + auto const annotateEVMVersion = [](EVMVersion const& _version) { + return _version.name() + (_version.isExperimental() ? " (experimental)" : ""); + }; + std::vector allEVMVersions = EVMVersion::allVersions(); + std::string annotatedEVMVersions = util::joinHumanReadable( + allEVMVersions | ranges::views::transform(annotateEVMVersion), + ", ", + " or " + ); + po::options_description outputOptions("Output Options"); outputOptions.add_options() ( @@ -606,8 +617,7 @@ General Information)").c_str(), ( g_strEVMVersion.c_str(), po::value()->value_name("version")->default_value(EVMVersion{}.name()), - "Select desired EVM version. Either homestead, tangerineWhistle, spuriousDragon, " - "byzantium, constantinople, petersburg, istanbul, berlin, london, paris, shanghai, cancun or prague." + ("Select desired EVM version: " + annotatedEVMVersions + ".").c_str() ) ; if (!_forHelp) // Note: We intentionally keep this undocumented for now. @@ -642,7 +652,7 @@ General Information)").c_str(), po::value()->default_value(util::toString(DebugInfoSelection::Default())), ("Debug info components to be included in the produced EVM assembly and Yul code. " "Value can be all, none or a comma-separated list containing one or more of the " - "following components: " + util::joinHumanReadable(DebugInfoSelection::componentMap() | ranges::views::keys) + ".").c_str() + "following components: " + util::joinHumanReadable(DebugInfoSelection::Default().selectedNames()) + ".").c_str() ) ( g_strStopAfter.c_str(), @@ -680,7 +690,10 @@ General Information)").c_str(), ) ( g_strImportEvmAssemblerJson.c_str(), - "Import EVM assembly from JSON. Assumes input is in the format used by --asm-json." + ("Import EVM assembly in JSON format produced by --asm-json. " + "WARNING: --asm-json output is already optimized according to settings stored in metadata. " + "Using --" + g_strOptimize + " in this mode is allowed, but not necessary under normal circumstances. " + "It forces the optimizer to run again and can produce bytecode that is not reproducible from metadata.").c_str() ) ( g_strLSP.c_str(), @@ -764,9 +777,23 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::transientStorageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in transient storage.") ; if (!_forHelp) // Note: We intentionally keep this undocumented for now. + { outputComponents.add_options() - (CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), "Control Flow Graph (CFG) of Yul code in JSON format.") - ; + ( + CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), + "Control Flow Graph (CFG) of Yul code in JSON format." + ); + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebug).c_str(), + "Ethdebug output of all contracts." + ); + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime).c_str(), + "Ethdebug output of the runtime part of all contracts." + ); + } desc.add(outputComponents); po::options_description extraOutput("Extra Output"); @@ -1061,6 +1088,7 @@ void CommandLineParser::processArgs() g_strCombinedJson, g_strInputFile, g_strJsonIndent, + g_strOptimize, g_strPrettyJson, "srcmap", "srcmap-runtime", @@ -1224,6 +1252,9 @@ void CommandLineParser::processArgs() m_options.output.eofVersion = 1; } + if (m_options.output.eofVersion.has_value() && !m_options.output.evmVersion.supportsEOF()) + solThrow(CommandLineValidationError, "EOF is not supported by EVM versions earlier than " + EVMVersion::firstWithEOF().name() + "."); + if (m_args.count(g_strNoOptimizeYul) > 0 && m_args.count(g_strOptimizeYul) > 0) solThrow( CommandLineValidationError, @@ -1312,6 +1343,20 @@ void CommandLineParser::processArgs() CommandLineValidationError, "Optimizer can only be used for strict assembly. Use --" + g_strStrictAssembly + "." ); + + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + { + if (m_options.optimiserSettings().runYulOptimiser) + solUnimplemented( + "Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." + ); + + if (!m_options.output.debugInfoSelection.has_value()) + { + m_options.output.debugInfoSelection = DebugInfoSelection::Default(); + m_options.output.debugInfoSelection->enable("ethdebug"); + } + } return; } else if (countEnabledOptions({g_strYulDialect, g_strMachine}) >= 1) @@ -1406,11 +1451,7 @@ void CommandLineParser::processArgs() } if (m_args.count(g_strModelCheckerPrintQuery)) - { - if (!(m_options.modelChecker.settings.solvers == smtutil::SMTSolverChoice::SMTLIB2())) - solThrow(CommandLineValidationError, "Only SMTLib2 solver can be enabled to print queries"); m_options.modelChecker.settings.printQuery = true; - } if (m_args.count(g_strModelCheckerTargets)) { @@ -1457,6 +1498,61 @@ void CommandLineParser::processArgs() m_options.input.mode == InputMode::CompilerWithASTImport || m_options.input.mode == InputMode::EVMAssemblerJSON ); + + bool incompatibleEthdebugOutputs = + m_options.compiler.outputs.asmJson || m_options.compiler.outputs.irAstJson || m_options.compiler.outputs.irOptimizedAstJson || + m_options.optimizer.optimizeYul || m_options.optimizer.optimizeEvmasm; + + bool incompatibleEthdebugInputs = m_options.input.mode != InputMode::Compiler; + + static std::string enableEthdebugMessage = + "--" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime); + + static std::string enableIrMessage = "--" + CompilerOutputs::componentName(&CompilerOutputs::ir) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized); + + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + { + if (!m_options.output.viaIR) + solThrow( + CommandLineValidationError, + enableEthdebugMessage + " output can only be selected, if --via-ir was specified." + ); + + if (incompatibleEthdebugOutputs) + solThrow( + CommandLineValidationError, + enableEthdebugMessage + " output can only be used with " + enableIrMessage + ". Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." + ); + + if (!m_options.output.debugInfoSelection.has_value()) + { + m_options.output.debugInfoSelection = DebugInfoSelection::Default(); + m_options.output.debugInfoSelection->enable("ethdebug"); + } + else + { + if (!m_options.output.debugInfoSelection->ethdebug) + solThrow( + CommandLineValidationError, + "--debug-info must contain ethdebug, when compiling with " + enableEthdebugMessage + "." + ); + } + } + + if ( + m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && + (!(m_options.compiler.outputs.ir || m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) || incompatibleEthdebugOutputs) + ) + solThrow( + CommandLineValidationError, + "--debug-info ethdebug can only be used with " + enableIrMessage + " and/or " + enableEthdebugMessage + ". Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." + ); + + if (m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && incompatibleEthdebugInputs) + solThrow( + CommandLineValidationError, + "Invalid input mode for --debug-info ethdebug / --ethdebug / --ethdebug-runtime." + ); } void CommandLineParser::parseCombinedJsonOption() diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 3d187694e2e0..d8141cb4fcf0 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -88,6 +88,8 @@ struct CompilerOutputs {"storage-layout", &CompilerOutputs::storageLayout}, {"transient-storage-layout", &CompilerOutputs::transientStorageLayout}, {"yul-cfg-json", &CompilerOutputs::yulCFGJson}, + {"ethdebug", &CompilerOutputs::ethdebug}, + {"ethdebug-runtime", &CompilerOutputs::ethdebugRuntime}, }; return components; } @@ -110,6 +112,8 @@ struct CompilerOutputs bool metadata = false; bool storageLayout = false; bool transientStorageLayout = false; + bool ethdebug = false; + bool ethdebugRuntime = false; }; struct CombinedJsonRequests diff --git a/solc/main.cpp b/solc/main.cpp index c6c3df7a2eba..49994559423a 100644 --- a/solc/main.cpp +++ b/solc/main.cpp @@ -51,6 +51,12 @@ int main(int argc, char** argv) std::cerr << boost::diagnostic_information(_exception); return 2; } + catch (yul::YulAssertion const& _exception) + { + std::cerr << "Yul assertion failed:" << std::endl; + std::cerr << boost::diagnostic_information(_exception); + return 2; + } catch (...) { std::cerr << "Uncaught exception:" << std::endl; diff --git a/test/Common.cpp b/test/Common.cpp index ae725774c48a..d39c6db1ea9e 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -16,19 +16,25 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include -#include #include + #include #include +#include + #include #include + #include #include #include + #include +#include +#include + namespace fs = boost::filesystem; namespace po = boost::program_options; @@ -123,22 +129,22 @@ void CommonOptions::addOptions() void CommonOptions::validate() const { - assertThrow( + solRequire( !testPath.empty(), ConfigException, "No test path specified. The --testpath argument must not be empty when given." ); - assertThrow( + solRequire( fs::exists(testPath), ConfigException, "Invalid test path specified." ); - assertThrow( + solRequire( batches > 0, ConfigException, "Batches needs to be at least 1." ); - assertThrow( + solRequire( selectedBatch < batches, ConfigException, "Selected batch has to be less than number of batches." @@ -155,6 +161,12 @@ void CommonOptions::validate() const std::cout << "- ABI coder: v1 (default: v2)" << std::endl; std::cout << std::endl << "DO NOT COMMIT THE UPDATED EXPECTATIONS." << std::endl << std::endl; } + + solRequire( + !eofVersion().has_value() || evmVersion().supportsEOF(), + ConfigException, + "EOF is not supported by EVM versions earlier than " + langutil::EVMVersion::firstWithEOF().name() + "." + ); } bool CommonOptions::parse(int argc, char const* const* argv) @@ -258,6 +270,12 @@ langutil::EVMVersion CommonOptions::evmVersion() const return langutil::EVMVersion(); } +yul::EVMDialect const& CommonOptions::evmDialect() const +{ + return yul::EVMDialect::strictAssemblyForEVMObjects(evmVersion(), eofVersion()); +} + + CommonOptions const& CommonOptions::get() { if (!m_singleton) @@ -288,6 +306,13 @@ bool isValidSemanticTestPath(boost::filesystem::path const& _testPath) return true; } +boost::unit_test::precondition::predicate_t nonEOF() +{ + return [](boost::unit_test::test_unit_id) { + return !solidity::test::CommonOptions::get().eofVersion().has_value(); + }; +} + boost::unit_test::precondition::predicate_t minEVMVersionCheck(langutil::EVMVersion _minEVMVersion) { return [_minEVMVersion](boost::unit_test::test_unit_id) { diff --git a/test/Common.h b/test/Common.h index 409d6f6960e1..27c2081346fc 100644 --- a/test/Common.h +++ b/test/Common.h @@ -29,18 +29,23 @@ #include #include +namespace solidity::yul +{ +class EVMDialect; +} + namespace solidity::test { #ifdef _WIN32 static constexpr auto evmoneFilename = "evmone.dll"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-windows-amd64.zip"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip"; #elif defined(__APPLE__) static constexpr auto evmoneFilename = "libevmone.dylib"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-darwin-arm64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-darwin-arm64.tar.gz"; #else static constexpr auto evmoneFilename = "libevmone.so"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz"; #endif struct ConfigException: public util::Exception {}; @@ -66,6 +71,7 @@ struct CommonOptions langutil::EVMVersion evmVersion() const; std::optional eofVersion() const { return m_eofVersion; } + yul::EVMDialect const& evmDialect() const; virtual void addOptions(); // @returns true if the program should continue, false if it should exit immediately without @@ -106,6 +112,10 @@ bool isValidSemanticTestPath(boost::filesystem::path const& _testPath); /// @return A predicate (function) that can be passed into @a boost::unit_test::precondition(). boost::unit_test::precondition::predicate_t minEVMVersionCheck(langutil::EVMVersion _minEVMVersion); +/// Helper that can be used to skip tests when the EOF is not supported by the test case. +/// @return A predicate (function) that can be passed into @a boost::unit_test::precondition(). +boost::unit_test::precondition::predicate_t nonEOF(); + bool loadVMs(CommonOptions const& _options); /** diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index 3cb908118ea2..ccf4added41e 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -197,15 +197,15 @@ void CommonSyntaxTest::printErrorList( for (auto const& error: _errorList) { { - util::AnsiColorized scope( + util::AnsiColorized formattedStream( _stream, _formatted, {BOLD, SourceReferenceFormatter::errorTextColor(Error::errorSeverity(error.type))} ); - _stream << _linePrefix << Error::formatErrorType(error.type); + formattedStream << _linePrefix << Error::formatErrorType(error.type); if (error.errorId.has_value()) - _stream << ' ' << error.errorId->error; - _stream << ": "; + formattedStream << ' ' << error.errorId->error; + formattedStream << ": "; } if (!error.sourceName.empty() || error.locationStart >= 0 || error.locationEnd >= 0) { diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 5626f8d436e7..983615312efd 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -20,7 +20,20 @@ * for testing purposes. */ +// Weird issue when compiling with O3 on gcc 12 and later due to usage of vector (aka bytes) as std::map key +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98465 +// also clang doesn't know stringop-overread +#if defined(__GNUC__) && !defined(__clang__) // GCC-specific pragma +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overread" +#endif + #include +#include + +#if defined(__GNUC__) && !defined(__clang__) // GCC-specific pragma +#pragma GCC diagnostic pop +#endif #include @@ -58,6 +71,7 @@ evmc::VM& EVMHost::getVM(std::string const& _path) std::cerr << ":" << std::endl << errorMsg; std::cerr << std::endl; } + vms[_path]->set_option("validate_eof", "1"); } if (vms.count(_path) > 0) @@ -92,7 +106,7 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): if (!m_vm) { std::cerr << "Unable to find evmone library" << std::endl; - assertThrow(false, Exception, ""); + solRequire(false, Exception, ""); } if (_evmVersion == langutil::EVMVersion::homestead()) @@ -121,8 +135,10 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): m_evmRevision = EVMC_CANCUN; else if (_evmVersion == langutil::EVMVersion::prague()) m_evmRevision = EVMC_PRAGUE; + else if (_evmVersion == langutil::EVMVersion::osaka()) + m_evmRevision = EVMC_OSAKA; else - assertThrow(false, Exception, "Unsupported EVM version"); + solRequire(false, Exception, "Unsupported EVM version"); if (m_evmRevision >= EVMC_PARIS) // This is the value from the merge block. @@ -213,7 +229,7 @@ void EVMHost::newTransactionFrame() void EVMHost::transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept { - assertThrow(u256(convertFromEVMC(_sender.balance)) >= _value, Exception, "Insufficient balance for transfer"); + solRequire(u256(convertFromEVMC(_sender.balance)) >= _value, Exception, "Insufficient balance for transfer"); _sender.balance = convertToEVMC(u256(convertFromEVMC(_sender.balance)) - _value); _recipient.balance = convertToEVMC(u256(convertFromEVMC(_recipient.balance)) + _value); } @@ -314,7 +330,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept } else if (value <= 0xffff) { return bytes{128 + 55 + 2, static_cast(value >> 8), static_cast(value)}; } else { - assertThrow(false, Exception, "Can only encode RLP numbers <= 0xffff"); + solUnimplemented("Can only encode RLP numbers <= 0xffff"); } }; @@ -328,17 +344,21 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept ), h160::AlignRight); message.recipient = convertToEVMC(createAddress); - assertThrow(accounts.count(message.recipient) == 0, Exception, "Account cannot exist"); + soltestAssert(accounts.count(message.recipient) == 0, "Account cannot exist"); code = evmc::bytes(message.input_data, message.input_data + message.input_size); } - else if (message.kind == EVMC_CREATE2) + else if (message.kind == EVMC_CREATE2 || message.kind == EVMC_EOFCREATE) { h160 createAddress(keccak256( bytes{0xff} + bytes(std::begin(message.sender.bytes), std::end(message.sender.bytes)) + bytes(std::begin(message.create2_salt.bytes), std::end(message.create2_salt.bytes)) + - keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes() + keccak256( + message.kind == EVMC_CREATE2 ? + bytes(message.input_data, message.input_data + message.input_size) : + bytes(message.code, message.code + message.code_size) + ).asBytes() ), h160::AlignRight); message.recipient = convertToEVMC(createAddress); @@ -353,13 +373,16 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept return result; } - code = evmc::bytes(message.input_data, message.input_data + message.input_size); + if (message.kind == EVMC_CREATE2) + code = evmc::bytes(message.input_data, message.input_data + message.input_size); + else // EOFCREATE + code = evmc::bytes(message.code, message.code + message.code_size); } else code = accounts[message.code_address].code; auto& destination = accounts[message.recipient]; - if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2) + if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2 || message.kind == EVMC_EOFCREATE) // Mark account as created if it is a CREATE or CREATE2 call // TODO: Should we roll changes back on failure like we do for `accounts`? m_newlyCreatedAccounts.emplace(message.recipient); @@ -396,7 +419,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept } evmc::Result result = m_vm.execute(*this, m_evmRevision, message, code.data(), code.size()); - if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2) + if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2 || message.kind == EVMC_EOFCREATE) { int64_t codeDepositGas = static_cast(evmasm::GasCosts::createDataGas * result.output_size); result.gas_left -= codeDepositGas; @@ -409,6 +432,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept } else { + // TODO: Add proper codehash calculation for EOF. m_totalCodeDepositGas += codeDepositGas; result.create_address = message.recipient; destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size); @@ -484,9 +508,33 @@ evmc::Result EVMHost::precompileECRecover(evmc_message const& _message) noexcept fromHex("0000000000000000000000008743523d96a1b2cbe0c6909653a56da18ed484af"), gas_cost } + }, + { + fromHex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000003" + ), + { + fromHex(""), + gas_cost + } + }, + { + fromHex( + "77e5189111eb6557e8a637b27ef8fbb15bc61d61c2f00cc48878f3a296e5e0ca" + "0000000000000000000000000000000000000000000000000000000000000000" + "6944c77849b18048f6abe0db8084b0d0d0689cdddb53d2671c36967b58691ad4" + "ef4f06ba4f78319baafd0424365777241af4dfd3da840471b4b4b087b7750d0d" + ), + { + fromHex(""), + gas_cost + } } }; - evmc::Result result = precompileGeneric(_message, inputOutput); + evmc::Result result = precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */); // ECRecover will return success with empty response in case of failure if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_OUT_OF_GAS) return resultWithGas(_message.gas, gas_cost, {}); @@ -643,8 +691,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012" "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -660,8 +706,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000002" "0000000000000000000000000000000000000000000000000000000000000001" "0000000000000000000000000000000000000000000000000000000000000002" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -677,8 +721,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000002" "0000000000000000000000000000000000000000000000000000000000000001" "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -694,8 +736,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "09f5528bdb0ef9354837a0f4b4c9da973bd5b805d359976f719ab0b74e0a7368" "28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e4283" "2795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -711,8 +751,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c" "1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf" "28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -728,8 +766,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "16dabf21b3f25b9665269d98dc17b1da6118251dc0b403ae50e96dfe91239375" "25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b2005" "0d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -745,8 +781,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "1b5ed0e9e8f3ff35589ea81a45cf63887d4a92c099a3be1d97b26f0db96323dd" "16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc" "1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -762,8 +796,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41" "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2" "16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -779,8 +811,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "1d1f2259c715327bedb42c095af6c0267e4e1be836b4e04b3f0502552f93cca9" "2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b" "05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -796,8 +826,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0185fbba22de9e698262925665735dbc4d6e8288bc3fc39fae10ca58e16e77f7" "258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6" "175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -813,8 +841,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b" "1496064626ba8bffeb7805f0d16143a65649bb0850333ea512c03fcdaf31e254" "07b4f210ab542533f1ee5633ae4406cd16c63494b537ce3f1cf4afff6f76a48f" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -830,8 +856,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b" "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59" "3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -847,8 +871,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "26dd3d225c9a71476db0cf834232eba84020f3073c6d20c519963e0b98f235e1" "2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a707" "1d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -864,8 +886,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "13cf106acf943c2a331de21c7d5e3351354e7412f2dba2918483a6593a6828d4" "2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d" "2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -881,8 +901,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "2c7cdf62c2498486fd52646e577a06723ce97737b3c958262d78c4a413661e8a" "0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a" "044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -893,7 +911,7 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex } } }; - return precompileGeneric(_message, inputOutput); + return precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */); } template @@ -906,84 +924,161 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex static std::map const inputOutput{ { - fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000002" + ), { - fromHex("030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"), + fromHex( + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3" + "15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4" + ), gas_cost } }, { - fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000005" + ), { - fromHex("17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c"), + fromHex( + "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa9" + "01e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c" + ), gas_cost } }, { - fromHex("09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4030f7b0c405c888aff922307ea2cd1c70f64664bab76899500341f4260a209290000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe" + "18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4" + "030f7b0c405c888aff922307ea2cd1c70f64664bab76899500341f4260a20929" + ), { - fromHex("16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c"), + fromHex( + "16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc" + "1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c" + ), gas_cost } }, { - fromHex("0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e1551dcd4965285ef049512d2d30cbfc1a91acd5baad4a6e19e22e93176197f170000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a" + "04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e" + "1551dcd4965285ef049512d2d30cbfc1a91acd5baad4a6e19e22e93176197f17" + ), { - fromHex("28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e42832795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f"), + fromHex( + "28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e4283" + "2795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f" + ), gas_cost } }, { - fromHex("0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e0c692b41f1acc961f6ea83bae2c3a1a55c54f766c63ba76989f52c149c17b5e70000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a" + "18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e" + "0c692b41f1acc961f6ea83bae2c3a1a55c54f766c63ba76989f52c149c17b5e7" + ), { - fromHex("258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6"), + fromHex( + "258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6" + "175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6" + ), gas_cost } }, { - fromHex("0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b0ea71d0abb524cac7cfff5323e1d0b14ab705842426c978f96753ccce258ed930000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d" + "0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b" + "0ea71d0abb524cac7cfff5323e1d0b14ab705842426c978f96753ccce258ed93" + ), { - fromHex("2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d"), + fromHex( + "2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d" + "2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d" + ), gas_cost } }, { - fromHex("111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b3000000000000000000000000000000000000000e40800000000000000008cdcbc0000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f" + "1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30" + "00000000000000000000000000000000000000e40800000000000000008cdcbc" + ), { - fromHex("25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b20050d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8"), + fromHex( + "25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b2005" + "0d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8" + ), gas_cost } }, { - fromHex("17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc502b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a11887420878c0c8e37605291c626585eabbec8d8b97a848fe8d58a37b004583510000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5" + "02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1" + "1887420878c0c8e37605291c626585eabbec8d8b97a848fe8d58a37b00458351" + ), { - fromHex("2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6"), + fromHex( + "2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b" + "05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6" + ), gas_cost } }, { - fromHex("1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db016086cc934d5cab679c6991a4efcedbab26d7e4fb23b6a1ad4e6b5c2fb59ce50000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f" + "042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db" + "016086cc934d5cab679c6991a4efcedbab26d7e4fb23b6a1ad4e6b5c2fb59ce5" + ), { - fromHex("1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d"), + fromHex( + "1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf" + "28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d" + ), gas_cost } }, { - fromHex("1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb1eec35a0e955cad4bee5846ae0f1d0b742d8636b278450c534e38e06a60509f90000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc" + "2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb" + "1eec35a0e955cad4bee5846ae0f1d0b742d8636b278450c534e38e06a60509f9" + ), { - fromHex("1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d501202254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"), + fromHex( + "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012" + "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c" + ), gas_cost } }, { - fromHex("232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f82ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda70689c3dc4311426ee11707866b2cbdf9751dacd07245bf99d2113d3f5a8cac470000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8" + "2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7" + "0689c3dc4311426ee11707866b2cbdf9751dacd07245bf99d2113d3f5a8cac47" + ), { - fromHex("2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a7071d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5"), + fromHex( + "2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a707" + "1d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5" + ), gas_cost } } }; - return precompileGeneric(_message, inputOutput); + return precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */); } template @@ -1152,6 +1247,7 @@ evmc::Result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess } } }; + return precompileGeneric(_message, inputOutput); } @@ -1163,16 +1259,35 @@ evmc::Result EVMHost::precompileBlake2f(evmc_message const&) noexcept evmc::Result EVMHost::precompileGeneric( evmc_message const& _message, - std::map const& _inOut) noexcept + std::map const& _inOut, + bool _ignoresTrailingInput +) noexcept { - bytes input(_message.input_data, _message.input_data + _message.input_size); + size_t meaningfulInputSize = _message.input_size; + if (_ignoresTrailingInput && !_inOut.empty()) + { + // _ignoresTrailingInput only implemented for the case where all inputs have same size. + // Simpler to implement and it's all we need for now. + for (auto const& [input, output]: _inOut) + solAssert(input.size() == _inOut.begin()->first.size()); + + // If there is more input that expected, precompiles tend to simply ignore it. + meaningfulInputSize = std::min(_message.input_size, _inOut.begin()->first.size()); + } + + bytes input(_message.input_data, _message.input_data + meaningfulInputSize); if (_inOut.count(input)) { auto const& ret = _inOut.at(input); return resultWithGas(_message.gas, ret.gas_used, ret.output); } else - return resultWithFailure(); + // FIXME: We're in a noexcept function; this will result in terminate() and then abort(). + // Still better than nothing - can't be mistaken for revert and Boost will report test name. + solThrow( + Exception, + "Test output for a precompile not defined for input: " + toHex(input, HexPrefix::Add) + ); } evmc::Result EVMHost::resultWithFailure() noexcept @@ -1206,7 +1321,7 @@ evmc::Result EVMHost::resultWithGas( StorageMap const& EVMHost::get_address_storage(evmc::address const& _addr) { - assertThrow(account_exists(_addr), Exception, "Account does not exist."); + soltestAssert(account_exists(_addr), "Account does not exist."); return accounts[_addr].storage; } @@ -1269,9 +1384,10 @@ void EVMHostPrinter::callRecords() return "CREATE"; case evmc_call_kind::EVMC_CREATE2: return "CREATE2"; - default: - assertThrow(false, Exception, "Invalid call kind."); + case evmc_call_kind::EVMC_EOFCREATE: + return "EOFCREATE"; } + unreachable(); }; for (auto const& record: m_host.recorded_calls) diff --git a/test/EVMHost.h b/test/EVMHost.h index 121adbc15945..522eb7b72fed 100644 --- a/test/EVMHost.h +++ b/test/EVMHost.h @@ -124,7 +124,17 @@ class EVMHost: public evmc::MockedHost template static evmc::Result precompileALTBN128PairingProduct(evmc_message const& _message) noexcept; static evmc::Result precompileBlake2f(evmc_message const& _message) noexcept; - static evmc::Result precompileGeneric(evmc_message const& _message, std::map const& _inOut) noexcept; + /// Generic implementation of a precompile for testing, with hard-coded answers for hard-coded inputs. + /// @param _message EVM message to handle. + /// @param _inOut Hard-coded inputs and corresponding outputs to be returned. + /// @param _ignoresTrailingInput Enable if the precompile only cares about the initial part of + /// its input and works exactly the same, regardless of what's in the remaining part. The message will + /// be considered a match for a test input even if it's longer. + static evmc::Result precompileGeneric( + evmc_message const& _message, + std::map const& _inOut, + bool _ignoresTrailingInput = false + ) noexcept; /// @returns a result object with gas usage and result data taken from @a _data. /// The outcome will be a failure if the limit < required. /// @note The return value is only valid as long as @a _data is alive! diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 0081ba4a9d27..582cf1edab6e 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -145,10 +145,13 @@ u256 ExecutionFramework::blockNumber() const return m_evmcHost->tx_context.block_number; } -void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) +void ExecutionFramework::sendMessage(bytes const& _bytecode, bytes const& _arguments, bool _isCreation, u256 const& _value) { + auto const eof = _bytecode.size() > 1 && _bytecode[0] == 0xef && _bytecode[1] == 0x00; m_evmcHost->newBlock(); + auto const data = _bytecode + _arguments; + if (m_showMessages) { if (_isCreation) @@ -157,17 +160,22 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 std::cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << std::endl; if (_value > 0) std::cout << " value: " << _value << std::endl; - std::cout << " in: " << util::toHex(_data) << std::endl; + std::cout << " in: " << util::toHex(data) << std::endl; } evmc_message message{}; - message.input_data = _data.data(); - message.input_size = _data.size(); + message.input_data = eof ? _arguments.data() : data.data(); + message.input_size = eof ? _arguments.size() : data.size(); + if (eof) + { + message.code = _bytecode.data(); + message.code_size = _bytecode.size(); + } message.sender = EVMHost::convertToEVMC(m_sender); message.value = EVMHost::convertToEVMC(_value); if (_isCreation) { - message.kind = EVMC_CREATE; + message.kind = eof ? EVMC_EOFCREATE : EVMC_CREATE; message.recipient = {}; message.code_address = {}; } diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 33340c58d70d..375660299cf7 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -91,7 +91,7 @@ class ExecutionFramework bytes const& callFallbackWithValue(u256 const& _value) { - sendMessage(bytes(), false, _value); + sendMessage(bytes(), bytes(), false, _value); return m_output; } @@ -102,13 +102,13 @@ class ExecutionFramework bytes const& callLowLevel(bytes const& _data, u256 const& _value) { - sendMessage(_data, false, _value); + sendMessage(_data, bytes(), false, _value); return m_output; } bytes const& callContractFunctionWithValueNoEncoding(std::string _sig, u256 const& _value, bytes const& _arguments) { - sendMessage(util::selectorFromSignatureH32(_sig).asBytes() + _arguments, false, _value); + sendMessage(util::selectorFromSignatureH32(_sig).asBytes(), _arguments, false, _value); return m_output; } @@ -278,7 +278,7 @@ class ExecutionFramework void selectVM(evmc_capabilities _cap = evmc_capabilities::EVMC_CAPABILITY_EVM1); void reset(); - void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0); + void sendMessage(bytes const& _bytecode, bytes const& _argument, bool _isCreation, u256 const& _value = 0); void sendEther(util::h160 const& _to, u256 const& _value); size_t currentTimestamp(); size_t blockTimestamp(u256 _number); diff --git a/test/FilesystemUtils.cpp b/test/FilesystemUtils.cpp index 2d917485d631..edd9a0d6d11d 100644 --- a/test/FilesystemUtils.cpp +++ b/test/FilesystemUtils.cpp @@ -44,12 +44,12 @@ void solidity::test::createFilesWithParentDirs(std::set void solidity::test::createFileWithContent(boost::filesystem::path const& _path, std::string const& _content) { if (boost::filesystem::is_regular_file(_path)) - BOOST_THROW_EXCEPTION(std::runtime_error("File already exists: \"" + _path.string() + "\".")); \ + BOOST_THROW_EXCEPTION(std::runtime_error("File already exists: \"" + _path.string() + "\".")); // Use binary mode to avoid line ending conversion on Windows. std::ofstream newFile(_path.string(), std::ofstream::binary); if (newFile.fail() || !boost::filesystem::is_regular_file(_path)) - BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create a file: \"" + _path.string() + "\".")); \ + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create a file: \"" + _path.string() + "\".")); newFile << _content; } diff --git a/test/Metadata.cpp b/test/Metadata.cpp index cdfcdfb19c48..6b2d1f3d82b8 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -20,11 +20,17 @@ * Metadata processing helpers. */ -#include -#include +#include + +#include + +#include + #include #include -#include + +#include +#include namespace solidity::test { @@ -64,11 +70,11 @@ class TinyCBORParser public: explicit TinyCBORParser(bytes const& _metadata): m_pos(0), m_metadata(_metadata) { - assertThrow((m_pos + 1) < _metadata.size(), CBORException, "Input too short."); + solRequire((m_pos + 1) < _metadata.size(), CBORException, "Input too short."); } unsigned mapItemCount() { - assertThrow(nextType() == MajorType::Map, CBORException, "Fixed-length map expected."); + solRequire(nextType() == MajorType::Map, CBORException, "Fixed-length map expected."); return readLength(); } std::string readKey() @@ -89,17 +95,14 @@ class TinyCBORParser m_pos++; if (value == 20) return "false"; - else if (value == 21) + if (value == 21) return "true"; - else - { - assertThrow(false, CBORException, "Unsupported simple value (not a boolean)."); - return ""; // unreachable, but prevents compiler warning. - } + solUnimplemented("Unsupported simple value (not a boolean)."); } - default: - assertThrow(false, CBORException, "Unsupported value type."); + case MajorType::Map: + solUnimplemented("Nested maps not supported."); } + util::unreachable(); } private: enum class MajorType @@ -118,7 +121,7 @@ class TinyCBORParser case 3: return MajorType::TextString; case 5: return MajorType::Map; case 7: return MajorType::SimpleData; - default: assertThrow(false, CBORException, "Unsupported major type."); + default: solUnimplemented("Unsupported major type."); } } unsigned nextImmediate() const { return m_metadata.at(m_pos) & 0x1f; } @@ -130,7 +133,7 @@ class TinyCBORParser if (length == 24) return m_metadata.at(m_pos++); // Unsupported length kind. (Only by this parser.) - assertThrow(false, CBORException, std::string("Unsupported length ") + std::to_string(length)); + solUnimplemented(std::string("Unsupported length ") + std::to_string(length)); } bytes readBytes(unsigned length) { @@ -141,7 +144,7 @@ class TinyCBORParser std::string readString() { // Expect a text string. - assertThrow(nextType() == MajorType::TextString, CBORException, "String expected."); + soltestAssert(nextType() == MajorType::TextString, "String expected."); bytes tmp{readBytes(readLength())}; return std::string{tmp.begin(), tmp.end()}; } diff --git a/test/TestCase.cpp b/test/TestCase.cpp index ae89bb56f31a..da47c26fde90 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -96,8 +96,7 @@ TestCase::TestResult TestCase::checkResult(std::ostream& _stream, const std::str return TestResult::Success; } -EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _filename): - TestCase(_filename) +void EVMVersionRestrictedTestCase::processEVMVersionSetting() { std::string versionString = m_reader.stringSetting("EVMVersion", "any"); if (versionString == "any") @@ -115,7 +114,11 @@ EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _f break; versionString = versionString.substr(versionBegin); - std::optional version = langutil::EVMVersion::fromString(versionString); + std::optional version; + if (versionString == "current") + version = std::make_optional(); + else + version = langutil::EVMVersion::fromString(versionString); if (!version) BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid EVM version: \"" + versionString + "\""}); @@ -139,3 +142,29 @@ EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _f if (!comparisonResult) m_shouldRun = false; } + +void EVMVersionRestrictedTestCase::processBytecodeFormatSetting() +{ + std::optional eofVersion = solidity::test::CommonOptions::get().eofVersion(); + // EOF only available since Osaka + solAssert(!eofVersion.has_value() || solidity::test::CommonOptions::get().evmVersion().supportsEOF()); + + std::string bytecodeFormatString = m_reader.stringSetting("bytecodeFormat", "legacy,>=EOFv1"); + if (bytecodeFormatString == "legacy,>=EOFv1" || bytecodeFormatString == ">=EOFv1,legacy") + return; + + // TODO: This is naive implementation because for now we support only one EOF version. + if (bytecodeFormatString == "legacy" && eofVersion.has_value()) + m_shouldRun = false; + else if (bytecodeFormatString == ">=EOFv1" && !eofVersion.has_value()) + m_shouldRun = false; + else if (bytecodeFormatString != "legacy" && bytecodeFormatString != ">=EOFv1" ) + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid bytecodeFormat flag: \"" + bytecodeFormatString + "\""}); +} + +EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _filename): + TestCase(_filename) +{ + processEVMVersionSetting(); + processBytecodeFormatSetting(); +} diff --git a/test/TestCase.h b/test/TestCase.h index 301dbfb658e4..bdf51d2a5566 100644 --- a/test/TestCase.h +++ b/test/TestCase.h @@ -112,6 +112,10 @@ class TestCase class EVMVersionRestrictedTestCase: public TestCase { +private: + void processEVMVersionSetting(); + void processBytecodeFormatSetting(); + protected: EVMVersionRestrictedTestCase(std::string const& _filename); }; diff --git a/test/benchmarks/external-setup.sh b/test/benchmarks/external-setup.sh index 2316d83d586e..9b82c5767cf7 100755 --- a/test/benchmarks/external-setup.sh +++ b/test/benchmarks/external-setup.sh @@ -40,74 +40,87 @@ function neutralize_via_ir { sed -i '/^via_ir\s*=.*$/d' foundry.toml } -mkdir -p "$BENCHMARK_DIR" -cd "$BENCHMARK_DIR" +function setup_foundry_project { + local subdir="$1" + local ref_type="$2" + local ref="$3" + local repo_url="$4" + local install_function="${5:-}" -if [[ ! -e openzeppelin/ ]]; then - git clone --depth=1 https://github.com/OpenZeppelin/openzeppelin-contracts openzeppelin/ --branch v5.0.2 - pushd openzeppelin/ - forge install - neutralize_via_ir - popd -else - echo "Skipped openzeppelin/. Already exists." -fi - -if [[ ! -e uniswap-v4/ ]]; then - git clone --single-branch https://github.com/Uniswap/v4-core uniswap-v4/ - pushd uniswap-v4/ - git checkout ae86975b058d386c9be24e8994236f662affacdb # branch main as of 2024-06-06 - forge install - neutralize_via_ir - popd -else - echo "Skipped uniswap-v4/. Already exists." -fi - -if [[ ! -e seaport/ ]]; then - git clone --single-branch https://github.com/ProjectOpenSea/seaport - pushd seaport/ - # NOTE: Can't select the tag with `git clone` because a branch of the same name exists. - git checkout tags/1.6 - forge install - neutralize_via_ir + printf ">>> %-22s | " "$subdir" + + [[ $ref_type == commit || $ref_type == tag ]] || assertFail + + [[ ! -e "$subdir" ]] || { printf "already exists\n"; return; } + printf "downloading...\n\n" + + if [[ $ref_type == tag ]]; then + git clone --depth=1 "$repo_url" "$subdir" --branch "$ref" + pushd "$subdir" + else + git clone "$repo_url" "$subdir" + pushd "$subdir" + git checkout "$ref" + fi + if [[ -z $install_function ]]; then + forge install + else + "$install_function" + fi + + [[ ! -e foundry.toml ]] || neutralize_via_ir neutralize_version_pragmas popd -else - echo "Skipped seaport/. Already exists." -fi - -if [[ ! -e eigenlayer/ ]]; then - git clone --depth=1 https://github.com/Layr-Labs/eigenlayer-contracts eigenlayer/ --branch v0.3.0-holesky-rewards - pushd eigenlayer/ - neutralize_via_ir + echo +} + +function install_liquity { + sed -i -e 's|git@github.com:|https://github.com/|g' .gitmodules forge install - popd -else - echo "Skipped eigenlayer/. Already exists." -fi +} -if [[ ! -e sablier-v2/ ]]; then - git clone --depth=1 https://github.com/sablier-labs/v2-core sablier-v2/ --branch v1.1.2 - pushd sablier-v2/ +function install_old_uniswap { + openzeppelin_version=$(sed -n 's|\s\+"@openzeppelin/contracts": "\([0-9.]\+\)"|\1|p' package.json) + rm package.json + rm yarn.lock + npm install "@openzeppelin/contracts@${openzeppelin_version}" +} + +function install_sablier { # NOTE: To avoid hard-coding dependency versions here we'd have to install them from npm forge install --no-commit \ - foundry-rs/forge-std@v1.5.6 \ - OpenZeppelin/openzeppelin-contracts@v4.9.2 \ - PaulRBerg/prb-math@v4.0.2 \ - PaulRBerg/prb-test@v0.6.4 \ + foundry-rs/forge-std@v1.8.2 \ + OpenZeppelin/openzeppelin-contracts@v5.0.2 \ + PaulRBerg/prb-math@v4.0.3 \ evmcheb/solarray@a547630 \ - Vectorized/solady@v0.0.129 + Vectorized/solady@v0.0.208 cat < remappings.txt @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ forge-std/=lib/forge-std/ @prb/math/=lib/prb-math/ -@prb/test/=lib/prb-test/ solarray/=lib/solarray/ solady/=lib/solady/ EOF - neutralize_via_ir - popd -else - echo "Skipped sablier-v2/. Already exists." -fi +} + +mkdir -p "$BENCHMARK_DIR" +cd "$BENCHMARK_DIR" + +setup_foundry_project openzeppelin-5.0.2/ tag v5.0.2 https://github.com/OpenZeppelin/openzeppelin-contracts +setup_foundry_project openzeppelin-4.9.0/ tag v4.9.0 https://github.com/OpenZeppelin/openzeppelin-contracts +setup_foundry_project openzeppelin-4.8.0/ tag v4.8.0 https://github.com/OpenZeppelin/openzeppelin-contracts +setup_foundry_project openzeppelin-4.7.0/ tag v4.7.0 https://github.com/OpenZeppelin/openzeppelin-contracts + +setup_foundry_project liquity-2024-10-30/ commit 7f93a3f1781dfce2c4e0b6a7262deddd8a10e45b https://github.com/liquity/V2-gov install_liquity + +setup_foundry_project uniswap-v4-2024-06-06/ commit ae86975b058d386c9be24e8994236f662affacdb https://github.com/Uniswap/v4-core +setup_foundry_project uniswap-v4-2022-06-16/ commit 9aeddf76e1b8646908fbcc7519c882bf458b794d https://github.com/Uniswap/v4-core install_old_uniswap + +setup_foundry_project farcaster-3.1.0/ tag v3.1.0 https://github.com/farcasterxyz/contracts + +# NOTE: Can't select the tag with `git clone` because a branch of the same name exists. +setup_foundry_project seaport-1.6/ commit tags/1.6 https://github.com/ProjectOpenSea/seaport + +setup_foundry_project eigenlayer-0.3.0/ tag v0.3.0-holesky-rewards https://github.com/Layr-Labs/eigenlayer-contracts + +setup_foundry_project sablier-v2-1.2.0/ tag v1.2.0 https://github.com/sablier-labs/v2-core install_sablier diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index 9acaccb67f79..b003f0ba18d2 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -65,7 +65,7 @@ function benchmark_project { > /dev/null \ 2> "../stderr-${project}-${pipeline}.log" || true - printf '| %-20s | %8s | %6d s | %9d MiB | %9d |\n' \ + printf '| %-21s | %8s | %6d s | %9d MiB | %9d |\n' \ "$project" \ "$pipeline" \ "$(jq '(.user + .sys) | round' "$time_file")" \ @@ -76,18 +76,24 @@ function benchmark_project { benchmarks=( # Fastest ones first so that we get *some* output quickly - openzeppelin - uniswap-v4 - eigenlayer - seaport - sablier-v2 + uniswap-v4-2022-06-16 # compiles via IR with solc >=0.8.12 + openzeppelin-5.0.2 # compiles via IR with solc >=0.8.26 + openzeppelin-4.9.0 # compiles via IR with solc 0.8.10-0.8.14 and >=0.8.26 + liquity-2024-10-30 # compiles via IR with solc >=0.8.24 + openzeppelin-4.7.0 # compiles via IR with solc >=0.8.10 + openzeppelin-4.8.0 # compiles via IR with solc >=0.8.10 + uniswap-v4-2024-06-06 # compiles via IR with solc >=0.8.24 + eigenlayer-0.3.0 # compiles via IR with solc >=0.8.18 + sablier-v2-1.2.0 # compiles via IR with solc >=0.8.28 (maybe >=0.8.26) + seaport-1.6 # StackTooDeep via IR + farcaster-3.1.0 # StackTooDeep via IR ) mkdir -p "$BENCHMARK_DIR" cd "$BENCHMARK_DIR" -echo "| File | Pipeline | Time | Memory (peak) | Exit code |" -echo "|----------------------|----------|---------:|--------------:|----------:|" +echo "| File | Pipeline | Time | Memory (peak) | Exit code |" +echo "|-----------------------|----------|---------:|--------------:|----------:|" for project in "${benchmarks[@]}"; do benchmark_project legacy "$project" diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 4f7b88fe974f..f68ed53dc066 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -220,6 +220,27 @@ json = re.sub(r"\n\s*\n", "\n", json) json = re.sub(r"},(\n{0,1})\n*(\s*(]|}))", r"}\1\2", json) # Remove trailing comma open("$stdout_path", "w").write(json) EOF + # Only do this to files that actually contain ethdebug output, because jq will reformat + # the whole file and its formatting differs from `solc --pretty-json` + if jq 'has("ethdebug")' "$stdout_path" --exit-status > /dev/null; then + local temporary_file + temporary_file=$(mktemp -t cmdline-ethdebug-XXXXXX.tmp) + if [[ -e ${tdir}/strip-ethdebug ]]; then + jq --indent 4 ' + (. | .. | objects | select(has("ethdebug"))) |= (.ethdebug = "") + ' "$stdout_path" > "$temporary_file" + else + jq --indent 4 ' + if .ethdebug.compilation.compiler.version? != null then + .ethdebug.compilation.compiler.version = "" + else + . + end + ' "$stdout_path" > "$temporary_file" + fi + mv "$temporary_file" "$stdout_path" + fi + sed -i.bak -E -e 's/ Consider adding \\"pragma solidity \^[0-9.]*;\\"//g' "$stdout_path" sed -i.bak -E -e 's/\"opcodes\":[[:space:]]*\"[^"]+\"/\"opcodes\":\"\"/g' "$stdout_path" sed -i.bak -E -e 's/\"sourceMap\":[[:space:]]*\"[0-9:;-]+\"/\"sourceMap\":\"\"/g' "$stdout_path" @@ -275,12 +296,18 @@ EOF sed -i.bak -e 's/^\(Dynamic exception type:\).*/\1/' "$stderr_path" rm "$stderr_path.bak" - if [[ $exitCode -ne "$exit_code_expected" ]] + if [[ "$(cat "$stderr_path")" != "${stderr_expected}" ]] then - printError "Incorrect exit code. Expected $exit_code_expected but got $exitCode." + printError "Incorrect output on stderr received. Expected:" + echo -e "${stderr_expected}" - [[ $exit_code_expectation_file != "" ]] && ask_expectation_update "$exitCode" "$exit_code_expectation_file" - [[ $exit_code_expectation_file == "" ]] && fail + printError "But got:" + echo -e "$(cat "$stderr_path")" + + printError "When running $solc_command" + + [[ $stderr_expectation_file != "" ]] && ask_expectation_update "$(cat "$stderr_path")" "$stderr_expectation_file" + [[ $stderr_expectation_file == "" ]] && fail fi if [[ "$(cat "$stdout_path")" != "${stdout_expected}" ]] @@ -297,18 +324,12 @@ EOF [[ $stdout_expectation_file == "" ]] && fail fi - if [[ "$(cat "$stderr_path")" != "${stderr_expected}" ]] + if [[ $exitCode -ne "$exit_code_expected" ]] then - printError "Incorrect output on stderr received. Expected:" - echo -e "${stderr_expected}" - - printError "But got:" - echo -e "$(cat "$stderr_path")" - - printError "When running $solc_command" + printError "Incorrect exit code. Expected $exit_code_expected but got $exitCode." - [[ $stderr_expectation_file != "" ]] && ask_expectation_update "$(cat "$stderr_path")" "$stderr_expectation_file" - [[ $stderr_expectation_file == "" ]] && fail + [[ $exit_code_expectation_file != "" ]] && ask_expectation_update "$exitCode" "$exit_code_expectation_file" + [[ $exit_code_expectation_file == "" ]] && fail fi rm "$stdout_path" "$stderr_path" diff --git a/test/cmdlineTests/ast_compact_json_storage_layout_specifier/args b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/args new file mode 100644 index 000000000000..76497f217954 --- /dev/null +++ b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/args @@ -0,0 +1 @@ +--ast-compact-json --pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/ast_compact_json_storage_layout_specifier/input.sol b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/input.sol new file mode 100644 index 000000000000..e6c5250af0ff --- /dev/null +++ b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C layout at 1234 + 4567 {} diff --git a/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output new file mode 100644 index 000000000000..4fe5fe193be9 --- /dev/null +++ b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output @@ -0,0 +1,103 @@ +JSON AST (compact format): + + +======= ast_compact_json_storage_layout_specifier/input.sol ======= +{ + "absolutePath": "ast_compact_json_storage_layout_specifier/input.sol", + "exportedSymbols": { + "C": [ + 6 + ] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": [ + 6 + ], + "name": "C", + "nameLocation": "69:1:0", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 7, + "src": "60:35:0", + "storageLayout": { + "baseSlotExpression": { + "commonType": { + "typeIdentifier": "t_rational_5801_by_1", + "typeString": "int_const 5801" + }, + "id": 4, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "leftExpression": { + "hexValue": "31323334", + "id": 2, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "81:4:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_1234_by_1", + "typeString": "int_const 1234" + }, + "value": "1234" + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "hexValue": "34353637", + "id": 3, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "88:4:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_4567_by_1", + "typeString": "int_const 4567" + }, + "value": "4567" + }, + "src": "81:11:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_5801_by_1", + "typeString": "int_const 5801" + } + }, + "id": 5, + "nodeType": "StorageLayoutSpecifier", + "src": "71:21:0" + }, + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "36:60:0" +} diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index d5c02fc82151..975582f669ba 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -312,6 +312,7 @@ object "D_27" { var__5_mpos := zero_t_string_memory_ptr_1_mpos /// @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." + let _2 := allocate_unbounded() let _3 := add(_2, datasize("C_2")) if or(gt(_3, 0xffffffffffffffff), lt(_3, _2)) { panic_error_0x41() } diff --git a/test/cmdlineTests/eof_unavailable_before_osaka/args b/test/cmdlineTests/eof_unavailable_before_osaka/args new file mode 100644 index 000000000000..90e7e00e2552 --- /dev/null +++ b/test/cmdlineTests/eof_unavailable_before_osaka/args @@ -0,0 +1 @@ +--optimize --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/eof_unavailable_before_osaka/err b/test/cmdlineTests/eof_unavailable_before_osaka/err new file mode 100644 index 000000000000..cf9a17a7dfb9 --- /dev/null +++ b/test/cmdlineTests/eof_unavailable_before_osaka/err @@ -0,0 +1 @@ +Error: EOF is not supported by EVM versions earlier than osaka. diff --git a/test/cmdlineTests/import_asm_json_optimize_not_supported/exit b/test/cmdlineTests/eof_unavailable_before_osaka/exit similarity index 100% rename from test/cmdlineTests/import_asm_json_optimize_not_supported/exit rename to test/cmdlineTests/eof_unavailable_before_osaka/exit diff --git a/test/cmdlineTests/eof_unavailable_before_osaka/input.sol b/test/cmdlineTests/eof_unavailable_before_osaka/input.sol new file mode 100644 index 000000000000..f123f6c8bee3 --- /dev/null +++ b/test/cmdlineTests/eof_unavailable_before_osaka/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C {} diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/args b/test/cmdlineTests/ethdebug_eof_container_osaka/args new file mode 100644 index 000000000000..65974c6287da --- /dev/null +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/args @@ -0,0 +1 @@ + --experimental-eof-version 1 --evm-version osaka --ethdebug --via-ir diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/err b/test/cmdlineTests/ethdebug_eof_container_osaka/err new file mode 100644 index 000000000000..7714685971d2 --- /dev/null +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/err @@ -0,0 +1 @@ +Error: ethdebug does not yet support EOF. diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/exit b/test/cmdlineTests/ethdebug_eof_container_osaka/exit similarity index 100% rename from test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/exit rename to test/cmdlineTests/ethdebug_eof_container_osaka/exit diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/input.sol b/test/cmdlineTests/ethdebug_eof_container_osaka/input.sol new file mode 100644 index 000000000000..415509ef9aef --- /dev/null +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/output b/test/cmdlineTests/ethdebug_eof_container_osaka/output new file mode 100644 index 000000000000..9d002fadc317 --- /dev/null +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/output @@ -0,0 +1,4 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"compilation":{"compiler":{"name":"solc","version": ""},"sources":[{"id":0,"path":"ethdebug_eof_container_osaka/input.sol"}]}} + +======= ethdebug_eof_container_osaka/input.sol:C ======= diff --git a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args new file mode 100644 index 000000000000..b5d6267fa5b0 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args @@ -0,0 +1 @@ +--import-asm-json --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/err b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/err new file mode 100644 index 000000000000..02ce7958c8d7 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/err @@ -0,0 +1 @@ +Error: Option --evm-version is not supported with --import-asm-json. diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/exit b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/exit similarity index 100% rename from test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/exit rename to test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/exit diff --git a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/stdin b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/stdin new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/stdin @@ -0,0 +1 @@ +{} diff --git a/test/cmdlineTests/import_asm_json_no_optimize/args b/test/cmdlineTests/import_asm_json_no_optimize/args new file mode 100644 index 000000000000..0af885908f1e --- /dev/null +++ b/test/cmdlineTests/import_asm_json_no_optimize/args @@ -0,0 +1 @@ +--import-asm-json - --asm diff --git a/test/cmdlineTests/import_asm_json_no_optimize/output b/test/cmdlineTests/import_asm_json_no_optimize/output new file mode 100644 index 000000000000..03aa23879874 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_no_optimize/output @@ -0,0 +1,19 @@ +EVM assembly: + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + pop(0x00) + pop + pop + pop + pop + pop + pop + pop + revert diff --git a/test/cmdlineTests/import_asm_json_no_optimize/stdin b/test/cmdlineTests/import_asm_json_no_optimize/stdin new file mode 100644 index 000000000000..c7017646aefd --- /dev/null +++ b/test/cmdlineTests/import_asm_json_no_optimize/stdin @@ -0,0 +1,23 @@ +{ + ".code": [ + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "REVERT" } + ] +} diff --git a/test/cmdlineTests/import_asm_json_optimize/args b/test/cmdlineTests/import_asm_json_optimize/args new file mode 100644 index 000000000000..b9370e6e4f11 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_optimize/args @@ -0,0 +1 @@ +--optimize --import-asm-json - --asm diff --git a/test/cmdlineTests/import_asm_json_optimize/exit b/test/cmdlineTests/import_asm_json_optimize/exit new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_optimize/exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/import_asm_json_optimize/output b/test/cmdlineTests/import_asm_json_optimize/output new file mode 100644 index 000000000000..25337fe77938 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_optimize/output @@ -0,0 +1,2 @@ +EVM assembly: + revert(0x00, 0x00) diff --git a/test/cmdlineTests/import_asm_json_optimize/stdin b/test/cmdlineTests/import_asm_json_optimize/stdin new file mode 100644 index 000000000000..c7017646aefd --- /dev/null +++ b/test/cmdlineTests/import_asm_json_optimize/stdin @@ -0,0 +1,23 @@ +{ + ".code": [ + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "REVERT" } + ] +} diff --git a/test/cmdlineTests/import_asm_json_optimize_not_supported/args b/test/cmdlineTests/import_asm_json_optimize_not_supported/args deleted file mode 100644 index f649e9740882..000000000000 --- a/test/cmdlineTests/import_asm_json_optimize_not_supported/args +++ /dev/null @@ -1 +0,0 @@ ---optimize --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_optimize_not_supported/err b/test/cmdlineTests/import_asm_json_optimize_not_supported/err deleted file mode 100644 index 8f42dca78694..000000000000 --- a/test/cmdlineTests/import_asm_json_optimize_not_supported/err +++ /dev/null @@ -1 +0,0 @@ -Error: Option --optimize is not supported with --import-asm-json. diff --git a/test/cmdlineTests/import_asm_json_optimize_not_supported/stdin b/test/cmdlineTests/import_asm_json_optimize_not_supported/stdin deleted file mode 100644 index f6cc546647c3..000000000000 --- a/test/cmdlineTests/import_asm_json_optimize_not_supported/stdin +++ /dev/null @@ -1,6 +0,0 @@ -{ - ".code": [ - {"name": "DIFFICULTY"}, - {"name": "PREVRANDAO"} - ] -} diff --git a/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json new file mode 100644 index 000000000000..d2ba25938f7d --- /dev/null +++ b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json @@ -0,0 +1,37 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "REVERT" } + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.assembly"] + } + } + } +} diff --git a/test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json new file mode 100644 index 000000000000..5dc5942bf7c0 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json @@ -0,0 +1,29 @@ +{ + "contracts": { + "A": { + "": { + "evm": { + "assembly": " 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + pop(0x00) + pop + pop + pop + pop + pop + pop + pop + revert +" + } + } + } + } +} diff --git a/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json b/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json new file mode 100644 index 000000000000..d1d45825952d --- /dev/null +++ b/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json @@ -0,0 +1,40 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "REVERT" } + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.assembly"] + } + }, + "optimizer": { + "enabled": true + } + } +} diff --git a/test/cmdlineTests/import_asm_json_standard_json_optimize/output.json b/test/cmdlineTests/import_asm_json_standard_json_optimize/output.json new file mode 100644 index 000000000000..606862e0af8a --- /dev/null +++ b/test/cmdlineTests/import_asm_json_standard_json_optimize/output.json @@ -0,0 +1,12 @@ +{ + "contracts": { + "A": { + "": { + "evm": { + "assembly": " revert(0x00, 0x00) +" + } + } + } + } +} diff --git a/test/cmdlineTests/inheritance_repeated_definition_error/args b/test/cmdlineTests/inheritance_repeated_definition_error/args new file mode 100644 index 000000000000..3cf20d57b0b8 --- /dev/null +++ b/test/cmdlineTests/inheritance_repeated_definition_error/args @@ -0,0 +1 @@ +- \ No newline at end of file diff --git a/test/cmdlineTests/inheritance_repeated_definition_error/err b/test/cmdlineTests/inheritance_repeated_definition_error/err new file mode 100644 index 000000000000..aa73b10f2281 --- /dev/null +++ b/test/cmdlineTests/inheritance_repeated_definition_error/err @@ -0,0 +1,10 @@ +Error: More than one inheritance list. + --> :9:20: + | +9 | contract C is A, B is B { + | ^^ +Note: Previous list: + --> :9:15: + | +9 | contract C is A, B is B { + | ^ diff --git a/test/cmdlineTests/model_checker_print_query_superflous_solver/exit b/test/cmdlineTests/inheritance_repeated_definition_error/exit similarity index 100% rename from test/cmdlineTests/model_checker_print_query_superflous_solver/exit rename to test/cmdlineTests/inheritance_repeated_definition_error/exit diff --git a/test/cmdlineTests/inheritance_repeated_definition_error/stdin b/test/cmdlineTests/inheritance_repeated_definition_error/stdin new file mode 100644 index 000000000000..8babcc4f2691 --- /dev/null +++ b/test/cmdlineTests/inheritance_repeated_definition_error/stdin @@ -0,0 +1,10 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract A { +} + +contract B { +} + +contract C is A, B is B { +} \ No newline at end of file diff --git a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/args b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/args new file mode 100644 index 000000000000..d0fe39023051 --- /dev/null +++ b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/args @@ -0,0 +1 @@ +--ir --debug-info none \ No newline at end of file diff --git a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/input.sol b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/input.sol new file mode 100644 index 000000000000..685bec80771a --- /dev/null +++ b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/input.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure { + // NOTE: memoryguard is a builtin but only in pure Yul, not inline assembly. + // NOTE: memoryguard is not a reserved identifier. + // The expectation of this test is to not see the shadowed memoryguard within the generated Yul code but rather + // a mangled version of it + assembly { function memoryguard() {} } + assembly { function f(memoryguard) {} } + assembly { function f() -> memoryguard {} } + assembly { let memoryguard } + } +} diff --git a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output new file mode 100644 index 000000000000..842580597d12 --- /dev/null +++ b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output @@ -0,0 +1,123 @@ +IR: + +/// @use-src 0:"memoryguard_shadowing_by_inline_assembly_identifiers/input.sol" +object "C_10" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_10() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_10_deployed"), datasize("C_10_deployed")) + + return(_1, datasize("C_10_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_10() { + + } + + } + /// @use-src 0:"memoryguard_shadowing_by_inline_assembly_identifiers/input.sol" + object "C_10_deployed" { + code { + + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + external_fun_f_9() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_9() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_9() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function fun_f_9() { + + { + function usr$memoryguard() + { } + } + + { + function usr$f(usr$memoryguard) + { } + } + + { + function usr$f() -> usr$memoryguard + { } + } + + { let usr$memoryguard } + + } + + } + + data ".metadata" hex"" + } + +} diff --git a/test/cmdlineTests/model_checker_divModSlacks_false_all/err b/test/cmdlineTests/model_checker_divModSlacks_false_all/err index 8de36b1ee4e8..bf4337810dc9 100644 --- a/test/cmdlineTests/model_checker_divModSlacks_false_all/err +++ b/test/cmdlineTests/model_checker_divModSlacks_false_all/err @@ -1,15 +1,3 @@ -Warning: CHC: Error trying to invoke SMT solver. - --> model_checker_divModSlacks_false_all/input.sol:6:11: - | -6 | return (a / b, a % b); - | ^^^^^ - -Warning: CHC: Error trying to invoke SMT solver. - --> model_checker_divModSlacks_false_all/input.sol:6:18: - | -6 | return (a / b, a % b); - | ^^^^^ - Warning: CHC: 2 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. Info: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_divModSlacks_false_chc/err b/test/cmdlineTests/model_checker_divModSlacks_false_chc/err index 56cca82c0832..0d6d7341e52c 100644 --- a/test/cmdlineTests/model_checker_divModSlacks_false_chc/err +++ b/test/cmdlineTests/model_checker_divModSlacks_false_chc/err @@ -1,13 +1 @@ -Warning: CHC: Error trying to invoke SMT solver. - --> model_checker_divModSlacks_false_chc/input.sol:6:11: - | -6 | return (a / b, a % b); - | ^^^^^ - -Warning: CHC: Error trying to invoke SMT solver. - --> model_checker_divModSlacks_false_chc/input.sol:6:18: - | -6 | return (a / b, a % b); - | ^^^^^ - Warning: CHC: 2 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. diff --git a/test/cmdlineTests/model_checker_invariants_all/err b/test/cmdlineTests/model_checker_invariants_all/err index 7ec97678e990..dcef00b5fd0e 100644 --- a/test/cmdlineTests/model_checker_invariants_all/err +++ b/test/cmdlineTests/model_checker_invariants_all/err @@ -1,14 +1,8 @@ -Warning: Return value of low-level calls not used. - --> model_checker_invariants_all/input.sol:6:3: - | -6 | _a.call(""); - | ^^^^^^^^^^^ - Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Contract invariant(s) for model_checker_invariants_all/input.sol:test: -(!(x >= 1) || true) +(true || !(x >= 1)) Reentrancy property(ies) for model_checker_invariants_all/input.sol:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_all/input.sol b/test/cmdlineTests/model_checker_invariants_all/input.sol index 8b90cb3c1324..e75a75b5fbb6 100644 --- a/test/cmdlineTests/model_checker_invariants_all/input.sol +++ b/test/cmdlineTests/model_checker_invariants_all/input.sol @@ -2,8 +2,7 @@ pragma solidity >=0.0; contract test { uint x; - function f(address _a) public { - _a.call(""); + function f() public view { assert(x == 0); - } -} \ No newline at end of file + } +} diff --git a/test/cmdlineTests/model_checker_invariants_contract/err b/test/cmdlineTests/model_checker_invariants_contract/err index f6b01e9b2cbf..3ecad6b35d48 100644 --- a/test/cmdlineTests/model_checker_invariants_contract/err +++ b/test/cmdlineTests/model_checker_invariants_contract/err @@ -1,4 +1,4 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Contract invariant(s) for model_checker_invariants_contract/input.sol:test: -(!(x >= 1) || true) +(true || !(x >= 1)) diff --git a/test/cmdlineTests/model_checker_invariants_contract/input.sol b/test/cmdlineTests/model_checker_invariants_contract/input.sol index 3a857d4848c9..e75a75b5fbb6 100644 --- a/test/cmdlineTests/model_checker_invariants_contract/input.sol +++ b/test/cmdlineTests/model_checker_invariants_contract/input.sol @@ -2,7 +2,7 @@ pragma solidity >=0.0; contract test { uint x; - function f() public view { - assert(x < 10); - } -} \ No newline at end of file + function f() public view { + assert(x == 0); + } +} diff --git a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err index 11ee3a702f8c..7764e89abc59 100644 --- a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err @@ -1,14 +1,8 @@ -Warning: Return value of low-level calls not used. - --> model_checker_invariants_contract_reentrancy/input.sol:6:3: - | -6 | _a.call(""); - | ^^^^^^^^^^^ - Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Contract invariant(s) for model_checker_invariants_contract_reentrancy/input.sol:test: -(!(x >= 1) || true) +(true || !(x >= 1)) Reentrancy property(ies) for model_checker_invariants_contract_reentrancy/input.sol:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/input.sol b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/input.sol index 8b90cb3c1324..e75a75b5fbb6 100644 --- a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/input.sol +++ b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/input.sol @@ -2,8 +2,7 @@ pragma solidity >=0.0; contract test { uint x; - function f(address _a) public { - _a.call(""); + function f() public view { assert(x == 0); - } -} \ No newline at end of file + } +} diff --git a/test/cmdlineTests/model_checker_invariants_reentrancy/err b/test/cmdlineTests/model_checker_invariants_reentrancy/err index 68ef6404cdb8..8891b0e18c59 100644 --- a/test/cmdlineTests/model_checker_invariants_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_reentrancy/err @@ -1,12 +1,6 @@ -Warning: Return value of low-level calls not used. - --> model_checker_invariants_reentrancy/input.sol:6:3: - | -6 | _a.call(""); - | ^^^^^^^^^^^ - Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Reentrancy property(ies) for model_checker_invariants_reentrancy/input.sol:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors - = 1 -> Assertion failed at assert(x < 10) + = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_reentrancy/input.sol b/test/cmdlineTests/model_checker_invariants_reentrancy/input.sol index f21d4d4c8f46..e75a75b5fbb6 100644 --- a/test/cmdlineTests/model_checker_invariants_reentrancy/input.sol +++ b/test/cmdlineTests/model_checker_invariants_reentrancy/input.sol @@ -2,8 +2,7 @@ pragma solidity >=0.0; contract test { uint x; - function f(address _a) public { - _a.call(""); - assert(x < 10); - } -} \ No newline at end of file + function f() public view { + assert(x == 0); + } +} diff --git a/test/cmdlineTests/model_checker_print_query_all/err b/test/cmdlineTests/model_checker_print_query_all/err index 76dff6664b80..e696c6ed3836 100644 --- a/test/cmdlineTests/model_checker_print_query_all/err +++ b/test/cmdlineTests/model_checker_print_query_all/err @@ -8,7 +8,7 @@ Info: CHC: Requested query: (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -45,7 +45,7 @@ Info: CHC: Requested query: (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -73,7 +73,7 @@ Info: CHC: Requested query: (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -86,8 +86,6 @@ Info: CHC: Requested query: Warning: CHC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. -Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. - Info: BMC: Requested query: (set-option :produce-models true) (set-option :timeout 1000) @@ -96,7 +94,7 @@ Info: BMC: Requested query: (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -112,7 +110,7 @@ Info: BMC: Requested query: (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -120,5 +118,3 @@ Info: BMC: Requested query: Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/model_checker_print_query_bmc/err b/test/cmdlineTests/model_checker_print_query_bmc/err index 6fb8440b7b8b..4713ac13e3ca 100644 --- a/test/cmdlineTests/model_checker_print_query_bmc/err +++ b/test/cmdlineTests/model_checker_print_query_bmc/err @@ -4,7 +4,7 @@ Info: BMC: Requested query: (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -19,7 +19,7 @@ Info: BMC: Requested query: (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -27,5 +27,3 @@ Info: BMC: Requested query: Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/model_checker_print_query_chc/err b/test/cmdlineTests/model_checker_print_query_chc/err index 28368f546205..a55ad5cea7d1 100644 --- a/test/cmdlineTests/model_checker_print_query_chc/err +++ b/test/cmdlineTests/model_checker_print_query_chc/err @@ -8,7 +8,7 @@ Info: CHC: Requested query: (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -45,7 +45,7 @@ Info: CHC: Requested query: (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -73,7 +73,7 @@ Info: CHC: Requested query: (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -85,5 +85,3 @@ Info: CHC: Requested query: Warning: CHC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/args b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/args deleted file mode 100644 index 12b7c324584b..000000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/args +++ /dev/null @@ -1 +0,0 @@ ---model-checker-engine bmc --model-checker-print-query --model-checker-solvers z3 diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/err b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/err deleted file mode 100644 index 1e2296446199..000000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/err +++ /dev/null @@ -1 +0,0 @@ -Error: Only SMTLib2 solver can be enabled to print queries diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/input.sol b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/input.sol deleted file mode 100644 index eb4cd572ae22..000000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/input.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.0; -contract C -{ - function f() public pure { - uint x = 0; - assert(x == 0); - } -} diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/args b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/args deleted file mode 100644 index e3a8c32d4716..000000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/args +++ /dev/null @@ -1 +0,0 @@ ---model-checker-engine chc --model-checker-print-query --model-checker-solvers z3 diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/err b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/err deleted file mode 100644 index 1e2296446199..000000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/err +++ /dev/null @@ -1 +0,0 @@ -Error: Only SMTLib2 solver can be enabled to print queries diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/input.sol b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/input.sol deleted file mode 100644 index eb4cd572ae22..000000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/input.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.0; -contract C -{ - function f() public pure { - uint x = 0; - assert(x == 0); - } -} diff --git a/test/cmdlineTests/model_checker_print_query_superflous_solver/args b/test/cmdlineTests/model_checker_print_query_superflous_solver/args deleted file mode 100644 index 64e5d88728ea..000000000000 --- a/test/cmdlineTests/model_checker_print_query_superflous_solver/args +++ /dev/null @@ -1 +0,0 @@ ---model-checker-engine bmc --model-checker-print-query --model-checker-solvers z3,smtlib2 diff --git a/test/cmdlineTests/model_checker_print_query_superflous_solver/err b/test/cmdlineTests/model_checker_print_query_superflous_solver/err deleted file mode 100644 index 1e2296446199..000000000000 --- a/test/cmdlineTests/model_checker_print_query_superflous_solver/err +++ /dev/null @@ -1 +0,0 @@ -Error: Only SMTLib2 solver can be enabled to print queries diff --git a/test/cmdlineTests/model_checker_print_query_superflous_solver/input.sol b/test/cmdlineTests/model_checker_print_query_superflous_solver/input.sol deleted file mode 100644 index eb4cd572ae22..000000000000 --- a/test/cmdlineTests/model_checker_print_query_superflous_solver/input.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.0; -contract C -{ - function f() public pure { - uint x = 0; - assert(x == 0); - } -} diff --git a/test/cmdlineTests/model_checker_show_unproved_default_all_engines/err b/test/cmdlineTests/model_checker_show_unproved_default_all_engines/err index 45c38ef3594a..486cd2c65899 100644 --- a/test/cmdlineTests/model_checker_show_unproved_default_all_engines/err +++ b/test/cmdlineTests/model_checker_show_unproved_default_all_engines/err @@ -1,3 +1,3 @@ Warning: CHC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. -Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. +Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_show_unproved_default_bmc/err b/test/cmdlineTests/model_checker_show_unproved_default_bmc/err index f8d0af2f4f72..21041fee1976 100644 --- a/test/cmdlineTests/model_checker_show_unproved_default_bmc/err +++ b/test/cmdlineTests/model_checker_show_unproved_default_bmc/err @@ -1 +1 @@ -Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. +Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err b/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err index 83864075dd74..7a338f614952 100644 --- a/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err +++ b/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err @@ -4,9 +4,4 @@ Warning: CHC: Assertion violation might happen here. 10 | assert(s.x > 0); | ^^^^^^^^^^^^^^^ -Warning: BMC: Assertion violation might happen here. - --> model_checker_show_unproved_true_all_engines/input.sol:10:9: - | -10 | assert(s.x > 0); - | ^^^^^^^^^^^^^^^ -Note: +Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_show_unproved_true_bmc/err b/test/cmdlineTests/model_checker_show_unproved_true_bmc/err index 84ada7873b07..21041fee1976 100644 --- a/test/cmdlineTests/model_checker_show_unproved_true_bmc/err +++ b/test/cmdlineTests/model_checker_show_unproved_true_bmc/err @@ -1,6 +1 @@ -Warning: BMC: Assertion violation might happen here. - --> model_checker_show_unproved_true_bmc/input.sol:10:9: - | -10 | assert(s.x > 0); - | ^^^^^^^^^^^^^^^ -Note: +Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/args b/test/cmdlineTests/stack_too_deep_from_code_transform/args new file mode 100644 index 000000000000..b182392aac61 --- /dev/null +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/args @@ -0,0 +1 @@ +--via-ir --bin diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/err b/test/cmdlineTests/stack_too_deep_from_code_transform/err new file mode 100644 index 000000000000..588f4d437945 --- /dev/null +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/err @@ -0,0 +1,6 @@ +Error: Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] +memoryguard was present. + --> stack_too_deep_from_code_transform/input.sol:1:1: + | +1 | contract C { + | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/exit b/test/cmdlineTests/stack_too_deep_from_code_transform/exit new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/input.sol b/test/cmdlineTests/stack_too_deep_from_code_transform/input.sol new file mode 100644 index 000000000000..aae75b841ce0 --- /dev/null +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/input.sol @@ -0,0 +1,10 @@ +contract C { + function f() public { + uint b; + abi.encodePacked( + b, b, b, b, b, b, b, b, + b, b, b, b, b, b, b, b, + b, b, b, b, b, b, b, b + ); + } +} diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args new file mode 100644 index 000000000000..f0b85640bd48 --- /dev/null +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args @@ -0,0 +1 @@ +--import-ast - \ No newline at end of file diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/err b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/err new file mode 100644 index 000000000000..bdb03116e486 --- /dev/null +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/err @@ -0,0 +1 @@ +Error: Failed to import AST: Expected field "baseSlotExpression" is missing. diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/exit b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/exit new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/stdin b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/stdin new file mode 100644 index 000000000000..88bd25df1283 --- /dev/null +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/stdin @@ -0,0 +1,62 @@ +{ + "language": "SolidityAST", + "sources": { + "A": { + "AST": { + "absolutePath": "A", + "exportedSymbols": { + "C": [ + 4 + ] + }, + "id": 5, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 4, + "linearizedBaseContracts": [ + 4 + ], + "name": "C", + "nameLocation": "69:1:0", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 5, + "src": "60:28:0", + "storageLayout": { + "id": 3, + "nodeType": "StorageLayoutSpecifier", + "src": "71:16:0" + }, + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "36:53:0" + }, + "id": 0 + } + }, + "settings": { + "outputSelection": { + "*": { "*": [] } + } + } +} \ No newline at end of file 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 5ff4e7a190fc..16220fd619b0 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -84,6 +84,7 @@ object \"C_54\" { } function copy_arguments_for_constructor_20_object_C_54() -> ret_param_0 { + let programSize := datasize(\"C_54\") let argSize := sub(codesize(), programSize) @@ -850,6 +851,7 @@ object \"D_72\" { } function copy_arguments_for_constructor_71_object_D_72() -> ret_param_0 { + let programSize := datasize(\"D_72\") let argSize := sub(codesize(), programSize) diff --git a/test/cmdlineTests/standard_empty_file_name/output.json b/test/cmdlineTests/standard_empty_file_name/output.json index 1fd016e54e81..b4e525c21516 100644 --- a/test/cmdlineTests/standard_empty_file_name/output.json +++ b/test/cmdlineTests/standard_empty_file_name/output.json @@ -4,6 +4,10 @@ "component": "general", "errorCode": "2904", "formattedMessage": "DeclarationError: Declaration \"A\" not found in \"\" (referenced as \".\"). + --> :2:24: + | +2 | pragma solidity >=0.0; import {A} from \".\"; + | ^^^^^^^^^^^^^^^^^^^^ ", "message": "Declaration \"A\" not found in \"\" (referenced as \".\").", diff --git a/test/cmdlineTests/standard_eof_unavailable_before_osaka/input.json b/test/cmdlineTests/standard_eof_unavailable_before_osaka/input.json new file mode 100644 index 000000000000..071e711e6742 --- /dev/null +++ b/test/cmdlineTests/standard_eof_unavailable_before_osaka/input.json @@ -0,0 +1,10 @@ +{ + "language": "Solidity", + "sources": { + "C.sol": {"content": "contract C {}"} + }, + "settings": { + "eofVersion": 1, + "evmVersion": "cancun" + } +} diff --git a/test/cmdlineTests/standard_eof_unavailable_before_osaka/output.json b/test/cmdlineTests/standard_eof_unavailable_before_osaka/output.json new file mode 100644 index 000000000000..8b50700db35a --- /dev/null +++ b/test/cmdlineTests/standard_eof_unavailable_before_osaka/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "EOF is not supported by EVM versions earlier than osaka.", + "message": "EOF is not supported by EVM versions earlier than osaka.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/input.json b/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/input.json new file mode 100644 index 000000000000..12cac3b2c8d9 --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/input.json @@ -0,0 +1,10 @@ +{ + "language": "EVMAssembly", + "sources": { + "C.sol": {"assemblyJson": {}} + }, + "settings": { + "eofVersion": 1, + "evmVersion": "cancun" + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/output.json b/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/output.json new file mode 100644 index 000000000000..8b50700db35a --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "EOF is not supported by EVM versions earlier than osaka.", + "message": "EOF is not supported by EVM versions earlier than osaka.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json index cccd241d9416..14e502301f20 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json @@ -2,8 +2,8 @@ "errors": [ { "component": "general", - "formattedMessage": "Assembly import error: InvalidOpcode", - "message": "Assembly import error: InvalidOpcode", + "formattedMessage": "Assembly import error: Invalid opcode (INVALID_OPCODE)", + "message": "Assembly import error: Invalid opcode (INVALID_OPCODE)", "severity": "error", "type": "Exception" } diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json index eefa60785bb2..f4137ae42961 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json @@ -1,43 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "1218", - "formattedMessage": "Warning: CHC: Error trying to invoke SMT solver. - --> A:7:15: - | -7 | \t\t\t\t\t\treturn (a / b, a % b); - | \t\t\t\t\t\t ^^^^^ - -", - "message": "CHC: Error trying to invoke SMT solver.", - "severity": "warning", - "sourceLocation": { - "end": 182, - "file": "A", - "start": 177 - }, - "type": "Warning" - }, - { - "component": "general", - "errorCode": "1218", - "formattedMessage": "Warning: CHC: Error trying to invoke SMT solver. - --> A:7:22: - | -7 | \t\t\t\t\t\treturn (a / b, a % b); - | \t\t\t\t\t\t ^^^^^ - -", - "message": "CHC: Error trying to invoke SMT solver.", - "severity": "warning", - "sourceLocation": { - "end": 189, - "file": "A", - "start": 184 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "5840", diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json index 16fb77513081..8690a6e96cf1 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json @@ -1,43 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "1218", - "formattedMessage": "Warning: CHC: Error trying to invoke SMT solver. - --> A:7:15: - | -7 | \t\t\t\t\t\treturn (a / b, a % b); - | \t\t\t\t\t\t ^^^^^ - -", - "message": "CHC: Error trying to invoke SMT solver.", - "severity": "warning", - "sourceLocation": { - "end": 182, - "file": "A", - "start": 177 - }, - "type": "Warning" - }, - { - "component": "general", - "errorCode": "1218", - "formattedMessage": "Warning: CHC: Error trying to invoke SMT solver. - --> A:7:22: - | -7 | \t\t\t\t\t\treturn (a / b, a % b); - | \t\t\t\t\t\t ^^^^^ - -", - "message": "CHC: Error trying to invoke SMT solver.", - "severity": "warning", - "sourceLocation": { - "end": 189, - "file": "A", - "start": 184 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "5840", diff --git a/test/cmdlineTests/standard_model_checker_invariants_contract/output.json b/test/cmdlineTests/standard_model_checker_invariants_contract/output.json index f3cd0758c0ea..09d392567c3b 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_contract/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_contract/output.json @@ -14,12 +14,12 @@ "component": "general", "errorCode": "1180", "formattedMessage": "Info: Contract invariant(s) for A:test: -(!(x >= 1) || true) +(true || !(x >= 1)) ", "message": "Contract invariant(s) for A:test: -(!(x >= 1) || true) +(true || !(x >= 1)) ", "severity": "info", "type": "Info" diff --git a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/input.json b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/input.json index 38f658653641..e4c7c7bd004f 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/input.json +++ b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/input.json @@ -6,9 +6,8 @@ { "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract test { uint x; - function f(address _a) public { - _a.call(\"\"); - assert(x == 10); + function f() view public { + assert(x == 0); } }" } diff --git a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json index d46fdda8a917..b51effdcb322 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json @@ -2,59 +2,35 @@ "errors": [ { "component": "general", - "errorCode": "9302", - "formattedMessage": "Warning: Return value of low-level calls not used. - --> A:7:7: - | -7 | \t\t\t\t\t\t_a.call(\"\"); - | \t\t\t\t\t\t^^^^^^^^^^^ + "errorCode": "1391", + "formattedMessage": "Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "Return value of low-level calls not used.", - "severity": "warning", - "sourceLocation": { - "end": 143, - "file": "A", - "start": 132 - }, - "type": "Warning" + "message": "CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" }, { "component": "general", - "errorCode": "6328", - "formattedMessage": "Warning: CHC: Assertion violation happens here. -Counterexample: -x = 0 -_a = 0x0 + "errorCode": "1180", + "formattedMessage": "Info: Contract invariant(s) for A:test: +(true || !(x >= 1)) +Reentrancy property(ies) for A:test: +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) + = 0 -> no errors + = 1 -> Assertion failed at assert(x == 0) -Transaction trace: -test.constructor() -State: x = 0 -test.f(0x0) - _a.call(\"\") -- untrusted external call - --> A:8:7: - | -8 | \t\t\t\t\t\tassert(x == 10); - | \t\t\t\t\t\t^^^^^^^^^^^^^^^ ", - "message": "CHC: Assertion violation happens here. -Counterexample: -x = 0 -_a = 0x0 - -Transaction trace: -test.constructor() -State: x = 0 -test.f(0x0) - _a.call(\"\") -- untrusted external call", - "severity": "warning", - "sourceLocation": { - "end": 166, - "file": "A", - "start": 151 - }, - "type": "Warning" + "message": "Contract invariant(s) for A:test: +(true || !(x >= 1)) +Reentrancy property(ies) for A:test: +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) + = 0 -> no errors + = 1 -> Assertion failed at assert(x == 0) +", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/input.json b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/input.json index 1f98000b0ec3..2a3673fade2c 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/input.json +++ b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/input.json @@ -6,9 +6,8 @@ { "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract test { uint x; - function f(address _a) public { - _a.call(\"\"); - assert(x < 10); + function f() public { + assert(x == 0); } }" } diff --git a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json index 760f1d7a75ad..f1f37340e7d1 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json @@ -2,20 +2,20 @@ "errors": [ { "component": "general", - "errorCode": "9302", - "formattedMessage": "Warning: Return value of low-level calls not used. - --> A:7:7: + "errorCode": "2018", + "formattedMessage": "Warning: Function state mutability can be restricted to view + --> A:6:6: | -7 | \t\t\t\t\t\t_a.call(\"\"); - | \t\t\t\t\t\t^^^^^^^^^^^ +6 | \t\t\t\t\tfunction f() public { + | \t\t\t\t\t^ (Relevant source part starts here and spans across multiple lines). ", - "message": "Return value of low-level calls not used.", + "message": "Function state mutability can be restricted to view", "severity": "warning", "sourceLocation": { - "end": 143, + "end": 144, "file": "A", - "start": 132 + "start": 94 }, "type": "Warning" }, @@ -33,16 +33,16 @@ "component": "general", "errorCode": "1180", "formattedMessage": "Info: Reentrancy property(ies) for A:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors - = 1 -> Assertion failed at assert(x < 10) + = 1 -> Assertion failed at assert(x == 0) ", "message": "Reentrancy property(ies) for A:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors - = 1 -> Assertion failed at assert(x < 10) + = 1 -> Assertion failed at assert(x == 0) ", "severity": "info", "type": "Info" diff --git a/test/cmdlineTests/standard_model_checker_print_query_all/output.json b/test/cmdlineTests/standard_model_checker_print_query_all/output.json index a800fb34d7b6..85c4e142c383 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_all/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_all/output.json @@ -1,121 +1,4 @@ { - "auxiliaryInputRequested": { - "smtlib2queries": { - "0x54683263097e1c4f5e0e75b68e4ebe3e4f7042f899198181df911c8196a1725b": "(set-option :produce-models true) -(set-option :timeout 1000) -(set-logic ALL) -(declare-fun |x_5_3| () Int) -(declare-fun |error_0| () Int) -(declare-fun |this_0| () Int) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |tx_0| () |tx_type|) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-fun |crypto_0| () |crypto_type|) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-fun |abi_0| () |abi_type|) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |state_0| () |state_type|) -(declare-fun |x_5_4| () Int) -(declare-fun |x_5_0| () Int) -(declare-fun |expr_6_0| () Int) -(declare-fun |x_5_1| () Int) -(declare-fun |expr_9_0| () Int) -(declare-fun |expr_10_0| () Int) -(declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) -(declare-const |EVALEXPR_0| Int) -(assert (= |EVALEXPR_0| x_5_1)) -(check-sat) -(get-value (|EVALEXPR_0| )) -", - "0x9cfcd53712a0be144c8e7983b3635498ead1af2624885fb89762eae8c43233e5": "(set-option :timeout 1000) -(set-logic HORN) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) -) -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) -) -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) -) -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) -) -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) -) -(declare-fun |error_target_3| () Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) -)(assert -(forall ((UNUSED Bool)) -(=> error_target_3 false))) -(check-sat) -" - } - }, "errors": [ { "component": "general", @@ -130,7 +13,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -167,7 +50,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -195,7 +78,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -217,7 +100,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -254,7 +137,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -282,7 +165,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -305,16 +188,6 @@ "severity": "warning", "type": "Warning" }, - { - "component": "general", - "errorCode": "3996", - "formattedMessage": "Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. - -", - "message": "CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.", - "severity": "warning", - "type": "Warning" - }, { "component": "general", "errorCode": "6240", @@ -326,7 +199,7 @@ (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -342,7 +215,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -358,7 +231,7 @@ (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -374,7 +247,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -392,16 +265,6 @@ "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", "severity": "warning", "type": "Warning" - }, - { - "component": "general", - "errorCode": "8084", - "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. - -", - "message": "BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.", - "severity": "warning", - "type": "Warning" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json index cee9d4b9bf9c..21fdedc40918 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json @@ -1,34 +1,4 @@ { - "auxiliaryInputRequested": { - "smtlib2queries": { - "0x2bd3d35071b94d7536d10aad691cee810d94841cca10218c3be21255e258aeb7": "(set-option :produce-models true) -(set-logic ALL) -(declare-fun |error_0| () Int) -(declare-fun |this_0| () Int) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |tx_0| () |tx_type|) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-fun |crypto_0| () |crypto_type|) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-fun |abi_0| () |abi_type|) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |state_0| () |state_type|) -(declare-fun |x_5_0| () Int) -(declare-fun |expr_6_0| () Int) -(declare-fun |x_5_1| () Int) -(declare-fun |expr_9_0| () Int) -(declare-fun |expr_10_0| () Int) -(declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) -(declare-const |EVALEXPR_0| Int) -(assert (= |EVALEXPR_0| x_5_1)) -(check-sat) -(get-value (|EVALEXPR_0| )) -" - } - }, "errors": [ { "component": "general", @@ -39,7 +9,7 @@ (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -54,7 +24,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -68,7 +38,7 @@ (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -83,7 +53,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -101,16 +71,6 @@ "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", "severity": "warning", "type": "Warning" - }, - { - "component": "general", - "errorCode": "8084", - "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. - -", - "message": "BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.", - "severity": "warning", - "type": "Warning" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json index 9553a3cfb662..57c81ec50a47 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json @@ -1,92 +1,4 @@ { - "auxiliaryInputRequested": { - "smtlib2queries": { - "0x9cfcd53712a0be144c8e7983b3635498ead1af2624885fb89762eae8c43233e5": "(set-option :timeout 1000) -(set-logic HORN) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) -) -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) -) -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) -) -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) -) -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) -) -(declare-fun |error_target_3| () Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) -)(assert -(forall ((UNUSED Bool)) -(=> error_target_3 false))) -(check-sat) -" - } - }, "errors": [ { "component": "general", @@ -101,7 +13,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -138,7 +50,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -166,7 +78,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -188,7 +100,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -225,7 +137,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -253,7 +165,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -275,16 +187,6 @@ "message": "CHC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", "severity": "warning", "type": "Warning" - }, - { - "component": "general", - "errorCode": "3996", - "formattedMessage": "Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. - -", - "message": "CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.", - "severity": "warning", - "type": "Warning" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/input.json b/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/input.json deleted file mode 100644 index 0159c256e6ed..000000000000 --- a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/input.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n - contract C - { - function f() public pure { - uint x = 0; - assert(x == 0); - } - }" - } - }, - "settings": - { - "modelChecker": - { - "engine": "all", - "printQuery": true - } - } -} diff --git a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json b/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json deleted file mode 100644 index d675499f91db..000000000000 --- a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "Only SMTLib2 solver can be enabled to print queries", - "message": "Only SMTLib2 solver can be enabled to print queries", - "severity": "error", - "type": "JSONError" - } - ] -} diff --git a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/input.json b/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/input.json deleted file mode 100644 index 9ebda00174b4..000000000000 --- a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/input.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n - contract C - { - function f() public pure { - uint x = 0; - assert(x == 0); - } - }" - } - }, - "settings": - { - "modelChecker": - { - "engine": "all", - "printQuery": true, - "solvers": ["smtlib2", "z3"] - } - } -} diff --git a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json b/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json deleted file mode 100644 index d675499f91db..000000000000 --- a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "Only SMTLib2 solver can be enabled to print queries", - "message": "Only SMTLib2 solver can be enabled to print queries", - "severity": "error", - "type": "JSONError" - } - ] -} diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json index da3b3dcad888..de2c2aca05b7 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json @@ -12,13 +12,13 @@ }, { "component": "general", - "errorCode": "2788", - "formattedMessage": "Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json index da3b3dcad888..de2c2aca05b7 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json @@ -12,13 +12,13 @@ }, { "component": "general", - "errorCode": "2788", - "formattedMessage": "Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json index 67f8df731994..0f1ce4e39454 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json @@ -2,13 +2,13 @@ "errors": [ { "component": "general", - "errorCode": "2788", - "formattedMessage": "Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json index b6153de5ebe5..22c2a48193c1 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json @@ -21,28 +21,13 @@ }, { "component": "general", - "errorCode": "7812", - "formattedMessage": "Warning: BMC: Assertion violation might happen here. - --> A:11:7: - | -11 | \t\t\t\t\t\tassert(s.x > 0); - | \t\t\t\t\t\t^^^^^^^^^^^^^^^ -Note: + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: Assertion violation might happen here.", - "secondarySourceLocations": [ - { - "message": "" - } - ], - "severity": "warning", - "sourceLocation": { - "end": 201, - "file": "A", - "start": 186 - }, - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json index 6c3b57c79553..0f1ce4e39454 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json @@ -2,28 +2,13 @@ "errors": [ { "component": "general", - "errorCode": "7812", - "formattedMessage": "Warning: BMC: Assertion violation might happen here. - --> A:11:7: - | -11 | \t\t\t\t\t\tassert(s.x > 0); - | \t\t\t\t\t\t^^^^^^^^^^^^^^^ -Note: + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: Assertion violation might happen here.", - "secondarySourceLocations": [ - { - "message": "" - } - ], - "severity": "warning", - "sourceLocation": { - "end": 201, - "file": "A", - "start": 186 - }, - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/input.json b/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/input.json deleted file mode 100644 index e3a42c295f8c..000000000000 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/input.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract test { - struct S { - uint x; - } - S s; - function f(bool b) public { - s.x |= b ? 1 : 2; - assert(s.x > 0); - } - }" - } - }, - "settings": - { - "modelChecker": - { - "engine": "all", - "showUnsupported": false - } - } -} diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/output.json deleted file mode 100644 index fb599d21d2e4..000000000000 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/output.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "errors": - [ - { - "component": "general", - "errorCode": "5840", - "formattedMessage": "Warning: CHC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -", - "message": "CHC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" - }, - { - "component": "general", - "errorCode": "2788", - "formattedMessage": "Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -", - "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" - } - ], - "sources": - { - "A": - { - "id": 0 - } - } -} diff --git a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json index a3f4cc03d784..79037e2236bd 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json @@ -1,13 +1,13 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x51b9801f3e8e35f2ff5f4538b0636fae81aa84a482cbb486ae4db63bede5ecb5": "(set-option :produce-models true) + "0x1b1a2b4161df2f2869bdcd6ee320ef4c54aded9ae9c0441dd2dd4248f5616d97": "(set-option :produce-models true) (set-logic ALL) (declare-fun |x_3_3| () Int) (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -21,13 +21,13 @@ (declare-fun |expr_7_0| () Int) (declare-fun |expr_8_0| () Int) (declare-fun |expr_9_1| () Bool) -(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) +(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_3_0)) (check-sat) (get-value (|EVALEXPR_0| )) ", - "0xdb239809dcdaa42e35abca69790cb7e11b105f839e37faa8841f0dd9736688d7": "(set-logic HORN) + "0xd2654693bf2b4f42bfe922319928772b52430787451450fda29da1ebea716f19": "(set-logic HORN) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) @@ -35,7 +35,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_14| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_14| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_14 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -72,7 +72,7 @@ (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2))) +(=> (and (and (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) (=> (and (and (interface_0_C_14 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1))) @@ -100,7 +100,7 @@ (=> (and (and (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json new file mode 100644 index 000000000000..422a54f90d9f --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json @@ -0,0 +1,29 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "ir", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json new file mode 100644 index 000000000000..8f198f1f3adb --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json @@ -0,0 +1,1193 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + /// @src 0:58:123 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 + function constructor_A1_14() { + + /// @src 0:58:123 + + } + /// @src 0:58:123 + + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + /// @src 0:58:123 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @src 0:72:121 + function fun_a_13(var_x_3) { + + /// @src 0:112:113 + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 + let expr_8 := 0x00 + /// @src 0:112:117 + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 + assert_helper(expr_9) + + } + /// @src 0:58:123 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @src 0:72:121 + function fun_a(var_x) + { + /// @src 0:112:113 + let _1 := var_x + let expr := _1 + /// @src 0:116:117 + let expr_1 := 0x00 + /// @src 0:112:117 + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + /// @src 0:124:189 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 + function constructor_A2_27() { + + /// @src 0:124:189 + + } + /// @src 0:124:189 + + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + /// @src 0:124:189 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @src 0:138:187 + function fun_a_26(var_x_16) { + + /// @src 0:178:179 + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 + let expr_21 := 0x00 + /// @src 0:178:183 + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 + assert_helper(expr_22) + + } + /// @src 0:124:189 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @src 0:138:187 + function fun_a(var_x) + { + /// @src 0:178:179 + let _1 := var_x + let expr := _1 + /// @src 0:182:183 + let expr_1 := 0x00 + /// @src 0:178:183 + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + /// @src 1:58:123 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 + function constructor_A1_42() { + + /// @src 1:58:123 + + } + /// @src 1:58:123 + + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + /// @src 1:58:123 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @src 1:72:121 + function fun_b_41(var_x_31) { + + /// @src 1:112:113 + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 + let expr_36 := 0x00 + /// @src 1:112:117 + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 + assert_helper(expr_37) + + } + /// @src 1:58:123 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @src 1:72:121 + function fun_b(var_x) + { + /// @src 1:112:113 + let _1 := var_x + let expr := _1 + /// @src 1:116:117 + let expr_1 := 0x00 + /// @src 1:112:117 + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + /// @src 1:124:189 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 + function constructor_B2_55() { + + /// @src 1:124:189 + + } + /// @src 1:124:189 + + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + /// @src 1:124:189 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @src 1:138:187 + function fun_b_54(var_x_44) { + + /// @src 1:178:179 + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 + let expr_49 := 0x00 + /// @src 1:178:183 + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 + assert_helper(expr_50) + + } + /// @src 1:124:189 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @src 1:138:187 + function fun_b(var_x) + { + /// @src 1:178:179 + let _1 := var_x + let expr := _1 + /// @src 1:182:183 + let expr_1 := 0x00 + /// @src 1:178:183 + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/strip-ethdebug b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/input.json new file mode 100644 index 000000000000..8f8edcd29203 --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": { + "*": { + "*": [ + "evm.assembly" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json new file mode 100644 index 000000000000..963bcd8d7d68 --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "message": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json new file mode 100644 index 000000000000..8ed44ca05de2 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json new file mode 100644 index 000000000000..7694acea611c --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json @@ -0,0 +1,737 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_14() { + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 13 + /// @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_13(var_x_3) { + + /// @src 0:112:113 \"x\" + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 \"0\" + let expr_8 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_9) + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A2_27() { + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 26 + /// @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_26(var_x_16) { + + /// @src 0:178:179 \"x\" + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 \"0\" + let expr_21 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_22) + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_42() { + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 41 + /// @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_41(var_x_31) { + + /// @src 1:112:113 \"x\" + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 \"0\" + let expr_36 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_37) + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_B2_55() { + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 54 + /// @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_54(var_x_44) { + + /// @src 1:178:179 \"x\" + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 \"0\" + let expr_49 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_50) + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json new file mode 100644 index 000000000000..27c400f9e946 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json new file mode 100644 index 000000000000..b129a0c91b85 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json @@ -0,0 +1,517 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 13 @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:116:117 \"0\" + let expr_1 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 26 @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:182:183 \"0\" + let expr_1 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 41 @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:116:117 \"0\" + let expr_1 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 54 @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:182:183 \"0\" + let expr_1 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json new file mode 100644 index 000000000000..ad74649f5d1d --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/output.json new file mode 100644 index 000000000000..44867c7a75eb --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json new file mode 100644 index 000000000000..ad74649f5d1d --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/output.json new file mode 100644 index 000000000000..44867c7a75eb --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json new file mode 100644 index 000000000000..35c8f940e82d --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json new file mode 100644 index 000000000000..c7463f124184 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json @@ -0,0 +1,725 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_14() { + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 13 + /// @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_13(var_x_3) { + + /// @src 0:112:113 \"x\" + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 \"0\" + let expr_8 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_9) + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A2_27() { + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 26 + /// @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_26(var_x_16) { + + /// @src 0:178:179 \"x\" + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 \"0\" + let expr_21 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_22) + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_42() { + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 41 + /// @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_41(var_x_31) { + + /// @src 1:112:113 \"x\" + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 \"0\" + let expr_36 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_37) + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_B2_55() { + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 54 + /// @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_54(var_x_44) { + + /// @src 1:178:179 \"x\" + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 \"0\" + let expr_49 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_50) + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json new file mode 100644 index 000000000000..e4681967f7db --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json new file mode 100644 index 000000000000..eab40879c4c5 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json @@ -0,0 +1,505 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 13 @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:116:117 \"0\" + let expr_1 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 26 @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:182:183 \"0\" + let expr_1 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 41 @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:116:117 \"0\" + let expr_1 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 54 @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:182:183 \"0\" + let expr_1 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json new file mode 100644 index 000000000000..6239a7275e4d --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.deployedBytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json new file mode 100644 index 000000000000..8a8080833cf6 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json @@ -0,0 +1,725 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_14() { + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 13 + /// @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_13(var_x_3) { + + /// @src 0:112:113 \"x\" + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 \"0\" + let expr_8 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_9) + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "A2": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A2_27() { + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 26 + /// @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_26(var_x_16) { + + /// @src 0:178:179 \"x\" + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 \"0\" + let expr_21 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_22) + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + }, + "b.sol": { + "A1": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_42() { + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 41 + /// @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_41(var_x_31) { + + /// @src 1:112:113 \"x\" + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 \"0\" + let expr_36 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_37) + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "B2": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_B2_55() { + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 54 + /// @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_54(var_x_44) { + + /// @src 1:178:179 \"x\" + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 \"0\" + let expr_49 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_50) + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json new file mode 100644 index 000000000000..fdb6c95b813e --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.deployedBytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json new file mode 100644 index 000000000000..4f3bd68eed09 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json @@ -0,0 +1,505 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 13 @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:116:117 \"0\" + let expr_1 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 26 @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:182:183 \"0\" + let expr_1 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 41 @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:116:117 \"0\" + let expr_1 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 54 @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:182:183 \"0\" + let expr_1 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json new file mode 100644 index 000000000000..5bc9d5467345 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json new file mode 100644 index 000000000000..c7463f124184 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json @@ -0,0 +1,725 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_14() { + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 13 + /// @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_13(var_x_3) { + + /// @src 0:112:113 \"x\" + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 \"0\" + let expr_8 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_9) + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A2_27() { + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 26 + /// @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_26(var_x_16) { + + /// @src 0:178:179 \"x\" + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 \"0\" + let expr_21 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_22) + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_42() { + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 41 + /// @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_41(var_x_31) { + + /// @src 1:112:113 \"x\" + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 \"0\" + let expr_36 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_37) + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_B2_55() { + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 54 + /// @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_54(var_x_44) { + + /// @src 1:178:179 \"x\" + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 \"0\" + let expr_49 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_50) + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_ir/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json new file mode 100644 index 000000000000..8952a241f6e7 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json new file mode 100644 index 000000000000..eab40879c4c5 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json @@ -0,0 +1,505 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 13 @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:116:117 \"0\" + let expr_1 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 26 @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:182:183 \"0\" + let expr_1 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 41 @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:116:117 \"0\" + let expr_1 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 54 @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:182:183 \"0\" + let expr_1 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": "", + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/input.json new file mode 100644 index 000000000000..574a8b1c43cd --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/input.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/output.json new file mode 100644 index 000000000000..1329babc3dd7 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + "message": "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json new file mode 100644 index 000000000000..a684e0dc073b --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/output.json new file mode 100644 index 000000000000..44867c7a75eb --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json new file mode 100644 index 000000000000..1f09e3a70253 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/output.json new file mode 100644 index 000000000000..44867c7a75eb --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json index e0f4e37e6ae0..0fa7fcff3cda 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json @@ -54,10 +54,19 @@ "component": "general", "errorCode": "1284", "formattedMessage": "CodeGenerationError: Some immutables were read from but never assigned, possibly because of optimization. + --> C:4:1: + | +4 | contract C { + | ^ (Relevant source part starts here and spans across multiple lines). ", "message": "Some immutables were read from but never assigned, possibly because of optimization.", "severity": "error", + "sourceLocation": { + "end": 320, + "file": "C", + "start": 56 + }, "type": "CodeGenerationError" } ], diff --git a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/in.sol b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/in.sol new file mode 100644 index 000000000000..aae75b841ce0 --- /dev/null +++ b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/in.sol @@ -0,0 +1,10 @@ +contract C { + function f() public { + uint b; + abi.encodePacked( + b, b, b, b, b, b, b, b, + b, b, b, b, b, b, b, b, + b, b, b, b, b, b, b, b + ); + } +} diff --git a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json new file mode 100644 index 000000000000..a01e842b384d --- /dev/null +++ b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json @@ -0,0 +1,12 @@ +{ + "language": "Solidity", + "sources": { + "in.sol": {"urls": ["standard_stack_too_deep_from_code_transform/in.sol"]} + }, + "settings": { + "viaIR": true, + "outputSelection": { + "*": {"*": ["evm.bytecode"]} + } + } +} diff --git a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json new file mode 100644 index 000000000000..b4b0139fee69 --- /dev/null +++ b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json @@ -0,0 +1,29 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "YulException: Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] +memoryguard was present. + --> in.sol:1:1: + | +1 | contract C { + | ^ (Relevant source part starts here and spans across multiple lines). + +", + "message": "Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] +memoryguard was present.", + "severity": "error", + "sourceLocation": { + "end": 206, + "file": "in.sol", + "start": 0 + }, + "type": "YulException" + } + ], + "sources": { + "in.sol": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_undeployable_contract_all_outputs/in.sol b/test/cmdlineTests/standard_undeployable_contract_all_outputs/in.sol new file mode 100644 index 000000000000..80cc66cd19b7 --- /dev/null +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/in.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +abstract contract C {} +interface I {} diff --git a/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json new file mode 100644 index 000000000000..4d2aea1f147a --- /dev/null +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_undeployable_contract_all_outputs/in.sol"]} + }, + "settings": { + "outputSelection": { + "*": { + "*": ["*", "ir", "irAst", "irOptimized", "irOptimizedAst"] + } + } + } +} diff --git a/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json new file mode 100644 index 000000000000..3869f7c652bd --- /dev/null +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json @@ -0,0 +1,109 @@ +{ + "contracts": { + "C": { + "C": { + "abi": [], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "evm": { + "assembly": "", + "bytecode": { + "functionDebugData": {}, + "generatedSources": [], + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "deployedBytecode": { + "functionDebugData": {}, + "generatedSources": [], + "immutableReferences": {}, + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "gasEstimates": null, + "legacyAssembly": null, + "methodIdentifiers": {} + }, + "ir": "", + "irAst": null, + "irOptimized": "", + "irOptimizedAst": null, + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "transientStorageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + }, + "I": { + "abi": [], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "evm": { + "assembly": "", + "bytecode": { + "functionDebugData": {}, + "generatedSources": [], + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "deployedBytecode": { + "functionDebugData": {}, + "generatedSources": [], + "immutableReferences": {}, + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "gasEstimates": null, + "legacyAssembly": null, + "methodIdentifiers": {} + }, + "ir": "", + "irAst": null, + "irOptimized": "", + "irOptimizedAst": null, + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"I\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "transientStorageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_viair_requested/output.json b/test/cmdlineTests/standard_viair_requested/output.json index 0105ea97298a..133815b97dd7 100644 --- a/test/cmdlineTests/standard_viair_requested/output.json +++ b/test/cmdlineTests/standard_viair_requested/output.json @@ -201,6 +201,7 @@ object \"D_16\" { function fun_f_15() { /// @src 0:134:141 \"new C()\" + let _1 := allocate_unbounded() let _2 := add(_1, datasize(\"C_3\")) if or(gt(_2, 0xffffffffffffffff), lt(_2, _1)) { panic_error_0x41() } diff --git a/test/cmdlineTests/standard_yul/output.json b/test/cmdlineTests/standard_yul/output.json index 30fe1dd7ecb7..a72904ee6c31 100644 --- a/test/cmdlineTests/standard_yul/output.json +++ b/test/cmdlineTests/standard_yul/output.json @@ -18,7 +18,6 @@ ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/in.sol b/test/cmdlineTests/standard_yul_cfg_json_export/in.sol new file mode 100644 index 000000000000..85691014f827 --- /dev/null +++ b/test/cmdlineTests/standard_yul_cfg_json_export/in.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +interface I { + function f() external pure returns (uint); +} + +contract C is I { + function f() public pure override returns (uint) { + return 42; + } +} + +contract D { + function f() public returns (uint) { + C c = new C(); + return c.f(); + } +} diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/input.json b/test/cmdlineTests/standard_yul_cfg_json_export/input.json new file mode 100644 index 000000000000..aee56abf8600 --- /dev/null +++ b/test/cmdlineTests/standard_yul_cfg_json_export/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_yul_cfg_json_export/in.sol"]} + }, + "settings": { + "optimizer": { + "enabled": true + }, + "viaIR": true, + "outputSelection": {"*": {"*": ["yulCFGJson"]}} + } +} diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json new file mode 100644 index 000000000000..303d51bbbbf4 --- /dev/null +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -0,0 +1,2140 @@ +{ + "contracts": { + "C": { + "C": { + "yulCFGJson": { + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": {} + }, + "type": "subObject" + } + }, + "type": "Object" + } + }, + "D": { + "yulCFGJson": { + "D_38": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "D_38_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v28", + "targets": [ + "Block12", + "Block11" + ], + "type": "ConditionalJump" + }, + "id": "Block9", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "datasize", + "out": [ + "v18" + ] + }, + { + "in": [ + "v18", + "v0" + ], + "op": "add", + "out": [ + "v24" + ] + }, + { + "in": [ + "v0", + "v24" + ], + "op": "lt", + "out": [ + "v25" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v24" + ], + "op": "gt", + "out": [ + "v27" + ] + }, + { + "in": [ + "v25", + "v27" + ], + "op": "or", + "out": [ + "v28" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0", + "v18", + "v24" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v42", + "targets": [ + "Block15", + "Block14" + ], + "type": "ConditionalJump" + }, + "id": "Block12", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v35" + ] + }, + { + "in": [ + "v18", + "v35", + "v0" + ], + "op": "datacopy", + "out": [] + }, + { + "in": [ + "v0", + "v24" + ], + "op": "sub", + "out": [ + "v40" + ] + }, + { + "in": [ + "v40", + "v0", + "0x00" + ], + "op": "create", + "out": [ + "v41" + ] + }, + { + "in": [ + "v41" + ], + "op": "iszero", + "out": [ + "v42" + ] + } + ], + "liveness": { + "in": [ + "v0", + "v18", + "v24" + ], + "out": [ + "v41" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block11", + "instructions": [ + { + "in": [ + "0x4e487b71", + "0xe0" + ], + "op": "shl", + "out": [ + "v30" + ] + }, + { + "in": [ + "v30", + "0x00" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v60", + "targets": [ + "Block18", + "Block17" + ], + "type": "ConditionalJump" + }, + "id": "Block15", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v46" + ] + }, + { + "in": [ + "0x026121ff", + "0xe4" + ], + "op": "shl", + "out": [ + "v49" + ] + }, + { + "in": [ + "v49", + "v46" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x01", + "0xa0" + ], + "op": "shl", + "out": [ + "v53" + ] + }, + { + "in": [ + "0x01", + "v53" + ], + "op": "sub", + "out": [ + "v54" + ] + }, + { + "in": [ + "v54", + "v41" + ], + "op": "and", + "out": [ + "v57" + ] + }, + { + "in": [], + "op": "gas", + "out": [ + "v58" + ] + }, + { + "in": [ + "0x20", + "v46", + "0x04", + "v46", + "v57", + "v58" + ], + "op": "staticcall", + "out": [ + "v59" + ] + }, + { + "in": [ + "v59" + ], + "op": "iszero", + "out": [ + "v60" + ] + } + ], + "liveness": { + "in": [ + "v41" + ], + "out": [ + "v46", + "v59" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block14", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v43" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v44" + ] + }, + { + "in": [ + "v44", + "0x00", + "v43" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v45" + ] + }, + { + "in": [ + "v45", + "v43" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v59", + "targets": [ + "Block21", + "Block20" + ], + "type": "ConditionalJump" + }, + "id": "Block18", + "instructions": [], + "liveness": { + "in": [ + "v46", + "v59" + ], + "out": [ + "v46" + ] + } + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block17", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v61" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v62" + ] + }, + { + "in": [ + "v62", + "0x00", + "v61" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v63" + ] + }, + { + "in": [ + "v63", + "v61" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "entries": [ + "Block18", + "Block28" + ], + "exit": { + "type": "Terminated" + }, + "id": "Block21", + "instructions": [ + { + "in": [ + "0x00", + "v93" + ], + "op": "PhiFunction", + "out": [ + "v95" + ] + }, + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v94" + ] + }, + { + "in": [ + "v95", + "v94" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v94" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v95" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v67", + "targets": [ + "Block23", + "Block22" + ], + "type": "ConditionalJump" + }, + "id": "Block20", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v66" + ] + }, + { + "in": [ + "v66", + "0x20" + ], + "op": "gt", + "out": [ + "v67" + ] + } + ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46" + ] + }, + "type": "BuiltinCall" + }, + { + "entries": [ + "Block20", + "Block22" + ], + "exit": { + "cond": "v80", + "targets": [ + "Block25", + "Block24" + ], + "type": "ConditionalJump" + }, + "id": "Block23", + "instructions": [ + { + "in": [ + "0x20", + "v68" + ], + "op": "PhiFunction", + "out": [ + "v71" + ] + }, + { + "in": [ + "0x1f" + ], + "op": "not", + "out": [ + "v70" + ] + }, + { + "in": [ + "0x1f", + "v71" + ], + "op": "add", + "out": [ + "v72" + ] + }, + { + "in": [ + "v70", + "v72" + ], + "op": "and", + "out": [ + "v73" + ] + }, + { + "in": [ + "v73", + "v46" + ], + "op": "add", + "out": [ + "v77" + ] + }, + { + "in": [ + "v46", + "v77" + ], + "op": "lt", + "out": [ + "v78" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v77" + ], + "op": "gt", + "out": [ + "v79" + ] + }, + { + "in": [ + "v78", + "v79" + ], + "op": "or", + "out": [ + "v80" + ] + } + ], + "liveness": { + "in": [ + "v46", + "v71" + ], + "out": [ + "v46", + "v71", + "v77" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block23" + ], + "type": "Jump" + }, + "id": "Block22", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v68" + ] + } + ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46", + "v68" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v90", + "targets": [ + "Block28", + "Block27" + ], + "type": "ConditionalJump" + }, + "id": "Block25", + "instructions": [ + { + "in": [ + "v77", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "v71", + "v46" + ], + "op": "add", + "out": [ + "v88" + ] + }, + { + "in": [ + "v46", + "v88" + ], + "op": "sub", + "out": [ + "v89" + ] + }, + { + "in": [ + "0x20", + "v89" + ], + "op": "slt", + "out": [ + "v90" + ] + } + ], + "liveness": { + "in": [ + "v46", + "v71", + "v77" + ], + "out": [ + "v46" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block24", + "instructions": [ + { + "in": [ + "0x4e487b71", + "0xe0" + ], + "op": "shl", + "out": [ + "v81" + ] + }, + { + "in": [ + "v81", + "0x00" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block21" + ], + "type": "Jump" + }, + "id": "Block28", + "instructions": [ + { + "in": [ + "v46" + ], + "op": "mload", + "out": [ + "v93" + ] + } + ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v93" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block27", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": {} + }, + "type": "subObject" + } + }, + "type": "subObject" + } + }, + "type": "subObject" + } + }, + "type": "Object" + } + }, + "I": { + "yulCFGJson": null + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_yul_code_generation_error/args b/test/cmdlineTests/standard_yul_code_generation_error/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_code_generation_error/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_code_generation_error/in.yul b/test/cmdlineTests/standard_yul_code_generation_error/in.yul new file mode 100644 index 000000000000..2bf18f0c6d4d --- /dev/null +++ b/test/cmdlineTests/standard_yul_code_generation_error/in.yul @@ -0,0 +1,9 @@ +object "C" { + code {} + + object "C_deployed" { + code { + sstore(0, loadimmutable("1")) + } + } +} diff --git a/test/cmdlineTests/standard_yul_code_generation_error/input.json b/test/cmdlineTests/standard_yul_code_generation_error/input.json new file mode 100644 index 000000000000..905eef6c758a --- /dev/null +++ b/test/cmdlineTests/standard_yul_code_generation_error/input.json @@ -0,0 +1,6 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_code_generation_error/in.yul"]} + } +} diff --git a/test/cmdlineTests/standard_yul_code_generation_error/output.json b/test/cmdlineTests/standard_yul_code_generation_error/output.json new file mode 100644 index 000000000000..9bd38bbacf31 --- /dev/null +++ b/test/cmdlineTests/standard_yul_code_generation_error/output.json @@ -0,0 +1,13 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "CodeGenerationError: Some immutables were read from but never assigned, possibly because of optimization. + +", + "message": "Some immutables were read from but never assigned, possibly because of optimization.", + "severity": "error", + "type": "CodeGenerationError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/args b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/in.yul b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/in.yul new file mode 100644 index 000000000000..aa564d00ce86 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/in.yul @@ -0,0 +1,16 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json new file mode 100644 index 000000000000..3e5b81c5ef69 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json @@ -0,0 +1,16 @@ +{ + "language": "Yul", + "sources": { + "C": { + "urls": [ + "standard_yul_debug_info_ethdebug_compatible_output/in.yul" + ] + } + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "outputSelection": { + "*": {"*": ["ir", "irOptimized", "evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json new file mode 100644 index 000000000000..2b2f395fadd4 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json @@ -0,0 +1,42 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { sstore(0, 42) } + } +} +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + fun_f() + } + /// @src 0:77:99 + function fun_f() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/strip-ethdebug b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/args b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul new file mode 100644 index 000000000000..aa564d00ce86 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul @@ -0,0 +1,16 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json new file mode 100644 index 000000000000..f05e6f361aca --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json @@ -0,0 +1,16 @@ +{ + "language": "Yul", + "sources": { + "C": { + "urls": [ + "standard_yul_debug_info_ethdebug_incompatible_output/in.yul" + ] + } + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "outputSelection": { + "*": {"*": ["evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json new file mode 100644 index 000000000000..963bcd8d7d68 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "message": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/args b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul new file mode 100644 index 000000000000..182cdc75ddc9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul @@ -0,0 +1,11 @@ +{ + let x := 2 + let y := sub(x, 2) + let t := verbatim_2i_1o("abc", x, y) + sstore(t, x) + let r := verbatim_0i_1o("def") + verbatim_0i_0o("xyz") + // more than 32 bytes + verbatim_0i_0o(hex"01020304050607090001020304050607090001020304050607090001020102030405060709000102030405060709000102030405060709000102") + r := 9 +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json new file mode 100644 index 000000000000..be4fbb64fce3 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json @@ -0,0 +1,16 @@ +{ + "language": "Yul", + "sources": { + "C": { + "urls": [ + "standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul" + ] + } + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/output.json new file mode 100644 index 000000000000..b645222de390 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/output.json @@ -0,0 +1,13 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "UnimplementedFeatureError: Verbatim bytecode is currently not supported by ethdebug. + +", + "message": "Verbatim bytecode is currently not supported by ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/input.json b/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/input.json new file mode 100644 index 000000000000..125792d0910a --- /dev/null +++ b/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/input.json @@ -0,0 +1,10 @@ +{ + "language": "Yul", + "sources": { + "C.yul": {"content": "{}"} + }, + "settings": { + "eofVersion": 1, + "evmVersion": "cancun" + } +} diff --git a/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/output.json b/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/output.json new file mode 100644 index 000000000000..8b50700db35a --- /dev/null +++ b/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "EOF is not supported by EVM versions earlier than osaka.", + "message": "EOF is not supported by EVM versions earlier than osaka.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/args b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/in.yul b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/in.yul new file mode 100644 index 000000000000..5c098cc80569 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/in.yul @@ -0,0 +1,7 @@ +object "a" { + code { + { + setimmutable(0, "long___name___that___definitely___exceeds___the___thirty___two___byte___limit", 0x1234567890123456789012345678901234567890) + } + } +} \ No newline at end of file diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json new file mode 100644 index 000000000000..83acd4c42085 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_assign_immutable/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json new file mode 100644 index 000000000000..3af82e21d392 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json @@ -0,0 +1,127 @@ +{ + "contracts": { + "C": { + "a": { + "evm": { + "bytecode": { + "ethdebug": { + "contract": { + "definition": { + "source": { + "id": 0 + } + }, + "name": "" + }, + "environment": "create", + "instructions": [ + { + "context": { + "code": { + "range": { + "length": 42, + "offset": 165 + }, + "source": { + "id": 0 + } + } + }, + "offset": 0, + "operation": { + "arguments": [ + "0x1234567890123456789012345678901234567890" + ], + "mnemonic": "PUSH20" + } + }, + { + "context": { + "code": { + "range": { + "length": 1, + "offset": 81 + }, + "source": { + "id": 0 + } + } + }, + "offset": 21, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 140, + "offset": 68 + }, + "source": { + "id": 0 + } + } + }, + "offset": 22, + "operation": { + "mnemonic": "POP" + } + }, + { + "context": { + "code": { + "range": { + "length": 140, + "offset": 68 + }, + "source": { + "id": 0 + } + } + }, + "offset": 23, + "operation": { + "mnemonic": "POP" + } + }, + { + "context": { + "code": { + "range": { + "length": 180, + "offset": 44 + }, + "source": { + "id": 0 + } + } + }, + "offset": 24, + "operation": { + "mnemonic": "STOP" + } + } + ] + } + } + } + } + } + }, + "ethdebug": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "C" + } + ] + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/args b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/in.yul b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/in.yul new file mode 100644 index 000000000000..920aef8e9dc2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json new file mode 100644 index 000000000000..abfb7ee863af --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_bytecode_ir/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "ir"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json new file mode 100644 index 000000000000..c1f6523d5388 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json @@ -0,0 +1,27 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/args b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/in.yul b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/in.yul new file mode 100644 index 000000000000..920aef8e9dc2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json new file mode 100644 index 000000000000..54094c67305f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_bytecode_iroptimized/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "irOptimized"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json new file mode 100644 index 000000000000..2f1d22b4df0f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json @@ -0,0 +1,29 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + fun_f() + } + /// @src 0:77:99 + function fun_f() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/args b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul new file mode 100644 index 000000000000..d5adfd0c28f4 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul @@ -0,0 +1,19 @@ +object "object" { + code { + mstore(64, 128) + fun_f_5() + function fun_f_5() { + sstore(0, 42) + } + } + + object "object_deployed" { + code { + mstore(64, 128) + fun_f_5() + function fun_f_5() { + sstore(0, 42) + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json new file mode 100644 index 000000000000..e222dfeda8c2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_deployed_bytecode/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.deployedBytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json new file mode 100644 index 000000000000..44183e45fdde --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json @@ -0,0 +1,14 @@ +{ + "contracts": { + "C": { + "object": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + } + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/args b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/in.yul b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/in.yul new file mode 100644 index 000000000000..d5adfd0c28f4 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/in.yul @@ -0,0 +1,19 @@ +object "object" { + code { + mstore(64, 128) + fun_f_5() + function fun_f_5() { + sstore(0, 42) + } + } + + object "object_deployed" { + code { + mstore(64, 128) + fun_f_5() + function fun_f_5() { + sstore(0, 42) + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json new file mode 100644 index 000000000000..20779012030d --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_deployed_bytecode/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.deployedBytecode.ethdebug", "evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/output.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/output.json new file mode 100644 index 000000000000..6d8064a94f36 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/output.json @@ -0,0 +1,17 @@ +{ + "contracts": { + "C": { + "object": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + } + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/args b/test/cmdlineTests/standard_yul_ethdebug_ir/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/in.yul b/test/cmdlineTests/standard_yul_ethdebug_ir/in.yul new file mode 100644 index 000000000000..920aef8e9dc2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json new file mode 100644 index 000000000000..3153a378db84 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_ir/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "ir"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/output.json b/test/cmdlineTests/standard_yul_ethdebug_ir/output.json new file mode 100644 index 000000000000..c1f6523d5388 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/output.json @@ -0,0 +1,27 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_ir/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/args b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/in.yul b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/in.yul new file mode 100644 index 000000000000..920aef8e9dc2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json new file mode 100644 index 000000000000..180abcf31f8d --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_iroptimize/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "irOptimize"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json new file mode 100644 index 000000000000..6323c1157973 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json @@ -0,0 +1,14 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": "" + } + } + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/strip-ethdebug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/args b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/in.yul b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/in.yul new file mode 100644 index 000000000000..920aef8e9dc2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json new file mode 100644 index 000000000000..9f0c8b0d5cef --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json @@ -0,0 +1,14 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_optimize_ir/in.yul"]} + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "ir"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/output.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/output.json new file mode 100644 index 000000000000..44867c7a75eb --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/args b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/in.yul b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/in.yul new file mode 100644 index 000000000000..920aef8e9dc2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json new file mode 100644 index 000000000000..81b637abd5b5 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json @@ -0,0 +1,14 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_optimize_iroptimized/in.yul"]} + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "irOptimized"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/output.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/output.json new file mode 100644 index 000000000000..44867c7a75eb --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_immutable_references/output.json b/test/cmdlineTests/standard_yul_immutable_references/output.json index 7bfbb076a389..3f82bcbaab54 100644 --- a/test/cmdlineTests/standard_yul_immutable_references/output.json +++ b/test/cmdlineTests/standard_yul_immutable_references/output.json @@ -5,7 +5,6 @@ "evm": { "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", @@ -13,7 +12,6 @@ }, "deployedBytecode": { "functionDebugData": {}, - "generatedSources": [], "immutableReferences": { "test": [ { diff --git a/test/cmdlineTests/standard_yul_object/output.json b/test/cmdlineTests/standard_yul_object/output.json index 3181da426000..c1bb2eb3eb6d 100644 --- a/test/cmdlineTests/standard_yul_object/output.json +++ b/test/cmdlineTests/standard_yul_object/output.json @@ -19,7 +19,6 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/standard_yul_object_name/output.json b/test/cmdlineTests/standard_yul_object_name/output.json index 1512900e1c85..2b6dc1f73e85 100644 --- a/test/cmdlineTests/standard_yul_object_name/output.json +++ b/test/cmdlineTests/standard_yul_object_name/output.json @@ -27,7 +27,6 @@ sub_0: assembly { ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", @@ -35,7 +34,6 @@ sub_0: assembly { }, "deployedBytecode": { "functionDebugData": {}, - "generatedSources": [], "immutableReferences": {}, "linkReferences": {}, "object": "", diff --git a/test/cmdlineTests/standard_yul_optimiserSteps/output.json b/test/cmdlineTests/standard_yul_optimiserSteps/output.json index 2a654d20a9cb..621a029076e2 100644 --- a/test/cmdlineTests/standard_yul_optimiserSteps/output.json +++ b/test/cmdlineTests/standard_yul_optimiserSteps/output.json @@ -15,7 +15,6 @@ ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/standard_yul_optimized/output.json b/test/cmdlineTests/standard_yul_optimized/output.json index 513f8148a0f9..ad0e9f40aa1f 100644 --- a/test/cmdlineTests/standard_yul_optimized/output.json +++ b/test/cmdlineTests/standard_yul_optimized/output.json @@ -15,7 +15,6 @@ ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/standard_yul_output_warning/output.json b/test/cmdlineTests/standard_yul_output_warning/output.json index 3234be1817fd..514280afcc80 100644 --- a/test/cmdlineTests/standard_yul_output_warning/output.json +++ b/test/cmdlineTests/standard_yul_output_warning/output.json @@ -19,7 +19,6 @@ ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/args b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/args new file mode 100644 index 000000000000..3cf20d57b0b8 --- /dev/null +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/args @@ -0,0 +1 @@ +- \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err new file mode 100644 index 000000000000..6d5d1dc46c36 --- /dev/null +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err @@ -0,0 +1,10 @@ +Error: Cannot inherit from a contract with a custom storage layout. + --> :5:15: + | +5 | contract B is A {} + | ^ +Note: Custom storage layout defined here: + --> :4:12: + | +4 | contract A layout at 0x1234 {} + | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/exit b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/exit new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/stdin b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/stdin new file mode 100644 index 000000000000..a340f7530003 --- /dev/null +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/stdin @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +contract A layout at 0x1234 {} +contract B is A {} +contract C layout at 0x1234 is B {} diff --git a/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/args b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/args new file mode 100644 index 000000000000..3cf20d57b0b8 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/args @@ -0,0 +1 @@ +- \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/err b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/err new file mode 100644 index 000000000000..983a9b92cd9d --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/err @@ -0,0 +1,10 @@ +Error: More than one storage layout definition. + --> :5:34: + | +5 | contract C layout at 0x1234 is A layout at 0xABCD { + | ^^^^^^ +Note: Previous definition: + --> :5:12: + | +5 | contract C layout at 0x1234 is A layout at 0xABCD { + | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/exit b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/exit new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/stdin b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/stdin new file mode 100644 index 000000000000..fc2ea9c9bad1 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/stdin @@ -0,0 +1,6 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract A { +} +contract C layout at 0x1234 is A layout at 0xABCD { +} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_smoke/args b/test/cmdlineTests/storage_layout_specifier_smoke/args new file mode 100644 index 000000000000..b207f3babd3e --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke/args @@ -0,0 +1 @@ +--no-cbor-metadata --optimize --asm --debug-info none - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_smoke/output b/test/cmdlineTests/storage_layout_specifier_smoke/output new file mode 100644 index 000000000000..d1c54c99b7d0 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke/output @@ -0,0 +1,85 @@ + +======= :C ======= +EVM assembly: + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + revert(0x00, 0x00) + tag_3: + tag_4 + tag_5 + jump // in + tag_4: + stop + tag_5: + sload(0x0abc) + tag_7 + swap1 + 0x01 + tag_8 + jump // in + tag_7: + 0x0abc + sstore + jump // out + tag_8: + dup1 + dup3 + add + dup1 + dup3 + gt + iszero + tag_11 + jumpi + 0x4e487b71 + 0xe0 + shl + 0x00 + mstore + 0x11 + 0x04 + mstore + 0x24 + 0x00 + revert + tag_11: + swap3 + swap2 + pop + pop + jump // out +} diff --git a/test/cmdlineTests/storage_layout_specifier_smoke/stdin b/test/cmdlineTests/storage_layout_specifier_smoke/stdin new file mode 100644 index 000000000000..7e6575feffb2 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke/stdin @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C layout at 0xABC { + uint x; + function f() public { + x = x + 1; + } +} diff --git a/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/args b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/args new file mode 100644 index 000000000000..9ad276caf3e4 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/args @@ -0,0 +1 @@ +--optimize --ir-optimized --debug-info none - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/output b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/output new file mode 100644 index 000000000000..de5fd53748d4 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/output @@ -0,0 +1,20 @@ +Optimized IR: +/// @use-src 0:"" +object "C_7" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + sstore(0x2a, 0x0a) + let _2 := datasize("C_7_deployed") + codecopy(_1, dataoffset("C_7_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"" + object "C_7_deployed" { + code { { revert(0, 0) } } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/stdin b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/stdin new file mode 100644 index 000000000000..c3dbe062ff30 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/stdin @@ -0,0 +1,6 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C layout at 42 { + uint x = 10; +} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output/args b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/args new file mode 100644 index 000000000000..b8163df7a36d --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/args @@ -0,0 +1 @@ +--storage-layout --transient-storage-layout --pretty-json --json-indent 4 - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output/output b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/output new file mode 100644 index 000000000000..7e5e61de0edb --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/output @@ -0,0 +1,435 @@ + +======= :A ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 3, + "contract": ":A", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 7, + "contract": ":A", + "label": "y", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 5, + "contract": ":A", + "label": "t1", + "offset": 0, + "slot": "0", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= :B ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 12, + "contract": ":B", + "label": "w", + "offset": 0, + "slot": "0", + "type": "t_int8" + } + ], + "types": { + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 10, + "contract": ":B", + "label": "t2", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 14, + "contract": ":B", + "label": "t3", + "offset": 0, + "slot": "1", + "type": "t_int8" + } + ], + "types": { + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= :C ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 12, + "contract": ":C", + "label": "w", + "offset": 0, + "slot": "0", + "type": "t_int8" + }, + { + "astId": 19, + "contract": ":C", + "label": "z", + "offset": 1, + "slot": "0", + "type": "t_uint128" + }, + { + "astId": 21, + "contract": ":C", + "label": "b", + "offset": 17, + "slot": "0", + "type": "t_bool" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 10, + "contract": ":C", + "label": "t2", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 14, + "contract": ":C", + "label": "t3", + "offset": 0, + "slot": "1", + "type": "t_int8" + }, + { + "astId": 23, + "contract": ":C", + "label": "t4", + "offset": 1, + "slot": "1", + "type": "t_bool" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= :D ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 3, + "contract": ":D", + "label": "x", + "offset": 0, + "slot": "100", + "type": "t_uint256" + }, + { + "astId": 7, + "contract": ":D", + "label": "y", + "offset": 0, + "slot": "101", + "type": "t_uint256" + }, + { + "astId": 12, + "contract": ":D", + "label": "w", + "offset": 0, + "slot": "102", + "type": "t_int8" + }, + { + "astId": 19, + "contract": ":D", + "label": "z", + "offset": 1, + "slot": "102", + "type": "t_uint128" + }, + { + "astId": 21, + "contract": ":D", + "label": "b", + "offset": 17, + "slot": "102", + "type": "t_bool" + }, + { + "astId": 32, + "contract": ":D", + "label": "addr", + "offset": 0, + "slot": "103", + "type": "t_address" + }, + { + "astId": 38, + "contract": ":D", + "label": "array", + "offset": 0, + "slot": "104", + "type": "t_array(t_uint256)2_storage" + }, + { + "astId": 42, + "contract": ":D", + "label": "m", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_uint256,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)2_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[2]", + "numberOfBytes": "64" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_mapping(t_uint256,t_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 5, + "contract": ":D", + "label": "t1", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 10, + "contract": ":D", + "label": "t2", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 14, + "contract": ":D", + "label": "t3", + "offset": 0, + "slot": "2", + "type": "t_int8" + }, + { + "astId": 23, + "contract": ":D", + "label": "t4", + "offset": 1, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 34, + "contract": ":D", + "label": "t5", + "offset": 2, + "slot": "2", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= :P ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 3, + "contract": ":P", + "label": "x", + "offset": 0, + "slot": "200", + "type": "t_uint256" + }, + { + "astId": 7, + "contract": ":P", + "label": "y", + "offset": 0, + "slot": "201", + "type": "t_uint256" + }, + { + "astId": 49, + "contract": ":P", + "label": "q", + "offset": 0, + "slot": "202", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 5, + "contract": ":P", + "label": "t1", + "offset": 0, + "slot": "0", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output/stdin b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/stdin new file mode 100644 index 000000000000..ac391d192eb5 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/stdin @@ -0,0 +1,31 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +abstract contract A { + uint x; + uint transient t1; + uint y; +} + +contract B { + uint transient t2; + int8 w; + int8 transient t3; +} + +contract C is B { + uint128 z; + bool b; + bool transient t4; +} + +contract D is A, C layout at 100 { + address addr; + address transient t5; + uint[2] array; + mapping(uint => address) m; +} + +contract P is A layout at 200 { + uint q; +} \ No newline at end of file diff --git a/test/cmdlineTests/strict_asm_code_generation_error/args b/test/cmdlineTests/strict_asm_code_generation_error/args new file mode 100644 index 000000000000..47be2b30ed16 --- /dev/null +++ b/test/cmdlineTests/strict_asm_code_generation_error/args @@ -0,0 +1 @@ +--strict-assembly --bin diff --git a/test/cmdlineTests/strict_asm_code_generation_error/err b/test/cmdlineTests/strict_asm_code_generation_error/err new file mode 100644 index 000000000000..31af508c7b40 --- /dev/null +++ b/test/cmdlineTests/strict_asm_code_generation_error/err @@ -0,0 +1 @@ +Error: Some immutables were read from but never assigned, possibly because of optimization. diff --git a/test/cmdlineTests/strict_asm_code_generation_error/exit b/test/cmdlineTests/strict_asm_code_generation_error/exit new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/test/cmdlineTests/strict_asm_code_generation_error/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/strict_asm_code_generation_error/input.yul b/test/cmdlineTests/strict_asm_code_generation_error/input.yul new file mode 100644 index 000000000000..2bf18f0c6d4d --- /dev/null +++ b/test/cmdlineTests/strict_asm_code_generation_error/input.yul @@ -0,0 +1,9 @@ +object "C" { + code {} + + object "C_deployed" { + code { + sstore(0, loadimmutable("1")) + } + } +} diff --git a/test/cmdlineTests/strict_asm_eof_container_osaka/args b/test/cmdlineTests/strict_asm_eof_container_osaka/args new file mode 100644 index 000000000000..60abde356339 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_container_osaka/args @@ -0,0 +1 @@ + --strict-assembly --experimental-eof-version 1 --evm-version osaka --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/input.yul b/test/cmdlineTests/strict_asm_eof_container_osaka/input.yul similarity index 50% rename from test/cmdlineTests/strict_asm_eof_container_prague/input.yul rename to test/cmdlineTests/strict_asm_eof_container_osaka/input.yul index 09306772c9a9..d4d9190ff68d 100644 --- a/test/cmdlineTests/strict_asm_eof_container_prague/input.yul +++ b/test/cmdlineTests/strict_asm_eof_container_osaka/input.yul @@ -1,33 +1,34 @@ object "object" { code { - revert(0, 0) + mstore(0, eofcreate("sub0", 0, 0, 0, 0)) + mstore(32, eofcreate("sub1", 0, 0, 0, 0)) + return(0, 64) } object "sub0" { code { - mstore(0, 0) - revert(0, 32) + returncontract("sub00", 0, 0) } - } - object "sub1" { - code { - mstore(0, 1) - revert(0, 32) + object "sub00" { + code { + mstore(0, 1) + revert(0, 32) + } } } - object "sub2" { + + object "sub1" { code { - mstore(0, 2) - revert(0, 32) + returncontract("sub10", 0, 0) } - object "sub20" { + object "sub10" { code { mstore(0, 0x20) revert(0, 32) } } } - object "sub3" { + object "sub2" { code { mstore(0, 3) revert(0, 32) diff --git a/test/cmdlineTests/strict_asm_eof_container_osaka/output b/test/cmdlineTests/strict_asm_eof_container_osaka/output new file mode 100644 index 000000000000..81f01798a766 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_container_osaka/output @@ -0,0 +1,112 @@ + +======= strict_asm_eof_container_osaka/input.yul (EVM) ======= + +Pretty printed source: +object "object" { + code { + { + mstore(0, eofcreate("sub0", 0, 0, 0, 0)) + mstore(32, eofcreate("sub1", 0, 0, 0, 0)) + return(0, 64) + } + } + object "sub0" { + code { + { returncontract("sub00", 0, 0) } + } + object "sub00" { + code { + { + mstore(0, 1) + revert(0, 32) + } + } + } + } + object "sub1" { + code { + { returncontract("sub10", 0, 0) } + } + object "sub10" { + code { + { + mstore(0, 0x20) + revert(0, 32) + } + } + } + } + object "sub2" { + code { + { + mstore(0, 3) + revert(0, 32) + } + } + } +} + + +Binary representation: +ef000101000402000100150300020037003704000000008000045f808080ec005f525f808080ec0160205260405ff3ef00010100040200010004030001001b04000000008000025f80ee00ef00010100040200010008040000000080000260015f5260205ffdef00010100040200010004030001001b04000000008000025f80ee00ef00010100040200010008040000000080000260205f5260205ffd + +Text representation: + 0x00 + dup1 + dup1 + dup1 + eofcreate{0} + 0x00 + mstore + 0x00 + dup1 + dup1 + dup1 + eofcreate{1} + 0x20 + mstore + 0x40 + 0x00 + return +stop + +sub_0: assembly { + 0x00 + dup1 + returncontract{0} + stop + + sub_0: assembly { + 0x01 + 0x00 + mstore + 0x20 + 0x00 + revert + } +} + +sub_1: assembly { + 0x00 + dup1 + returncontract{0} + stop + + sub_0: assembly { + 0x20 + 0x00 + mstore + 0x20 + 0x00 + revert + } +} + +sub_2: assembly { + 0x03 + 0x00 + mstore + 0x20 + 0x00 + revert +} diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/args b/test/cmdlineTests/strict_asm_eof_container_prague/args deleted file mode 100644 index 0078e6e68e36..000000000000 --- a/test/cmdlineTests/strict_asm_eof_container_prague/args +++ /dev/null @@ -1 +0,0 @@ - --strict-assembly --experimental-eof-version 1 --evm-version prague --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/output b/test/cmdlineTests/strict_asm_eof_container_prague/output deleted file mode 100644 index 17f6df675585..000000000000 --- a/test/cmdlineTests/strict_asm_eof_container_prague/output +++ /dev/null @@ -1,103 +0,0 @@ - -======= strict_asm_eof_container_prague/input.yul (EVM) ======= - -Pretty printed source: -object "object" { - code { { revert(0, 0) } } - object "sub0" { - code { - { - mstore(0, 0) - revert(0, 32) - } - } - } - object "sub1" { - code { - { - mstore(0, 1) - revert(0, 32) - } - } - } - object "sub2" { - code { - { - mstore(0, 2) - revert(0, 32) - } - } - object "sub20" { - code { - { - mstore(0, 0x20) - revert(0, 32) - } - } - } - } - object "sub3" { - code { - { - mstore(0, 3) - revert(0, 32) - } - } - } -} - - -Binary representation: -ef00010100040200010003030004001a001b003b001b040000000080ffff5f80fdef00010100040200010007040000000080ffff5f805260205ffdef00010100040200010008040000000080ffff60015f5260205ffdef00010100040200010008030001001b040000000080ffff60025f5260205ffdef00010100040200010008040000000080ffff60205f5260205ffdef00010100040200010008040000000080ffff60035f5260205ffd - -Text representation: - 0x00 - dup1 - revert -stop - -sub_0: assembly { - 0x00 - dup1 - mstore - 0x20 - 0x00 - revert -} - -sub_1: assembly { - 0x01 - 0x00 - mstore - 0x20 - 0x00 - revert -} - -sub_2: assembly { - 0x02 - 0x00 - mstore - 0x20 - 0x00 - revert - stop - - sub_0: assembly { - 0x20 - 0x00 - mstore - 0x20 - 0x00 - revert - } -} - -sub_3: assembly { - 0x03 - 0x00 - mstore - 0x20 - 0x00 - revert -} diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args new file mode 100644 index 000000000000..60abde356339 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args @@ -0,0 +1 @@ + --strict-assembly --experimental-eof-version 1 --evm-version osaka --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/input.yul b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/input.yul new file mode 100644 index 000000000000..bd29cf65979c --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/input.yul @@ -0,0 +1,9 @@ +object "a" { + code { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + + data "data1" "Hello, World!" +} + diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output new file mode 100644 index 000000000000..355c96451e0d --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output @@ -0,0 +1,27 @@ + +======= strict_asm_eof_dataloadn_osaka/input.yul (EVM) ======= + +Pretty printed source: +object "a" { + code { + { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + } + data "data1" hex"48656c6c6f2c20576f726c6421" +} + + +Binary representation: +ef0001010004020001000904002d0000800002ef000d5f5260205ff348656c6c6f2c20576f726c6421 + +Text representation: + auxdataloadn{0} + 0x00 + mstore + 0x20 + 0x00 + return +stop +data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args new file mode 100644 index 000000000000..7ec243fdeb21 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args @@ -0,0 +1 @@ +--strict-assembly --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/err b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/err new file mode 100644 index 000000000000..cf9a17a7dfb9 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/err @@ -0,0 +1 @@ +Error: EOF is not supported by EVM versions earlier than osaka. diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/exit b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/exit new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/input.yul b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/input.yul new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/input.yul @@ -0,0 +1 @@ +{} diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/args b/test/cmdlineTests/strict_asm_yul_cfg_json_export/args new file mode 100644 index 000000000000..1147466b54ef --- /dev/null +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/args @@ -0,0 +1 @@ +--strict-assembly --optimize --yul-cfg-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/input.yul b/test/cmdlineTests/strict_asm_yul_cfg_json_export/input.yul new file mode 100644 index 000000000000..4165f70ba640 --- /dev/null +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/input.yul @@ -0,0 +1,36 @@ +/// @use-src 0:"input.sol" +object "C_19" { + code { + { + /// @src 0:124:223 "contract C is I {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_19_deployed") + codecopy(_1, dataoffset("C_19_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"input.sol" + object "C_19_deployed" { + code { + { + /// @src 0:124:223 "contract C is I {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + mstore(_1, /** @src 0:212:214 "42" */ 0x2a) + /// @src 0:124:223 "contract C is I {..." + return(_1, 32) + } + } + revert(0, 0) + } + } + } +} diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output new file mode 100644 index 000000000000..c79692c3c035 --- /dev/null +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -0,0 +1,448 @@ + +======= strict_asm_yul_cfg_json_export/input.yul (EVM) ======= +Yul Control Flow Graph: + +{ + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {} + }, + "type": "subObject" + } + }, + "type": "Object" +} diff --git a/test/cmdlineTests/undeployable_contract_empty_outputs/args b/test/cmdlineTests/undeployable_contract_empty_outputs/args new file mode 100644 index 000000000000..74c8e867fc91 --- /dev/null +++ b/test/cmdlineTests/undeployable_contract_empty_outputs/args @@ -0,0 +1 @@ +--bin --bin-runtime --opcodes --asm --ir --ir-ast-json --ir-optimized --ir-optimized-ast-json --gas --asm-json --abi --hashes --optimize --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/undeployable_contract_empty_outputs/input.sol b/test/cmdlineTests/undeployable_contract_empty_outputs/input.sol new file mode 100644 index 000000000000..06496f4a26e7 --- /dev/null +++ b/test/cmdlineTests/undeployable_contract_empty_outputs/input.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +abstract contract C {} +interface I {} diff --git a/test/cmdlineTests/undeployable_contract_empty_outputs/output b/test/cmdlineTests/undeployable_contract_empty_outputs/output new file mode 100644 index 000000000000..123edc75ddd6 --- /dev/null +++ b/test/cmdlineTests/undeployable_contract_empty_outputs/output @@ -0,0 +1,44 @@ + +======= undeployable_contract_empty_outputs/input.sol:C ======= +EVM assembly: +null +Gas estimation: +Opcodes: + +Binary: + +Binary of the runtime part: + +IR: + +IR AST: +null +Optimized IR: + +Optimized IR AST: +null +Function signatures: +Contract JSON ABI +[] + +======= undeployable_contract_empty_outputs/input.sol:I ======= +EVM assembly: +null +Gas estimation: +Opcodes: + +Binary: + +Binary of the runtime part: + +IR: + +IR AST: +null +Optimized IR: + +Optimized IR AST: +null +Function signatures: +Contract JSON ABI +[] diff --git a/test/cmdlineTests/yul_cfg_json_export/args b/test/cmdlineTests/yul_cfg_json_export/args new file mode 100644 index 000000000000..4af41df671fb --- /dev/null +++ b/test/cmdlineTests/yul_cfg_json_export/args @@ -0,0 +1 @@ +--via-ir --optimize --yul-cfg-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/yul_cfg_json_export/input.sol b/test/cmdlineTests/yul_cfg_json_export/input.sol new file mode 100644 index 000000000000..85691014f827 --- /dev/null +++ b/test/cmdlineTests/yul_cfg_json_export/input.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +interface I { + function f() external pure returns (uint); +} + +contract C is I { + function f() public pure override returns (uint) { + return 42; + } +} + +contract D { + function f() public returns (uint) { + C c = new C(); + return c.f(); + } +} diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output new file mode 100644 index 000000000000..0508769d7cb0 --- /dev/null +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -0,0 +1,2132 @@ + +======= yul_cfg_json_export/input.sol:C ======= +Yul Control Flow Graph: +{ + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": {} + }, + "type": "subObject" + } + }, + "type": "Object" +} + +======= yul_cfg_json_export/input.sol:D ======= +Yul Control Flow Graph: +{ + "D_38": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "D_38_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v28", + "targets": [ + "Block12", + "Block11" + ], + "type": "ConditionalJump" + }, + "id": "Block9", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "datasize", + "out": [ + "v18" + ] + }, + { + "in": [ + "v18", + "v0" + ], + "op": "add", + "out": [ + "v24" + ] + }, + { + "in": [ + "v0", + "v24" + ], + "op": "lt", + "out": [ + "v25" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v24" + ], + "op": "gt", + "out": [ + "v27" + ] + }, + { + "in": [ + "v25", + "v27" + ], + "op": "or", + "out": [ + "v28" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0", + "v18", + "v24" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v42", + "targets": [ + "Block15", + "Block14" + ], + "type": "ConditionalJump" + }, + "id": "Block12", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v35" + ] + }, + { + "in": [ + "v18", + "v35", + "v0" + ], + "op": "datacopy", + "out": [] + }, + { + "in": [ + "v0", + "v24" + ], + "op": "sub", + "out": [ + "v40" + ] + }, + { + "in": [ + "v40", + "v0", + "0x00" + ], + "op": "create", + "out": [ + "v41" + ] + }, + { + "in": [ + "v41" + ], + "op": "iszero", + "out": [ + "v42" + ] + } + ], + "liveness": { + "in": [ + "v0", + "v18", + "v24" + ], + "out": [ + "v41" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block11", + "instructions": [ + { + "in": [ + "0x4e487b71", + "0xe0" + ], + "op": "shl", + "out": [ + "v30" + ] + }, + { + "in": [ + "v30", + "0x00" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v60", + "targets": [ + "Block18", + "Block17" + ], + "type": "ConditionalJump" + }, + "id": "Block15", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v46" + ] + }, + { + "in": [ + "0x026121ff", + "0xe4" + ], + "op": "shl", + "out": [ + "v49" + ] + }, + { + "in": [ + "v49", + "v46" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x01", + "0xa0" + ], + "op": "shl", + "out": [ + "v53" + ] + }, + { + "in": [ + "0x01", + "v53" + ], + "op": "sub", + "out": [ + "v54" + ] + }, + { + "in": [ + "v54", + "v41" + ], + "op": "and", + "out": [ + "v57" + ] + }, + { + "in": [], + "op": "gas", + "out": [ + "v58" + ] + }, + { + "in": [ + "0x20", + "v46", + "0x04", + "v46", + "v57", + "v58" + ], + "op": "staticcall", + "out": [ + "v59" + ] + }, + { + "in": [ + "v59" + ], + "op": "iszero", + "out": [ + "v60" + ] + } + ], + "liveness": { + "in": [ + "v41" + ], + "out": [ + "v46", + "v59" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block14", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v43" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v44" + ] + }, + { + "in": [ + "v44", + "0x00", + "v43" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v45" + ] + }, + { + "in": [ + "v45", + "v43" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v59", + "targets": [ + "Block21", + "Block20" + ], + "type": "ConditionalJump" + }, + "id": "Block18", + "instructions": [], + "liveness": { + "in": [ + "v46", + "v59" + ], + "out": [ + "v46" + ] + } + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block17", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v61" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v62" + ] + }, + { + "in": [ + "v62", + "0x00", + "v61" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v63" + ] + }, + { + "in": [ + "v63", + "v61" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "entries": [ + "Block18", + "Block28" + ], + "exit": { + "type": "Terminated" + }, + "id": "Block21", + "instructions": [ + { + "in": [ + "0x00", + "v93" + ], + "op": "PhiFunction", + "out": [ + "v95" + ] + }, + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v94" + ] + }, + { + "in": [ + "v95", + "v94" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v94" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v95" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v67", + "targets": [ + "Block23", + "Block22" + ], + "type": "ConditionalJump" + }, + "id": "Block20", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v66" + ] + }, + { + "in": [ + "v66", + "0x20" + ], + "op": "gt", + "out": [ + "v67" + ] + } + ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46" + ] + }, + "type": "BuiltinCall" + }, + { + "entries": [ + "Block20", + "Block22" + ], + "exit": { + "cond": "v80", + "targets": [ + "Block25", + "Block24" + ], + "type": "ConditionalJump" + }, + "id": "Block23", + "instructions": [ + { + "in": [ + "0x20", + "v68" + ], + "op": "PhiFunction", + "out": [ + "v71" + ] + }, + { + "in": [ + "0x1f" + ], + "op": "not", + "out": [ + "v70" + ] + }, + { + "in": [ + "0x1f", + "v71" + ], + "op": "add", + "out": [ + "v72" + ] + }, + { + "in": [ + "v70", + "v72" + ], + "op": "and", + "out": [ + "v73" + ] + }, + { + "in": [ + "v73", + "v46" + ], + "op": "add", + "out": [ + "v77" + ] + }, + { + "in": [ + "v46", + "v77" + ], + "op": "lt", + "out": [ + "v78" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v77" + ], + "op": "gt", + "out": [ + "v79" + ] + }, + { + "in": [ + "v78", + "v79" + ], + "op": "or", + "out": [ + "v80" + ] + } + ], + "liveness": { + "in": [ + "v46", + "v71" + ], + "out": [ + "v46", + "v71", + "v77" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block23" + ], + "type": "Jump" + }, + "id": "Block22", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v68" + ] + } + ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46", + "v68" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v90", + "targets": [ + "Block28", + "Block27" + ], + "type": "ConditionalJump" + }, + "id": "Block25", + "instructions": [ + { + "in": [ + "v77", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "v71", + "v46" + ], + "op": "add", + "out": [ + "v88" + ] + }, + { + "in": [ + "v46", + "v88" + ], + "op": "sub", + "out": [ + "v89" + ] + }, + { + "in": [ + "0x20", + "v89" + ], + "op": "slt", + "out": [ + "v90" + ] + } + ], + "liveness": { + "in": [ + "v46", + "v71", + "v77" + ], + "out": [ + "v46" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block24", + "instructions": [ + { + "in": [ + "0x4e487b71", + "0xe0" + ], + "op": "shl", + "out": [ + "v81" + ] + }, + { + "in": [ + "v81", + "0x00" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block21" + ], + "type": "Jump" + }, + "id": "Block28", + "instructions": [ + { + "in": [ + "v46" + ], + "op": "mload", + "out": [ + "v93" + ] + } + ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v93" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block27", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": {} + }, + "type": "subObject" + } + }, + "type": "subObject" + } + }, + "type": "subObject" + } + }, + "type": "Object" +} + +======= yul_cfg_json_export/input.sol:I ======= +Yul Control Flow Graph: +null diff --git a/test/cmdlineTests/~via_ir_equivalence/test.sh b/test/cmdlineTests/~via_ir_equivalence/test.sh index d663bef858c5..0dcfba47135f 100755 --- a/test/cmdlineTests/~via_ir_equivalence/test.sh +++ b/test/cmdlineTests/~via_ir_equivalence/test.sh @@ -86,7 +86,7 @@ requiresOptimizer=( for contractFile in "${externalContracts[@]}" do - if ! [[ "${requiresOptimizer[*]}" =~ $contractFile ]] + if ! [[ " ${requiresOptimizer[*]} " == *" $contractFile "* ]] then printTask " - ${contractFile}" test_via_ir_equivalence "${REPO_ROOT}/test/${contractFile}" diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index eda9db933ecf..a732c64afee0 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -225,7 +225,7 @@ class AuctionRegistrarTestFramework: public SolidityExecutionFramework return compileContract(registrarCode, "GlobalRegistrar"); }); - sendMessage(compiled, true); + sendMessage(compiled, bytes(), true); BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 5c8edda92824..cf42e0ac945e 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -454,7 +454,7 @@ class WalletTestFramework: public SolidityExecutionFramework }); bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners); - sendMessage(compiled + args, true, _value); + sendMessage(compiled, args, true, _value); BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } diff --git a/test/externalTests/README.md b/test/externalTests/README.md index 8df5b4dfe043..327920e216d2 100644 --- a/test/externalTests/README.md +++ b/test/externalTests/README.md @@ -15,7 +15,7 @@ these projects *can* be upgraded at all. #### Adding a new external project 1. If the upstream code cannot be compiled without modifications, create a fork of the repository in https://github.com/solidity-external-tests/. -2. In our fork, remove all the branches except for main one (`master`, `develop`, `main`, etc). +2. In our fork, remove all the branches except for the main one (`master`, `develop`, `main`, etc). This branch is going to be always kept up to date with the upstream repository and should not contain any extra commits. - If the project is not up to date with the latest compiler version but has a branch that is, @@ -88,6 +88,6 @@ branches if they exist. If no changes on our part were necessary, it is complete e.g. the `master_060` of an external project in Solidity 0.8.x. Since each project is handled separately, this approach may result in a mix of version-specific branches -between different external projects. For example, in one project we could could have `master_050` on +between different external projects. For example, in one project we could have `master_050` on both `develop` and `breaking` and in another `breaking` could use `master_080` while `develop` still uses `master_060`. diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index b1222b49d1ae..6a41f7a7394c 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,7 @@ using namespace solidity::langutil; using namespace solidity::evmasm; +using namespace solidity::test; using namespace std::string_literals; namespace solidity::frontend::test @@ -54,7 +56,7 @@ namespace BOOST_AUTO_TEST_SUITE(Assembler) -BOOST_AUTO_TEST_CASE(all_assembly_items) +BOOST_AUTO_TEST_CASE(all_assembly_items, *boost::unit_test::precondition(nonEOF())) { std::map indices = { { "root.asm", 0 }, @@ -216,7 +218,8 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON(indices)), util::jsonCompactPrint(jsonValue)); } -BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) +// TODO: Implement EOF counterpart +BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps, *boost::unit_test::precondition(nonEOF())) { EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); // Tests for 1, 2, 3 number of immutables. @@ -301,7 +304,8 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) } } -BOOST_AUTO_TEST_CASE(immutable) +// TODO: Implement EOF counterpart +BOOST_AUTO_TEST_CASE(immutable, *boost::unit_test::precondition(nonEOF())) { std::map indices = { { "root.asm", 0 }, @@ -422,6 +426,46 @@ BOOST_AUTO_TEST_CASE(subobject_encode_decode) BOOST_CHECK(assembly.decodeSubPath(assembly.encodeSubPath(subPath)) == subPath); } +BOOST_AUTO_TEST_CASE(ethdebug_program_last_instruction_with_immediate_arguments) +{ + EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); + { + Assembly assembly{evmVersion, true, {}, {}}; + assembly.append(AssemblyItem{0x11223344}); + LinkerObject output = assembly.assemble(); + + Json const program = ethdebug::program("", 0, &assembly, output); + BOOST_REQUIRE(program["instructions"].size() == 1); + BOOST_REQUIRE(program["instructions"][0]["operation"]["mnemonic"] == "PUSH4"); + BOOST_REQUIRE(program["instructions"][0]["operation"]["arguments"][0] == "0x11223344"); + } + { + Assembly assembly{evmVersion, true, {}, {}}; + assembly.append(AssemblyItem{Instruction::PUSH0}); + assembly.append(AssemblyItem{0x1122334455}); + LinkerObject output = assembly.assemble(); + + Json const program = ethdebug::program("", 0, &assembly, output); + BOOST_REQUIRE(program["instructions"].size() == 2); + BOOST_REQUIRE(program["instructions"][0]["operation"]["mnemonic"] == "PUSH0"); + BOOST_REQUIRE(!program["instructions"][0]["operation"].contains("arguments")); + BOOST_REQUIRE(program["instructions"][1]["operation"]["mnemonic"] == "PUSH5"); + BOOST_REQUIRE(program["instructions"][1]["operation"]["arguments"][0] == "0x1122334455"); + } +} + +BOOST_AUTO_TEST_CASE(ethdebug_resources) +{ + Json const resources = ethdebug::resources({"sourceA", "sourceB"}, "version1"); + BOOST_REQUIRE(resources["compilation"]["compiler"]["name"] == "solc"); + BOOST_REQUIRE(resources["compilation"]["compiler"]["version"] == "version1"); + BOOST_REQUIRE(resources["compilation"]["sources"].size() == 2); + BOOST_REQUIRE(resources["compilation"]["sources"][0]["id"] == 0); + BOOST_REQUIRE(resources["compilation"]["sources"][0]["path"] == "sourceA"); + BOOST_REQUIRE(resources["compilation"]["sources"][1]["id"] == 1); + BOOST_REQUIRE(resources["compilation"]["sources"][1]["path"] == "sourceB"); +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 8ed413cfe199..f4b7034de544 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -41,6 +41,7 @@ using namespace solidity::langutil; using namespace solidity::evmasm; +using namespace solidity::test; namespace solidity::frontend::test { @@ -1329,13 +1330,14 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal) ); } -BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) +BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies, *boost::unit_test::precondition(nonEOF())) { // This tests that tags from subassemblies are not removed // if they are referenced by a super-assembly. Furthermore, // tag unifications (due to block deduplication) is also // visible at the super-assembly. + solAssert(!solidity::test::CommonOptions::get().eofVersion().has_value()); Assembly::OptimiserSettings settings; settings.runInliner = false; settings.runJumpdestRemover = true; @@ -1343,11 +1345,11 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) settings.runDeduplicate = true; settings.runCSE = true; settings.runConstantOptimiser = true; - settings.evmVersion = solidity::test::CommonOptions::get().evmVersion(); settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment; - Assembly main{settings.evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), {}}; - AssemblyPointer sub = std::make_shared(settings.evmVersion, true, solidity::test::CommonOptions::get().eofVersion(), std::string{}); + auto const evmVersion = CommonOptions::get().evmVersion(); + Assembly main{evmVersion, false, std::nullopt, {}}; + AssemblyPointer sub = std::make_shared(evmVersion, true, std::nullopt, std::string{}); sub->append(u256(1)); auto t1 = sub->newTag(); diff --git a/test/libsolidity/ASTJSON/storage_layout_specifier.json b/test/libsolidity/ASTJSON/storage_layout_specifier.json new file mode 100644 index 000000000000..5ffa1abe3f74 --- /dev/null +++ b/test/libsolidity/ASTJSON/storage_layout_specifier.json @@ -0,0 +1,88 @@ +{ + "absolutePath": "a", + "exportedSymbols": { + "C": [ + 5 + ] + }, + "id": 6, + "nodeType": "SourceUnit", + "nodes": [ + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 5, + "linearizedBaseContracts": [ + 5 + ], + "name": "C", + "nameLocation": "9:1:1", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 6, + "src": "0:35:1", + "storageLayout": { + "baseSlotExpression": { + "commonType": { + "typeIdentifier": "t_rational_5801_by_1", + "typeString": "int_const 5801" + }, + "id": 3, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "leftExpression": { + "hexValue": "31323334", + "id": 1, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "21:4:1", + "typeDescriptions": { + "typeIdentifier": "t_rational_1234_by_1", + "typeString": "int_const 1234" + }, + "value": "1234" + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "hexValue": "34353637", + "id": 2, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "28:4:1", + "typeDescriptions": { + "typeIdentifier": "t_rational_4567_by_1", + "typeString": "int_const 4567" + }, + "value": "4567" + }, + "src": "21:11:1", + "typeDescriptions": { + "typeIdentifier": "t_rational_5801_by_1", + "typeString": "int_const 5801" + } + }, + "id": 4, + "nodeType": "StorageLayoutSpecifier", + "src": "11:21:1" + }, + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "0:36:1" +} diff --git a/test/libsolidity/ASTJSON/storage_layout_specifier.sol b/test/libsolidity/ASTJSON/storage_layout_specifier.sol new file mode 100644 index 000000000000..1031f2db092c --- /dev/null +++ b/test/libsolidity/ASTJSON/storage_layout_specifier.sol @@ -0,0 +1,3 @@ +contract C layout at 1234 + 4567 {} + +// ---- \ No newline at end of file diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index bf1e5caf7c04..bf9c6b16afb9 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -81,7 +81,11 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) if (Error::containsErrors(errorReporter.errors())) return AssemblyItems(); } - TypeChecker checker(solidity::test::CommonOptions::get().evmVersion(), errorReporter); + TypeChecker checker( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), + errorReporter + ); BOOST_REQUIRE_NO_THROW(checker.checkTypeRequirements(*sourceUnit)); if (Error::containsErrors(errorReporter.errors())) return AssemblyItems(); @@ -90,6 +94,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) { Compiler compiler( solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), RevertStrings::Default, solidity::test::CommonOptions::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal() ); diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 1afebac5c5c8..9012ad083c02 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -76,7 +76,7 @@ class GasMeterTestFramework: public SolidityExecutionFramework util::FixedHash<4> hash = util::selectorFromSignatureH32(_sig); for (bytes const& arguments: _argumentVariants) { - sendMessage(hash.asBytes() + arguments, false, 0); + sendMessage(hash.asBytes(), arguments, false, 0); BOOST_CHECK(m_transactionSuccessful); gasUsed = std::max(gasUsed, m_gasUsed); gas = std::max(gas, gasForTransaction(hash.asBytes() + arguments, false)); diff --git a/test/libsolidity/GasTest.cpp b/test/libsolidity/GasTest.cpp index 14722535e446..39b0e6681abe 100644 --- a/test/libsolidity/GasTest.cpp +++ b/test/libsolidity/GasTest.cpp @@ -37,7 +37,7 @@ using namespace solidity; using namespace boost::unit_test; GasTest::GasTest(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); m_optimise = m_reader.boolSetting("optimize", false); @@ -114,10 +114,6 @@ void GasTest::setupCompiler(CompilerStack& _compiler) } settings.expectedExecutionsPerDeployment = m_optimiseRuns; _compiler.setOptimiserSettings(settings); - - // Intentionally ignoring EVM version specified on the command line. - // Gas expectations are only valid for the default version. - _compiler.setEVMVersion(EVMVersion{}); } TestCase::TestResult GasTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) diff --git a/test/libsolidity/GasTest.h b/test/libsolidity/GasTest.h index 1337ae3f6f07..998411abf863 100644 --- a/test/libsolidity/GasTest.h +++ b/test/libsolidity/GasTest.h @@ -32,7 +32,7 @@ namespace solidity::frontend::test { -class GasTest: AnalysisFramework, public TestCase +class GasTest: AnalysisFramework, public EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index b3993e39f3df..fb08c667ce54 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -44,6 +44,7 @@ using namespace solidity::langutil; using namespace solidity::yul; +using namespace solidity::test; namespace solidity::frontend::test { @@ -294,7 +295,8 @@ BOOST_AUTO_TEST_CASE(designated_invalid_instruction) BOOST_CHECK(successAssemble("{ invalid() }")); } -BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_declaration) +// TODO: Implement EOF counterpart +BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_declaration, *boost::unit_test::precondition(nonEOF())) { CHECK_ASSEMBLE_ERROR("{ let gas := 1 }", ParserError, "Cannot use builtin"); } @@ -333,14 +335,14 @@ BOOST_AUTO_TEST_CASE(returndatacopy) BOOST_CHECK(successAssemble("{ returndatacopy(0, 32, 64) }")); } -BOOST_AUTO_TEST_CASE(staticcall) +BOOST_AUTO_TEST_CASE(staticcall, *boost::unit_test::precondition(nonEOF())) { if (!solidity::test::CommonOptions::get().evmVersion().hasStaticCall()) return; BOOST_CHECK(successAssemble("{ pop(staticcall(10000, 0x123, 64, 0x10, 128, 0x10)) }")); } -BOOST_AUTO_TEST_CASE(create2) +BOOST_AUTO_TEST_CASE(create2, *boost::unit_test::precondition(nonEOF())) { if (!solidity::test::CommonOptions::get().evmVersion().hasCreate2()) return; diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 08a2814c95e3..f7d07aa4447c 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -20,13 +20,17 @@ #include #include + #include + #include #include + #include -#include #include #include +#include + #include #include #include @@ -38,6 +42,7 @@ using namespace solidity::langutil; using namespace solidity::frontend; using namespace solidity::frontend::test; using namespace solidity::test; +using namespace solidity::yul::test; using namespace yul; void MemoryGuardTest::setupCompiler(CompilerStack& _compiler) @@ -60,30 +65,32 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con for (std::string contractName: compiler().contractNames()) { ErrorList errors; - auto [object, analysisInfo] = yul::test::parse( - compiler().yulIR(contractName), - EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion()), - errors - ); + std::optional const& ir = compiler().yulIR(contractName); + soltestAssert(ir); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(*ir); + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing IR:" << std::endl; - printPrefixed(_stream, formatErrors(filterErrors(errors), _formatted), _linePrefix); + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } auto handleObject = [&](std::string const& _kind, Object const& _object) { - m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( + auto const memoryGuardHandle = yulStack.dialect().findBuiltin("memoryguard"); + m_obtainedResult += contractName + "(" + _kind + ") "; + if (memoryGuardHandle && !findFunctionCalls( _object.code()->root(), - "memoryguard"_yulname - ).empty() ? "false" : "true") + "\n"; + *memoryGuardHandle + ).empty()) + m_obtainedResult += "true\n"; + else + m_obtainedResult += "false\n"; }; - handleObject("creation", *object); - size_t deployedIndex = object->subIndexByName.at( + handleObject("creation", *yulStack.parserResult()); + size_t deployedIndex = yulStack.parserResult()->subIndexByName.at( IRNames::deployedObject(compiler().contractDefinition(contractName)) ); - handleObject("runtime", dynamic_cast(*object->subObjects[deployedIndex])); + handleObject("runtime", dynamic_cast(*yulStack.parserResult()->subObjects[deployedIndex])); } return checkResult(_stream, _linePrefix, _formatted); } diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index ed490b9a839b..3b7d101d5948 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -225,6 +225,48 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) } } +BOOST_AUTO_TEST_CASE(metadata_eof_experimental) +{ + // Check that setting an EOF version results in the experimental flag being set. + char const* sourceCode = R"( + pragma solidity >=0.0; + contract test { + function g(function(uint) external returns (uint) x) public {} + } + )"; + for (auto metadataFormat: std::set{ + CompilerStack::MetadataFormat::NoMetadata, + CompilerStack::MetadataFormat::WithReleaseVersionTag, + CompilerStack::MetadataFormat::WithPrereleaseVersionTag + }) + { + CompilerStack compilerStack; + compilerStack.setMetadataFormat(metadataFormat); + compilerStack.setSources({{"", sourceCode}}); + compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); + compilerStack.setViaIR(true); + compilerStack.setEOFVersion(solidity::test::CommonOptions::get().eofVersion()); + compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); + bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; + std::string const& metadata = compilerStack.metadata("test"); + BOOST_CHECK(solidity::test::isValidMetadata(metadata)); + + auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat); + + if ( + metadataFormat == CompilerStack::MetadataFormat::NoMetadata || + !solidity::test::CommonOptions::get().eofVersion().has_value() + ) + BOOST_CHECK(cborMetadata.count("experimental") == 0); + else + { + BOOST_CHECK(cborMetadata.count("experimental") == 1); + BOOST_CHECK(cborMetadata.at("experimental") == "true"); + } + } +} + BOOST_AUTO_TEST_CASE(metadata_relevant_sources) { CompilerStack compilerStack; @@ -401,7 +443,7 @@ BOOST_AUTO_TEST_CASE(metadata_revert_strings) BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) { - char const* sourceCode = R"( + std::string const sourceCode = R"( pragma solidity >=0.0; contract C { } @@ -413,19 +455,36 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) {"", ""}, {"", "fDn"}, {"dhfoDgvulfnTUtnIf", "" }, - {"dhfoDgvulfnTUtnIf", "fDn"} + {"dhfoDgvulfnTUtnIf", "fDn"}, + // test that a custom cleanup step sequence does not lead to default standard optimiser settings in metadata + {OptimiserSettings::DefaultYulOptimiserSteps, "D"}, + // test that a custom optimizer sequence does not lead to default standard optimiser settings in metadata + {"dhfoDgvulfnTUtnIf", OptimiserSettings::DefaultYulOptimiserCleanupSteps} }; - auto check = [sourceCode](std::string const& _optimizerSequence, std::string const& _optimizerCleanupSequence) + std::vector settingsToTest; + for (auto const& [optimizerSequence, optimizerCleanupSequence]: sequences) + { + for (auto const& preset: { + OptimiserSettings::none(), + OptimiserSettings::minimal(), + OptimiserSettings::standard(), + OptimiserSettings::full(), + }) + { + settingsToTest.emplace_back(preset); + settingsToTest.back().runYulOptimiser = true; + settingsToTest.back().yulOptimiserSteps = optimizerSequence; + settingsToTest.back().yulOptimiserCleanupSteps = optimizerCleanupSequence; + } + } + + auto generateMetadataJson = [](std::string const& _source, OptimiserSettings const& _optimizerSettings) -> Json { - OptimiserSettings optimizerSettings = OptimiserSettings::minimal(); - optimizerSettings.runYulOptimiser = true; - optimizerSettings.yulOptimiserSteps = _optimizerSequence; - optimizerSettings.yulOptimiserCleanupSteps = _optimizerCleanupSequence; CompilerStack compilerStack; - compilerStack.setSources({{"", sourceCode}}); + compilerStack.setSources({{"", _source}}); compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); - compilerStack.setOptimiserSettings(optimizerSettings); + compilerStack.setOptimiserSettings(_optimizerSettings); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); @@ -433,17 +492,33 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - BOOST_CHECK(metadata["settings"]["optimizer"].contains("details")); - BOOST_CHECK(metadata["settings"]["optimizer"]["details"].contains("yulDetails")); - BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].contains("optimizerSteps")); + return metadata; + }; - std::string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].get(); - std::string const expectedMetadataOptimiserSteps = _optimizerSequence + ":" + _optimizerCleanupSequence; + auto checkCustomSettings = [generateMetadataJson, sourceCode](OptimiserSettings const& _optimizerSettings) + { + auto const metadataJson = generateMetadataJson(sourceCode, _optimizerSettings); + BOOST_CHECK(metadataJson["settings"]["optimizer"].contains("details")); + BOOST_CHECK(metadataJson["settings"]["optimizer"]["details"].contains("yulDetails")); + BOOST_CHECK(metadataJson["settings"]["optimizer"]["details"]["yulDetails"].contains("optimizerSteps")); + + std::string const metadataOptimizerSteps = metadataJson["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].get(); + std::string const expectedMetadataOptimiserSteps = _optimizerSettings.yulOptimiserSteps + ":" + _optimizerSettings.yulOptimiserCleanupSteps; BOOST_CHECK_EQUAL(metadataOptimizerSteps, expectedMetadataOptimiserSteps); }; - for (auto const& [sequence, cleanupSequence] : sequences) - check(sequence, cleanupSequence); + for (auto const& optimizerSettings: settingsToTest) + checkCustomSettings(optimizerSettings); + + for (auto const& preset: {OptimiserSettings::minimal(), OptimiserSettings::standard(), OptimiserSettings::full()}) + { + auto const metadataJson = generateMetadataJson(sourceCode, preset); + Json expectedOptimizerMetadata = { + {"enabled", preset != OptimiserSettings::minimal()}, + {"runs", preset.expectedExecutionsPerDeployment} + }; + BOOST_CHECK(metadataJson["settings"]["optimizer"] == expectedOptimizerMetadata); + } } BOOST_AUTO_TEST_CASE(metadata_license_missing) diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index c25025ccf77c..d8843e0d3a1e 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -131,11 +131,19 @@ SMTCheckerTest::SMTCheckerTest(std::string const& _filename): #elif __linux__ if (os == "linux") m_shouldRun = false; +#else + // On other operating systems this setting is ignored (as we don't test other operating systems in CI), + // but we need to prevent an unused-variable warning. + (void)os; #endif } auto const& bmcLoopIterations = m_reader.sizetSetting("BMCLoopIterations", 1); m_modelCheckerSettings.bmcLoopIterations = std::optional{bmcLoopIterations}; + + // TODO: Enable EOF testing when EOF gets stable and smtCheckerTest starts using IR. + if (CommonOptions::get().eofVersion().has_value()) + m_shouldRun = false; } void SMTCheckerTest::setupCompiler(CompilerStack& _compiler) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index b0bdb95cb9c4..1b66dd60fffb 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -91,7 +91,12 @@ SemanticTest::SemanticTest( if (m_runWithABIEncoderV1Only && !solidity::test::CommonOptions::get().useABIEncoderV1) m_shouldRun = false; - std::string compileViaYul = m_reader.stringSetting("compileViaYul", "also"); + auto const eofEnabled = solidity::test::CommonOptions::get().eofVersion().has_value(); + std::string compileViaYul = m_reader.stringSetting("compileViaYul", eofEnabled ? "true" : "also"); + + if (compileViaYul == "false" && eofEnabled) + m_shouldRun = false; + if (m_runWithABIEncoderV1Only && compileViaYul != "false") BOOST_THROW_EXCEPTION(std::runtime_error( "ABIEncoderV1Only tests cannot be run via yul, " diff --git a/test/libsolidity/SolidityCompiler.cpp b/test/libsolidity/SolidityCompiler.cpp index 7cb95a99d0bc..79d838349af9 100644 --- a/test/libsolidity/SolidityCompiler.cpp +++ b/test/libsolidity/SolidityCompiler.cpp @@ -24,6 +24,7 @@ #include +using namespace solidity::test; namespace solidity::frontend::test { @@ -42,7 +43,8 @@ class SolidityCompilerFixture: protected AnalysisFramework BOOST_FIXTURE_TEST_SUITE(SolidityCompiler, SolidityCompilerFixture) -BOOST_AUTO_TEST_CASE(does_not_include_creation_time_only_internal_functions) +// TODO: Implement EOF counterpart +BOOST_AUTO_TEST_CASE(does_not_include_creation_time_only_internal_functions, *boost::unit_test::precondition(nonEOF())) { char const* sourceCode = R"( contract C { diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e321a5298603..76699c2e3b6c 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1374,7 +1374,7 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) ALSO_VIA_YUL( compileAndRun(sourceCode); bytes calldata1 = util::selectorFromSignatureH32("f()").asBytes() + bytes(61, 0x22) + bytes(12, 0x12); - sendMessage(calldata1, false); + sendMessage(calldata1, bytes(), false); BOOST_CHECK(m_transactionSuccessful); BOOST_CHECK(m_output == encodeArgs(util::keccak256(bytes{'a', 'b', 'c'} + calldata1))); ); @@ -1474,7 +1474,7 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) compileAndRun(sourceCode); ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - sendMessage(bytes(), false); + sendMessage(bytes(), bytes(), false); BOOST_CHECK(m_transactionSuccessful); BOOST_CHECK(m_output.empty()); BOOST_CHECK(storageEmpty(m_contractAddress)); diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index f91ba758f08b..4caa4aa1e1a4 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -62,7 +62,7 @@ class SolidityExecutionFramework: public solidity::test::ExecutionFramework ) override { bytes bytecode = multiSourceCompileContract(_sourceCode, _sourceName, _contractName, _libraryAddresses); - sendMessage(bytecode + _arguments, true, _value); + sendMessage(bytecode, _arguments, true, _value); return m_output; } diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 031e9bdbfc2d..1a09475c49b8 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -133,7 +133,11 @@ bytes compileFirstExpression( DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion()); for (ASTPointer const& node: sourceUnit->nodes()) BOOST_REQUIRE(declarationTypeChecker.check(*node)); - TypeChecker typeChecker(solidity::test::CommonOptions::get().evmVersion(), errorReporter); + TypeChecker typeChecker( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), + errorReporter + ); BOOST_REQUIRE(typeChecker.checkTypeRequirements(*sourceUnit)); for (ASTPointer const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) @@ -143,6 +147,7 @@ bytes compileFirstExpression( CompilerContext context( solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), RevertStrings::Default ); context.resetVisitedNodes(contract); diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 4cb0b3c93068..b17f566613a1 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include +#include using namespace solidity::evmasm; using namespace std::string_literals; @@ -152,6 +154,147 @@ Json compile(std::string _input) return ret; } +Json createLanguageAndSourcesSection(std::string const& _language, std::map const& _sources, bool _contentNode = true) +{ + Json result = Json::object(); + result["language"] = _language; + result["sources"] = Json::object(); + for (auto const& source: _sources) + { + result["sources"][source.first] = Json::object(); + if (_contentNode) + result["sources"][source.first]["content"] = source.second; + else + result["sources"][source.first] = source.second; + } + return result; +} + +class Code +{ +public: + virtual ~Code() = default; + explicit Code(std::map _code = {}) : m_code(std::move(_code)) {} + [[nodiscard]] virtual Json json() const = 0; +protected: + std::map m_code; +}; + +class SolidityCode: public Code +{ +public: + explicit SolidityCode(std::map _code = { + {"fileA", "pragma solidity >=0.0; contract C { function f() public pure {} }"} + }) : Code(std::move(_code)) {} + [[nodiscard]] Json json() const override + { + return createLanguageAndSourcesSection("Solidity", m_code); + } +}; + +class YulCode: public Code +{ +public: + explicit YulCode(std::map _code = { + {"fileA", "{}"} + }) : Code(std::move(_code)) {} + [[nodiscard]] Json json() const override + { + return createLanguageAndSourcesSection("Yul", m_code); + } +}; + +class EvmAssemblyCode: public Code +{ +public: + explicit EvmAssemblyCode(std::map _code = { + {"fileA", Json::parse(R"( + { + "assemblyJson": { + ".code": [ + { + "begin": 36, + "end": 51, + "name": "PUSH", + "source": 0, + "value": "0" + } + ], + "sourceList": [ + "" + ] + } + } + )")} + }) : Code(std::move(_code)) {} + [[nodiscard]] Json json() const override + { + return createLanguageAndSourcesSection("EVMAssembly", m_code, false); + } +}; + +class SolidityAstCode: public Code +{ +public: + explicit SolidityAstCode(std::map _code = { + {"fileA", Json::parse(R"( + { + "ast": { + "absolutePath": "empty_contract.sol", + "exportedSymbols": { + "test": [ + 1 + ] + }, + "id": 2, + "nodeType": "SourceUnit", + "nodes": [ + { + "abstract": false, + "baseContracts": [], + "canonicalName": "test", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 1, + "linearizedBaseContracts": [ + 1 + ], + "name": "test", + "nameLocation": "9:4:0", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 2, + "src": "0:17:0", + "usedErrors": [] + } + ], + "src": "0:124:0" + }, + "id": 0 + } + )")} + }) : Code(std::move(_code)) {} + [[nodiscard]] Json json() const override + { + return createLanguageAndSourcesSection("SolidityAST", m_code); + } +}; + +Json generateStandardJson(bool _viaIr, Json const& _debugInfoSelection, Json const& _outputSelection, Code const& _code = SolidityCode(), bool _advancedOutputSelection = false) +{ + Json result = _code.json(); + result["settings"] = Json::object(); + result["settings"]["viaIR"] = _viaIr; + if (!_debugInfoSelection.empty()) + result["settings"]["debug"]["debugInfo"] = _debugInfoSelection; + if (_advancedOutputSelection) + result["settings"]["outputSelection"] = _outputSelection; + else + result["settings"]["outputSelection"]["*"]["*"] = _outputSelection; + return result; +} + } // end anonymous namespace BOOST_AUTO_TEST_SUITE(StandardCompiler) @@ -1782,6 +1925,354 @@ BOOST_AUTO_TEST_CASE(source_location_of_bare_block) BOOST_REQUIRE(sourceMap.find(sourceRef) != std::string::npos); } +BOOST_AUTO_TEST_CASE(ethdebug_excluded_from_wildcards) +{ + frontend::StandardCompiler compiler; + // excluded from output selection wildcard + Json result = compiler.compile(generateStandardJson(true, {}, Json::array({"*"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); + // excluded from debug info selection wildcard + result = compiler.compile(generateStandardJson(true, {"*"}, Json::array({"ir"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); + // excluded from both - just in case ;) + result = compiler.compile(generateStandardJson(true, {"*"}, Json::array({"*"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); +} + +BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) +{ + static std::vector>>> tests{ + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"})), + std::nullopt, + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"})), + std::nullopt, + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + std::nullopt, + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + std::nullopt, + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + std::nullopt, + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), + {} + }, + { + generateStandardJson(true, Json::array({"ethdebugs"}), Json::array({"irOptimized"}), YulCode()), {} + }, + { + generateStandardJson( + true, Json::array({"ethdebug"}), { + {"fileA", {{"contractA", Json::array({"evm.deployedBytecode.bin"})}}}, + {"fileB", {{"contractB", Json::array({"evm.bytecode.bin"})}}} + }, + SolidityCode({ + {"fileA", "pragma solidity >=0.0; contract contractA { function f() public pure {} }"}, + {"fileB", "pragma solidity >=0.0; contract contractB { function f() public pure {} }"} + }), true + ), + std::nullopt, + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), EvmAssemblyCode()), + std::nullopt, + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), SolidityAstCode()), + std::nullopt, + }, + }; + frontend::StandardCompiler compiler; + for (auto const& test: tests) + { + Json result = compiler.compile(std::get<0>(test)); + if (std::get<1>(test).has_value()) + BOOST_REQUIRE((*std::get<1>(test))(result)); + } +} + +BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) +{ + static std::vector>>> tests{ + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(false, {}, Json::array({"evm.deployedBytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(true, Json::array({"location"}), Json::array({"evm.deployedBytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + std::nullopt + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug"})), + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug"})), + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebugs"})), + std::nullopt + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebugs"})), + std::nullopt + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"})), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"}), YulCode()), + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result["contracts"]["fileA"]["object"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"}), YulCode()), + std::nullopt + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"}), YulCode()), + std::nullopt + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode"})), + [](const Json& result) + { + return result.dump().find("ethdebug") == std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode"})), + [](const Json& result) + { + return result.dump().find("ethdebug") == std::string::npos; + } + }, + { + generateStandardJson( + true, {}, { + {"fileA", {{"contractA", Json::array({"evm.deployedBytecode.ethdebug"})}}}, + {"fileB", {{"contractB", Json::array({"evm.bytecode.ethdebug"})}}} + }, + SolidityCode({ + {"fileA", "pragma solidity >=0.0; contract contractA { function f() public pure {} }"}, + {"fileB", "pragma solidity >=0.0; contract contractB { function f() public pure {} }"} + }), true + ), + [](const Json& result) + { + return result["contracts"]["fileA"]["contractA"]["evm"]["deployedBytecode"].contains("ethdebug") && + result["contracts"]["fileB"]["contractB"]["evm"]["bytecode"].contains("ethdebug") && result.contains("ethdebug"); + } + } + }; + frontend::StandardCompiler compiler; + for (auto const& [standardJsonToCompile, optionalCheck]: tests) + { + Json result = compiler.compile(standardJsonToCompile); + BOOST_REQUIRE(!optionalCheck.has_value() ? result.contains("errors") : result.contains("contracts")); + if (optionalCheck.has_value()) + BOOST_REQUIRE((*optionalCheck)(result)); + } +} + +BOOST_DATA_TEST_CASE(ethdebug_output_instructions_smoketest, boost::unit_test::data::make({"deployedBytecode", "bytecode"}), bytecodeType) +{ + frontend::StandardCompiler compiler; + Json result = compiler.compile(generateStandardJson(true, {}, Json::array({std::string("evm.") + bytecodeType + ".ethdebug"}))); + BOOST_REQUIRE(result["contracts"]["fileA"]["C"]["evm"][bytecodeType].contains("ethdebug")); + bool creation = std::string(bytecodeType) == "bytecode"; + Json ethdebugInstructionsToCheck = result["contracts"]["fileA"]["C"]["evm"][bytecodeType]["ethdebug"]; + BOOST_REQUIRE(ethdebugInstructionsToCheck["contract"]["definition"]["source"]["id"] == 0); + BOOST_REQUIRE(ethdebugInstructionsToCheck["contract"]["name"] == "C"); + BOOST_REQUIRE(ethdebugInstructionsToCheck["environment"] == (creation ? "create" : "call")); + BOOST_REQUIRE(ethdebugInstructionsToCheck["instructions"].is_array()); + for (auto const& instruction: ethdebugInstructionsToCheck["instructions"]) + { + BOOST_REQUIRE(instruction.contains("offset")); + BOOST_REQUIRE(instruction.contains("operation")); + BOOST_REQUIRE(instruction["operation"].contains("mnemonic")); + BOOST_REQUIRE(instruction["context"]["code"]["range"].contains("length")); + BOOST_REQUIRE(instruction["context"]["code"]["range"].contains("offset")); + BOOST_REQUIRE(instruction["context"]["code"]["source"].contains("id")); + std::string mnemonic = instruction["operation"]["mnemonic"]; + if (mnemonic.find("PUSH") != std::string::npos) + { + size_t bytesToPush = boost::lexical_cast(mnemonic.substr(4)); + if (bytesToPush > 0) + { + BOOST_REQUIRE(instruction["operation"].contains("arguments")); + BOOST_REQUIRE(instruction["operation"]["arguments"].is_array()); + BOOST_REQUIRE(instruction["operation"]["arguments"].size() == 1); + std::string argument = instruction["operation"]["arguments"][0]; + BOOST_REQUIRE(argument.length() % 2 == 0); + BOOST_REQUIRE(bytesToPush == (argument.length() - 2) / 2); // remove "0x" and calculate actual byte size from hex. + } + else + BOOST_REQUIRE(!instruction["operation"].contains("arguments")); + } + else + BOOST_REQUIRE(!instruction["operation"].contains("arguments")); + } +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 41c1d0568be6..8944710542a5 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -48,9 +48,15 @@ SyntaxTest::SyntaxTest( { static std::set const compileViaYulAllowedValues{"true", "false"}; - m_compileViaYul = m_reader.stringSetting("compileViaYul", "false"); + auto const eofEnabled = solidity::test::CommonOptions::get().eofVersion().has_value(); + + m_compileViaYul = m_reader.stringSetting("compileViaYul", eofEnabled ? "true" : "false"); if (!util::contains(compileViaYulAllowedValues, m_compileViaYul)) BOOST_THROW_EXCEPTION(std::runtime_error("Invalid compileViaYul value: " + m_compileViaYul + ".")); + + if (m_compileViaYul == "false" && eofEnabled) + m_shouldRun = false; + m_optimiseYul = m_reader.boolSetting("optimize-yul", true); static std::map const pipelineStages = { diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index 3d0e024da83b..ac220283a8e6 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -28,6 +28,7 @@ #include using namespace solidity::langutil; +using namespace solidity::test; namespace solidity::frontend::test { @@ -133,7 +134,7 @@ BOOST_AUTO_TEST_CASE(address_staticcall) } -BOOST_AUTO_TEST_CASE(assembly_staticcall) +BOOST_AUTO_TEST_CASE(assembly_staticcall, *boost::unit_test::precondition(nonEOF())) { std::string text = R"( contract C { diff --git a/test/libsolidity/gasTests/abiv2.sol b/test/libsolidity/gasTests/abiv2.sol index 6fa822fade47..95c30ac645db 100644 --- a/test/libsolidity/gasTests/abiv2.sol +++ b/test/libsolidity/gasTests/abiv2.sol @@ -12,6 +12,9 @@ contract C { function f7(uint[31] memory, string[20] memory, C, address) public returns (bytes[] memory, uint16[] memory) {} function f8(uint[32] memory, string[] memory, uint32, address) public returns (uint[] memory, uint16[] memory) {} } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 1208000 diff --git a/test/libsolidity/gasTests/abiv2_optimised.sol b/test/libsolidity/gasTests/abiv2_optimised.sol index 2989c1acd8f9..e23a7bff2562 100644 --- a/test/libsolidity/gasTests/abiv2_optimised.sol +++ b/test/libsolidity/gasTests/abiv2_optimised.sol @@ -13,6 +13,8 @@ contract C { function f8(uint[32] memory, string[] memory, uint32, address) public returns (uint[] memory, uint16[] memory) {} } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy // optimize: true // optimize-yul: true // ---- diff --git a/test/libsolidity/gasTests/data_storage.sol b/test/libsolidity/gasTests/data_storage.sol index 0d24ef505273..d9cacf5caf44 100644 --- a/test/libsolidity/gasTests/data_storage.sol +++ b/test/libsolidity/gasTests/data_storage.sol @@ -11,6 +11,9 @@ contract C { require(false, "12345678901234567890123456789012123456789012345678901234567890123"); } } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 377800 diff --git a/test/libsolidity/gasTests/dispatch_large.sol b/test/libsolidity/gasTests/dispatch_large.sol index e1cce4acd764..2b7822f5f855 100644 --- a/test/libsolidity/gasTests/dispatch_large.sol +++ b/test/libsolidity/gasTests/dispatch_large.sol @@ -22,6 +22,9 @@ contract Large { function g9(uint x) public payable returns (uint) { b[uint8(msg.data[8])] = x; } function g0(uint x) public payable returns (uint) { require(x > 10); } } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 618400 diff --git a/test/libsolidity/gasTests/dispatch_large_optimised.sol b/test/libsolidity/gasTests/dispatch_large_optimised.sol index 83e55c1a9c1e..5ab62e892285 100644 --- a/test/libsolidity/gasTests/dispatch_large_optimised.sol +++ b/test/libsolidity/gasTests/dispatch_large_optimised.sol @@ -23,6 +23,8 @@ contract Large { function g0(uint x) public payable returns (uint) { require(x > 10); } } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy // optimize: true // optimize-runs: 2 // ---- diff --git a/test/libsolidity/gasTests/dispatch_medium.sol b/test/libsolidity/gasTests/dispatch_medium.sol index 6bf8f89394fa..aedbec0b081f 100644 --- a/test/libsolidity/gasTests/dispatch_medium.sol +++ b/test/libsolidity/gasTests/dispatch_medium.sol @@ -9,6 +9,9 @@ contract Medium { function g9(uint x) public payable returns (uint) { b[uint8(msg.data[8])] = x; } function g0(uint x) public payable returns (uint) { require(x > 10); } } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 259600 diff --git a/test/libsolidity/gasTests/dispatch_medium_optimised.sol b/test/libsolidity/gasTests/dispatch_medium_optimised.sol index e921fcf125ba..2ea33955e9c8 100644 --- a/test/libsolidity/gasTests/dispatch_medium_optimised.sol +++ b/test/libsolidity/gasTests/dispatch_medium_optimised.sol @@ -10,6 +10,9 @@ contract Medium { function g0(uint x) public payable returns (uint) { require(x > 10); } } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy +// ==== // optimize: true // optimize-runs: 2 // ---- diff --git a/test/libsolidity/gasTests/dispatch_small.sol b/test/libsolidity/gasTests/dispatch_small.sol index d2c391582ed5..d198fd9927f1 100644 --- a/test/libsolidity/gasTests/dispatch_small.sol +++ b/test/libsolidity/gasTests/dispatch_small.sol @@ -4,6 +4,9 @@ contract Small { function f1(uint x) public returns (uint) { a = x; b[uint8(msg.data[0])] = x; } fallback () external payable {} } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 103800 diff --git a/test/libsolidity/gasTests/dispatch_small_optimised.sol b/test/libsolidity/gasTests/dispatch_small_optimised.sol index e20e1d982427..b59bdafc2780 100644 --- a/test/libsolidity/gasTests/dispatch_small_optimised.sol +++ b/test/libsolidity/gasTests/dispatch_small_optimised.sol @@ -5,8 +5,10 @@ contract Small { fallback () external payable {} } // ==== +// EVMVersion: =current // optimize: true // optimize-runs: 2 +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 58200 diff --git a/test/libsolidity/gasTests/exp.sol b/test/libsolidity/gasTests/exp.sol index 6ad4dd3bee43..40ef138136cd 100644 --- a/test/libsolidity/gasTests/exp.sol +++ b/test/libsolidity/gasTests/exp.sol @@ -15,6 +15,8 @@ contract C { } } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy // optimize: false // optimize-yul: false // ---- diff --git a/test/libsolidity/gasTests/exp_optimized.sol b/test/libsolidity/gasTests/exp_optimized.sol index 982fcd28feb9..fae9a24fd757 100644 --- a/test/libsolidity/gasTests/exp_optimized.sol +++ b/test/libsolidity/gasTests/exp_optimized.sol @@ -15,6 +15,8 @@ contract C { } } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy // optimize: true // optimize-yul: true // ---- diff --git a/test/libsolidity/gasTests/storage_costs.sol b/test/libsolidity/gasTests/storage_costs.sol index afb442ed7f97..871c15eab388 100644 --- a/test/libsolidity/gasTests/storage_costs.sol +++ b/test/libsolidity/gasTests/storage_costs.sol @@ -11,8 +11,10 @@ contract C { } } // ==== +// EVMVersion: =current // optimize: true // optimize-yul: true +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 25600 diff --git a/test/libsolidity/lsp/goto/goto_definition_imports.sol b/test/libsolidity/lsp/goto/goto_definition_imports.sol index dd0267d710b0..f58bd002c385 100644 --- a/test/libsolidity/lsp/goto/goto_definition_imports.sol +++ b/test/libsolidity/lsp/goto/goto_definition_imports.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0; import {Weather as Wetter} from "./lib.sol"; -// ^ @wheatherImportCursor +// ^ @weatherImportCursor import "./lib.sol" as That; // ^^^^ @ThatImport @@ -25,7 +25,7 @@ contract C // ---- // lib: @diagnostics 2072 // -> textDocument/definition { -// "position": @wheatherImportCursor +// "position": @weatherImportCursor // } // <- [ // { diff --git a/test/libsolidity/memoryGuardTests/shadowing_memoryguard_with_inline_assembly_identifiers.sol b/test/libsolidity/memoryGuardTests/shadowing_memoryguard_with_inline_assembly_identifiers.sol new file mode 100644 index 000000000000..5152882bb2a0 --- /dev/null +++ b/test/libsolidity/memoryGuardTests/shadowing_memoryguard_with_inline_assembly_identifiers.sol @@ -0,0 +1,26 @@ +// NOTE: memoryguard is a builtin but only in pure Yul, not inline assembly. +// NOTE: memoryguard is not a reserved identifier. + +contract C { + constructor() { + // The expectation of this test is to see a 'true' outcome, indicating the memoryguard builtin being used + // due to explicitly marking the inline assembly as memory-safe + + assembly ("memory-safe") { mstore(42, 42) function memoryguard() {} } + assembly ("memory-safe") { mstore(42, 42) function f(memoryguard) {} } + assembly ("memory-safe") { mstore(42, 42) function f() -> memoryguard {} } + assembly ("memory-safe") { mstore(42, 42) let memoryguard } + } + + function f() public pure { + // The expectation of this test is to see a 'false' outcome, indicating the memoryguard builtin not being used + + assembly { mstore(42, 42) function memoryguard() {} } + assembly { mstore(42, 42) function f(memoryguard) {} } + assembly { mstore(42, 42) function f() -> memoryguard {} } + assembly { mstore(42, 42) let memoryguard } + } +} +// ---- +// :C(creation) true +// :C(runtime) false diff --git a/test/libsolidity/natspecJSON/dev_mutiline_param_description.sol b/test/libsolidity/natspecJSON/dev_multiline_param_description.sol similarity index 100% rename from test/libsolidity/natspecJSON/dev_mutiline_param_description.sol rename to test/libsolidity/natspecJSON/dev_multiline_param_description.sol diff --git a/test/libsolidity/natspecJSON/storage_layout_specifier_no_doc.sol b/test/libsolidity/natspecJSON/storage_layout_specifier_no_doc.sol new file mode 100644 index 000000000000..9bb8f4a06e24 --- /dev/null +++ b/test/libsolidity/natspecJSON/storage_layout_specifier_no_doc.sol @@ -0,0 +1,23 @@ +contract C + /// @notice this changes the base slot of the contract storage + layout at + /// @dev the expression must be in range of uint256 + 0x1234 +{ } +// ==== +// stopAfter: analysis +// ---- +// ---- +// :C devdoc +// { +// "kind": "dev", +// "methods": {}, +// "version": 1 +// } +// +// :C userdoc +// { +// "kind": "user", +// "methods": {}, +// "version": 1 +// } diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_calldata.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_calldata.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_decode_calldata.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_calldata.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_declaration.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_declaration.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_declaration.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_declaration.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_is_consistent.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_is_consistent.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_is_consistent.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_is_consistent.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_memory.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_memory.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_memory.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_memory.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_special_args.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_special_args.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_special_args.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_special_args.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_uint_bytes.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_uint_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_uint_bytes.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_uint_bytes.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_empty_string_v1.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_empty_string_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_empty_string_v1.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_empty_string_v1.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_selector.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selector.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_selector.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selector.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_selectorv2.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selectorv2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_selectorv2.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selectorv2.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signature.sol similarity index 96% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signature.sol index 61a8d0b431b1..97d7273e9424 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol +++ b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signature.sol @@ -20,7 +20,7 @@ contract C { y[2] = type(uint).max - 2; y[3] = type(uint).max - 3; r = abi.encodeWithSignature(x, y); - // The hash uses temporary memory. This allocation re-uses the memory + // The hash uses temporary memory. This allocation reuses the memory // and should initialize it properly. ar = new uint[](2); } diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signaturev2.sol similarity index 97% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signaturev2.sol index 4020530864a0..b44d39c3498e 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol +++ b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signaturev2.sol @@ -20,7 +20,7 @@ contract C { y[2] = type(uint).max - 2; y[3] = type(uint).max - 3; r = abi.encodeWithSignature(x, y); - // The hash uses temporary memory. This allocation re-uses the memory + // The hash uses temporary memory. This allocation reuses the memory // and should initialize it properly. ar = new uint[](2); } diff --git a/test/libsolidity/semanticTests/abiencodedecode/contract_array.sol b/test/libsolidity/semanticTests/abiEncodeDecode/contract_array.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/contract_array.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/contract_array.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/contract_array_v2.sol b/test/libsolidity/semanticTests/abiEncodeDecode/contract_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/contract_array_v2.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/contract_array_v2.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding.sol b/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding_2.sol b/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding_2.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_2.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding_3.sol b/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_3.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding_3.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_3.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_2d_zeroed_memory_index_access.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_2d_zeroed_memory_index_access.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_2d_zeroed_memory_index_access.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_2d_zeroed_memory_index_access.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_array_static.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_array_static.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_array_static.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_array_static.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_static_return_param_zeroed_memory_index_access.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_static_return_param_zeroed_memory_index_access.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_static_return_param_zeroed_memory_index_access.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_static_return_param_zeroed_memory_index_access.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_static_zeroed_memory_index_access.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_static_zeroed_memory_index_access.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_static_zeroed_memory_index_access.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_static_zeroed_memory_index_access.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_zeroed_memory_index_access.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_zeroed_memory_index_access.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_zeroed_memory_index_access.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_zeroed_memory_index_access.sol diff --git a/test/libsolidity/semanticTests/array/nested_calldata_storage.sol b/test/libsolidity/semanticTests/array/nested_calldata_storage.sol new file mode 100644 index 000000000000..7cc9753bec8f --- /dev/null +++ b/test/libsolidity/semanticTests/array/nested_calldata_storage.sol @@ -0,0 +1,13 @@ +pragma abicoder v2; + +contract C { + uint[][2] public tmp_i; + function i(uint[][2] calldata s) external { tmp_i = s; } +} +// ==== +// compileViaYul: true +// ---- +// i(uint256[][2]): 0x20, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 +// gas irOptimized: 223100 +// tmp_i(uint256,uint256): 0, 0 -> 0x0A01 +// tmp_i(uint256,uint256): 1, 0 -> 0x0B01 diff --git a/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol b/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol new file mode 100644 index 000000000000..f8db31b54cc8 --- /dev/null +++ b/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol @@ -0,0 +1,13 @@ +pragma abicoder v2; + +contract C { + uint[][] public tmp_i; + function i(uint[][] calldata s) external { tmp_i = s; } +} +// ==== +// compileViaYul: true +// ---- +// i(uint256[][]): 0x20, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 +// gas irOptimized: 245506 +// tmp_i(uint256,uint256): 0, 0 -> 0x0A01 +// tmp_i(uint256,uint256): 1, 0 -> 0x0B01 diff --git a/test/libsolidity/semanticTests/builtinFunctions/keccak256_packed_complex_types.sol b/test/libsolidity/semanticTests/builtinFunctions/keccak256_packed_complex_types.sol index ea6d781898f0..fbecf750ab4f 100644 --- a/test/libsolidity/semanticTests/builtinFunctions/keccak256_packed_complex_types.sol +++ b/test/libsolidity/semanticTests/builtinFunctions/keccak256_packed_complex_types.sol @@ -7,8 +7,8 @@ contract C { x[2] = y[2] = uint120(type(uint).max - 3); hash1 = keccak256(abi.encodePacked(x)); hash2 = keccak256(abi.encodePacked(y)); - hash3 = keccak256(abi.encodePacked(this.f)); + hash3 = keccak256(abi.encodePacked(C(address(0x1234)))); } } // ---- -// f() -> 0xba4f20407251e4607cd66b90bfea19ec6971699c03e4a4f3ea737d5818ac27ae, 0xba4f20407251e4607cd66b90bfea19ec6971699c03e4a4f3ea737d5818ac27ae, 0x0e9229fb1d2cd02cee4b6c9f25497777014a8766e3479666d1c619066d2887ec +// f() -> 0xba4f20407251e4607cd66b90bfea19ec6971699c03e4a4f3ea737d5818ac27ae, 0xba4f20407251e4607cd66b90bfea19ec6971699c03e4a4f3ea737d5818ac27ae, 0xe7490fade3a8e31113ecb6c0d2635e28a6f5ca8359a57afe914827f41ddf0848 diff --git a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/cleanup/byte_array_to_storage_cleanup.sol similarity index 100% rename from test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol rename to test/libsolidity/semanticTests/cleanup/byte_array_to_storage_cleanup.sol diff --git a/test/libsolidity/semanticTests/dirty_calldata_bytes.sol b/test/libsolidity/semanticTests/cleanup/dirty_calldata_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/dirty_calldata_bytes.sol rename to test/libsolidity/semanticTests/cleanup/dirty_calldata_bytes.sol diff --git a/test/libsolidity/semanticTests/dirty_calldata_dynamic_array.sol b/test/libsolidity/semanticTests/cleanup/dirty_calldata_dynamic_array.sol similarity index 100% rename from test/libsolidity/semanticTests/dirty_calldata_dynamic_array.sol rename to test/libsolidity/semanticTests/cleanup/dirty_calldata_dynamic_array.sol diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 8fe8d36f9bb8..aeeb1a0c1aa4 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -22,6 +22,8 @@ contract Creator { ch = c.part(x); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 // gas irOptimized: 327784 diff --git a/test/libsolidity/semanticTests/constructor/base_constructor_arguments.sol b/test/libsolidity/semanticTests/constructor/base_constructor_arguments.sol index 55daf6d3d547..ee1ed30195e5 100644 --- a/test/libsolidity/semanticTests/constructor/base_constructor_arguments.sol +++ b/test/libsolidity/semanticTests/constructor/base_constructor_arguments.sol @@ -19,5 +19,7 @@ contract Derived is Base { return m_a; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getA() -> 49 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 69896ebf1584..55abe4804c56 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -22,6 +22,8 @@ contract Creator { ch = c.part(x); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" // gas irOptimized: 169292 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 036d6ca629a3..13db633b9b06 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -6,6 +6,8 @@ contract Test { m_s = s; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> // gas irOptimized: 181465 diff --git a/test/libsolidity/semanticTests/constructor/callvalue_check.sol b/test/libsolidity/semanticTests/constructor/callvalue_check.sol index f45fbed925ad..10086886a622 100644 --- a/test/libsolidity/semanticTests/constructor/callvalue_check.sol +++ b/test/libsolidity/semanticTests/constructor/callvalue_check.sol @@ -11,6 +11,7 @@ contract B4 { constructor() {} } contract C { function createWithValue(bytes memory c, uint256 value) public payable returns (bool) { uint256 y = 0; + // TODO: This test is hard to recreate for EOF as for now eofcreate is disallowed in inline assembly. assembly { y := create(value, add(c, 0x20), mload(c)) } return y != 0; } @@ -29,6 +30,7 @@ contract C { } // ==== // EVMVersion: >homestead +// bytecodeFormat: legacy // ---- // f(uint256), 2000 ether: 0 -> true // f(uint256), 2000 ether: 100 -> false diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol index 7d068338b091..e59cb4214a23 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol @@ -15,6 +15,8 @@ contract Main { return flag; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): "abc", true // gas irOptimized: 80174 diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol index bf3f0c0c9b74..a811d12c89f6 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol @@ -32,6 +32,8 @@ contract Main { return h.getName(); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getFlag() -> true // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol index 159f2943d432..76e5193d9720 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol @@ -3,5 +3,7 @@ contract D { constructor(function() external returns (uint)) { } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): 0xfdd67305928fcac8d213d1e47bfa6165cd0b87b946644cd0000000000000000 -> diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol index 13abe72c5cce..10a4ee06dbb5 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol @@ -15,6 +15,8 @@ contract C { return 16; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f() -> 16 // gas legacy: 78477 diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index 5947b257363f..ed4eb6e4d15f 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -7,6 +7,8 @@ contract C { b = _b; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): 1, 2, 3, 4 -> // gas irOptimized: 148129 diff --git a/test/libsolidity/semanticTests/constructor/evm_exceptions_in_constructor_call_fail.sol b/test/libsolidity/semanticTests/constructor/evm_exceptions_in_constructor_call_fail.sol index 43d1fdab848f..d45c65524902 100644 --- a/test/libsolidity/semanticTests/constructor/evm_exceptions_in_constructor_call_fail.sol +++ b/test/libsolidity/semanticTests/constructor/evm_exceptions_in_constructor_call_fail.sol @@ -13,6 +13,8 @@ contract B { ++test; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // testIt() -> // test() -> 2 diff --git a/test/libsolidity/semanticTests/constructor/function_usage_in_constructor_arguments.sol b/test/libsolidity/semanticTests/constructor/function_usage_in_constructor_arguments.sol index c04f039188c4..a736cab912fa 100644 --- a/test/libsolidity/semanticTests/constructor/function_usage_in_constructor_arguments.sol +++ b/test/libsolidity/semanticTests/constructor/function_usage_in_constructor_arguments.sol @@ -19,5 +19,7 @@ contract Derived is Base { return m_a; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getA() -> 2 diff --git a/test/libsolidity/semanticTests/constructor/functions_called_by_constructor.sol b/test/libsolidity/semanticTests/constructor/functions_called_by_constructor.sol index b968a07a161d..d70508b7645d 100644 --- a/test/libsolidity/semanticTests/constructor/functions_called_by_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/functions_called_by_constructor.sol @@ -14,5 +14,7 @@ contract Test { name = _name; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/constructor/functions_called_by_constructor_through_dispatch.sol b/test/libsolidity/semanticTests/constructor/functions_called_by_constructor_through_dispatch.sol index 0a1250a8ba62..ef7b5dcf8cad 100644 --- a/test/libsolidity/semanticTests/constructor/functions_called_by_constructor_through_dispatch.sol +++ b/test/libsolidity/semanticTests/constructor/functions_called_by_constructor_through_dispatch.sol @@ -24,5 +24,7 @@ contract Test { name = _shiftOperator(name, _bytes); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getName() -> "def\x00\x00\x00" diff --git a/test/libsolidity/semanticTests/constructor/inline_member_init_inheritence_without_constructor.sol b/test/libsolidity/semanticTests/constructor/inline_member_init_inheritence_without_constructor.sol index 320349cda9ed..13c80b7b6273 100644 --- a/test/libsolidity/semanticTests/constructor/inline_member_init_inheritence_without_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/inline_member_init_inheritence_without_constructor.sol @@ -14,6 +14,8 @@ contract Derived is Base { return m_derived; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getBMember() -> 5 // getDMember() -> 6 diff --git a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol index 583f1ca37b3f..a46b6a6a8e8d 100644 --- a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol +++ b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol @@ -9,17 +9,19 @@ contract B3 { constructor() payable {} } contract C { function f() public payable returns (bool) { // Make sure none of these revert. - new B1{value: 10}(); - new B2{value: 10}(); - new B3{value: 10}(); + new B1{value: 10, salt: hex"00"}(); + new B2{value: 10, salt: hex"01"}(); + new B3{value: 10, salt: hex"02"}(); return true; } } +// ==== +// EVMVersion: >=constantinople // ---- // f(), 2000 ether -> true -// gas irOptimized: 117623 +// gas irOptimized: 117688 // gas irOptimized code: 1800 -// gas legacy: 117821 +// gas legacy: 117889 // gas legacy code: 4800 -// gas legacyOptimized: 117690 +// gas legacyOptimized: 117761 // gas legacyOptimized code: 4800 diff --git a/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol b/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol index 2416f124ec37..14bb7cf07c6c 100644 --- a/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol +++ b/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol @@ -18,5 +18,7 @@ contract X is D, C, B, A { function g() public view returns (uint[] memory) { return x; } constructor() A(f(1)) C(f(2)) B(f(3)) D(f(4)) {} } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // g() -> 0x20, 4, 1, 3, 2, 4 diff --git a/test/libsolidity/semanticTests/constructor/payable_constructor.sol b/test/libsolidity/semanticTests/constructor/payable_constructor.sol index 09fe0a1cc32d..1020f697dd06 100644 --- a/test/libsolidity/semanticTests/constructor/payable_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/payable_constructor.sol @@ -1,5 +1,7 @@ contract C { constructor() payable {} } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(), 27 wei -> diff --git a/test/libsolidity/semanticTests/state_var_initialization.sol b/test/libsolidity/semanticTests/constructor/state_variable_initialization.sol similarity index 100% rename from test/libsolidity/semanticTests/state_var_initialization.sol rename to test/libsolidity/semanticTests/constructor/state_variable_initialization.sol diff --git a/test/libsolidity/semanticTests/constructor/store_function_in_constructor.sol b/test/libsolidity/semanticTests/constructor/store_function_in_constructor.sol index dee3af35415f..7bc2982b78f1 100644 --- a/test/libsolidity/semanticTests/constructor/store_function_in_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/store_function_in_constructor.sol @@ -15,6 +15,8 @@ contract C { return x(_arg); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // use(uint256): 3 -> 6 // result_in_constructor() -> 4 diff --git a/test/libsolidity/semanticTests/constructor/store_function_in_constructor_packed.sol b/test/libsolidity/semanticTests/constructor/store_function_in_constructor_packed.sol index 07b12ad96cb7..b0a20f14310d 100644 --- a/test/libsolidity/semanticTests/constructor/store_function_in_constructor_packed.sol +++ b/test/libsolidity/semanticTests/constructor/store_function_in_constructor_packed.sol @@ -16,6 +16,8 @@ contract C { return x(_arg); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // use(uint16): 3 -> 0xfff9 // result_in_constructor() -> 0xfffb diff --git a/test/libsolidity/semanticTests/constructor/store_internal_unused_function_in_constructor.sol b/test/libsolidity/semanticTests/constructor/store_internal_unused_function_in_constructor.sol index cc9d8ca6a134..905e1d3492d0 100644 --- a/test/libsolidity/semanticTests/constructor/store_internal_unused_function_in_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/store_internal_unused_function_in_constructor.sol @@ -13,5 +13,7 @@ contract C { return x(); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // t() -> 7 diff --git a/test/libsolidity/semanticTests/constructor/store_internal_unused_library_function_in_constructor.sol b/test/libsolidity/semanticTests/constructor/store_internal_unused_library_function_in_constructor.sol index 5845e9b56e15..b7d9bb5f454b 100644 --- a/test/libsolidity/semanticTests/constructor/store_internal_unused_library_function_in_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/store_internal_unused_library_function_in_constructor.sol @@ -16,5 +16,7 @@ contract C { return x(); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // t() -> 7 diff --git a/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol b/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol index 3260fa30ff23..46a9090c24d8 100644 --- a/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol +++ b/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol @@ -14,5 +14,6 @@ contract C { // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy,>=EOFv1 // ---- // f() -> 100 diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol index 64b80422c352..69a4bd65b1d9 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. function longdata(S memory) pure returns (bytes memory) { return "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" @@ -36,5 +37,7 @@ contract C { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol index 931109199649..28843b25d19d 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. library L { function longdata() pure internal returns (bytes memory) { return @@ -30,5 +31,7 @@ contract C { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol index 018d410557b0..8e075654f313 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. ==== Source: mod.sol ==== function longdata() pure returns (bytes memory) { return @@ -32,5 +33,7 @@ contract C { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol index 0f9b023b08d9..255e99e82489 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. abstract contract S { function longdata() internal pure returns (bytes memory) { return @@ -31,5 +32,7 @@ contract C is S { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/subassembly_deduplication.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/subassembly_deduplication.sol index b6ae85b838d8..4425475695a1 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/subassembly_deduplication.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/subassembly_deduplication.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. contract A { function longdata() pure external returns (bytes memory) { return @@ -37,5 +38,7 @@ contract C { x < 2 * type(A).creationCode.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol index 9accc54a2b05..17aabdf83832 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. abstract contract S { function longdata() internal pure returns (bytes memory) { return @@ -31,5 +32,7 @@ contract C is S { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol index 866fe9dfc452..322de3c84435 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. abstract contract S { function longdata() internal virtual pure returns (bytes memory); } @@ -35,5 +36,7 @@ contract C is X { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/ecrecover/ecrecover.sol b/test/libsolidity/semanticTests/ecrecover/ecrecover.sol index 1beb451de8b0..41b0bf86590a 100644 --- a/test/libsolidity/semanticTests/ecrecover/ecrecover.sol +++ b/test/libsolidity/semanticTests/ecrecover/ecrecover.sol @@ -3,6 +3,8 @@ contract test { return ecrecover(h, v, r, s); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // a(bytes32,uint8,bytes32,bytes32): // 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c, diff --git a/test/libsolidity/semanticTests/ecrecover/failing_ecrecover_invalid_input.sol b/test/libsolidity/semanticTests/ecrecover/failing_ecrecover_invalid_input.sol index 55621bdcdae6..ee3f4c6bec51 100644 --- a/test/libsolidity/semanticTests/ecrecover/failing_ecrecover_invalid_input.sol +++ b/test/libsolidity/semanticTests/ecrecover/failing_ecrecover_invalid_input.sol @@ -1,7 +1,7 @@ contract C { // ecrecover should return zero for malformed input - // (v should be 27 or 28, not 1) - // Note that the precompile does not return zero but returns nothing. + // (v should be 27 or 28, not 1) + // Note that the precompile does not return zero but returns nothing. function f() public returns (address) { return ecrecover(bytes32(type(uint256).max), 1, bytes32(uint(2)), bytes32(uint(3))); } diff --git a/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol b/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol index bc70b5bef757..906fd0597d53 100644 --- a/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol +++ b/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol @@ -27,10 +27,10 @@ contract C { require(false, E3(S(1, true, "string literal"))); } function e() external view { - require(false, E4(address(this))); + require(false, E4(address(0x1234))); } function f() external view { - require(false, E5(this.a)); + require(false, E5(C(address(0x1234)).a)); } } @@ -41,5 +41,5 @@ contract C { // b() -> FAILURE, hex"47e26897", hex"0000000000000000000000000000000000000000000000000000000000000001" // c() -> FAILURE, hex"8f372c34", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000e", hex"737472696e67206c69746572616c000000000000000000000000000000000000" // d() -> FAILURE, hex"5717173e", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"000000000000000000000000000000000000000000000000000000000000000e", hex"737472696e67206c69746572616c000000000000000000000000000000000000" -// e() -> FAILURE, hex"7efef9ea", hex"000000000000000000000000c06afe3a8444fc0004668591e8306bfb9968e79e" -// f() -> FAILURE, hex"0c3f12eb", hex"c06afe3a8444fc0004668591e8306bfb9968e79e0dbe671f0000000000000000" +// e() -> FAILURE, hex"7efef9ea", hex"0000000000000000000000000000000000000000000000000000000000001234" +// f() -> FAILURE, hex"0c3f12eb", hex"00000000000000000000000000000000000012340dbe671f0000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol b/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol index 3af19ca64fbf..7a82d4f81e35 100644 --- a/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol +++ b/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol @@ -10,9 +10,9 @@ contract C function f() external view { // more than one stack slot - require(false, CustomError(this.e)); + require(false, CustomError(C(address(0x1234)).e)); } } // ---- -// f() -> FAILURE, hex"271b1dfa", hex"c06afe3a8444fc0004668591e8306bfb9968e79ef37cdc8e0000000000000000" +// f() -> FAILURE, hex"271b1dfa", hex"0000000000000000000000000000000000001234f37cdc8e0000000000000000" diff --git a/test/libsolidity/semanticTests/emit_three_identical_events.sol b/test/libsolidity/semanticTests/events/emit_three_identical_events.sol similarity index 100% rename from test/libsolidity/semanticTests/emit_three_identical_events.sol rename to test/libsolidity/semanticTests/events/emit_three_identical_events.sol diff --git a/test/libsolidity/semanticTests/emit_two_identical_events.sol b/test/libsolidity/semanticTests/events/emit_two_identical_events.sol similarity index 100% rename from test/libsolidity/semanticTests/emit_two_identical_events.sol rename to test/libsolidity/semanticTests/events/emit_two_identical_events.sol 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 61e1bbdd6c0e..e6d800d9b229 100644 --- a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol +++ b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol @@ -1,3 +1,5 @@ +// TODO: Implement this test for EOF. Now it's not possible because deployed contract address depends on contract bytecode. +// This means that the address changes when optimisations are applied. contract D { event Deposit(address indexed _from, bytes32 indexed _id, uint _value); function deposit(bytes32 _id) public payable { @@ -13,6 +15,8 @@ contract C { d.deposit(_id); } } +// ==== +// bytecodeFormat: legacy // ---- // constructor() -> // gas irOptimized: 113970 diff --git a/test/libsolidity/semanticTests/events/event_indexed_function.sol b/test/libsolidity/semanticTests/events/event_indexed_function.sol index ea7574159500..29b19dbe711d 100644 --- a/test/libsolidity/semanticTests/events/event_indexed_function.sol +++ b/test/libsolidity/semanticTests/events/event_indexed_function.sol @@ -1,9 +1,9 @@ contract C { event Test(function() external indexed); function f() public { - emit Test(this.f); + emit Test(C(address(0x1234)).f); } } // ---- // f() -> -// ~ emit Test(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79e26121ff00000000000000000 +// ~ emit Test(function): #0x123426121ff00000000000000000 diff --git a/test/libsolidity/semanticTests/events/event_indexed_function2.sol b/test/libsolidity/semanticTests/events/event_indexed_function2.sol index d4c47e868a1f..9587f8c37778 100644 --- a/test/libsolidity/semanticTests/events/event_indexed_function2.sol +++ b/test/libsolidity/semanticTests/events/event_indexed_function2.sol @@ -2,14 +2,14 @@ contract C { event TestA(function() external indexed); event TestB(function(uint256) external indexed); function f1() public { - emit TestA(this.f1); + emit TestA(C(address(0x1234)).f1); } function f2(uint256 a) public { - emit TestB(this.f2); + emit TestB(C(address(0x1234)).f2); } } // ---- // f1() -> -// ~ emit TestA(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79ec27fc3050000000000000000 +// ~ emit TestA(function): #0x1234c27fc3050000000000000000 // f2(uint256): 1 -> -// ~ emit TestB(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79ebf3724af0000000000000000 +// ~ emit TestB(function): #0x1234bf3724af0000000000000000 diff --git a/test/libsolidity/semanticTests/experimental/stub.sol b/test/libsolidity/semanticTests/experimental/stub.sol index 6e7a750fe980..d2d0999bfb76 100644 --- a/test/libsolidity/semanticTests/experimental/stub.sol +++ b/test/libsolidity/semanticTests/experimental/stub.sol @@ -92,6 +92,7 @@ contract C { // EVMVersion: >=constantinople // ==== // compileViaYul: true +// bytecodeFormat: legacy // ---- // (): 0 -> 0 // (): 1 -> 544 diff --git a/test/libsolidity/semanticTests/experimental/type_class.sol b/test/libsolidity/semanticTests/experimental/type_class.sol index 69fa568dfd96..7331c0dbd73c 100644 --- a/test/libsolidity/semanticTests/experimental/type_class.sol +++ b/test/libsolidity/semanticTests/experimental/type_class.sol @@ -63,5 +63,6 @@ contract C { // ==== // EVMVersion: >=constantinople // compileViaYul: true +// bytecodeFormat: legacy // ---- // () -> 1, 0 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 906279d17935..c073993e1d37 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -1,3 +1,5 @@ +pragma abicoder v2; + library Pairing { struct G1Point { uint X; @@ -40,13 +42,9 @@ library Pairing { input[1] = p1.Y; input[2] = p2.X; input[3] = p2.Y; - bool success; - assembly { - success := call(sub(gas(), 2000), 6, 0, input, 0xc0, r, 0x60) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } + (bool success, bytes memory encodedResult) = address(6).call(abi.encode(input)); require(success); + r = abi.decode(encodedResult, (G1Point)); } /// @return r the product of a point on G1 and a scalar, i.e. @@ -56,13 +54,9 @@ library Pairing { input[0] = p.X; input[1] = p.Y; input[2] = s; - bool success; - assembly { - success := call(sub(gas(), 2000), 7, 0, input, 0x80, r, 0x60) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } + (bool success, bytes memory encodedResult) = address(7).call(abi.encode(input)); require(success); + r = abi.decode(encodedResult, (G1Point)); } /// @return the result of computing the pairing check @@ -83,15 +77,19 @@ library Pairing { input[i * 6 + 4] = p2[i].Y[0]; input[i * 6 + 5] = p2[i].Y[1]; } - uint[1] memory out; - bool success; - assembly { - success := call(sub(gas(), 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } + + bytes memory encodedInput = new bytes(inputSize * 32); + for (uint i = 0; i < inputSize; i++) + { + uint offset = (i + 1) * 32; + uint item = input[i]; + assembly ("memory-safe") { + mstore(add(encodedInput, offset), item) + } } + (bool success, bytes memory encodedResult) = address(8).call(encodedInput); require(success); - return out[0] != 0; + return abi.decode(encodedResult, (bool)); } function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal returns (bool) { G1Point[] memory p1 = new G1Point[](2); @@ -294,11 +292,11 @@ contract Test { // f() -> true // g() -> true // pair() -> true -// gas irOptimized: 270409 -// gas legacy: 275219 -// gas legacyOptimized: 266862 +// gas irOptimized: 275229 +// gas legacy: 293579 +// gas legacyOptimized: 276313 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." -// gas irOptimized: 785720 -// gas legacy: 801903 -// gas legacyOptimized: 770941 +// gas irOptimized: 818076 +// gas legacy: 904397 +// gas legacyOptimized: 816770 diff --git a/test/libsolidity/semanticTests/externalSource/_non_normalized_paths/a.sol b/test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/a.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_non_normalized_paths/a.sol rename to test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/a.sol diff --git a/test/libsolidity/semanticTests/externalSource/_non_normalized_paths/c.sol b/test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/c.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_non_normalized_paths/c.sol rename to test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/c.sol diff --git a/test/libsolidity/semanticTests/externalSource/_non_normalized_paths/d.sol b/test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/d.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_non_normalized_paths/d.sol rename to test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/d.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/D/d.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/D/d.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/D/d.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/D/d.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/c.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/c.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/c.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/c.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/B/b.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/B/b.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/dir/B/b.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/dir/B/b.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/G/g.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/G/g.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/dir/G/g.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/dir/G/g.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/a.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/a.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/dir/a.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/dir/a.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/contract.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/contract.sol similarity index 76% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/dir/contract.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/dir/contract.sol index aab81b975c5b..e41d935a233d 100644 --- a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/contract.sol +++ b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/contract.sol @@ -3,6 +3,6 @@ import {B} from "./B/b.sol"; import {C} from "../c.sol"; import {D} from "../D/d.sol"; import {G} from "./E/../F/../G/./g.sol"; -import {H} from "../../../../_relative_imports/h.sol"; +import {H} from "../../../../_relativeImports/h.sol"; contract Contract { } diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/h.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/h.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/h.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/h.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/b.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/b.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/b.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/b.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dir/a.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dir/a.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dir/a.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dir/a.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dir/contract.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dir/contract.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dir/contract.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dir/contract.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dot_a.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dot_a.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dot_a.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dot_a.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dot_dot_b.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dot_dot_b.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dot_dot_b.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dot_dot_b.sol diff --git a/test/libsolidity/semanticTests/externalSource/non_normalized_paths.sol b/test/libsolidity/semanticTests/externalSource/non_normalized_paths.sol index 7316cc7d57fd..84ad75514f99 100644 --- a/test/libsolidity/semanticTests/externalSource/non_normalized_paths.sol +++ b/test/libsolidity/semanticTests/externalSource/non_normalized_paths.sol @@ -1,7 +1,7 @@ -==== ExternalSource: _non_normalized_paths//a.sol ==== -==== ExternalSource: C/////c.sol=_non_normalized_paths/c.sol ==== -==== ExternalSource: C/../////D/d.sol=_non_normalized_paths///d.sol ==== -import {A} from "_non_normalized_paths//a.sol"; +==== ExternalSource: _nonNormalizedPaths//a.sol ==== +==== ExternalSource: C/////c.sol=_nonNormalizedPaths/c.sol ==== +==== ExternalSource: C/../////D/d.sol=_nonNormalizedPaths///d.sol ==== +import {A} from "_nonNormalizedPaths//a.sol"; import {C} from "C/////c.sol"; import {D} from "C/../////D/d.sol"; contract Contract { diff --git a/test/libsolidity/semanticTests/externalSource/relative_imports.sol b/test/libsolidity/semanticTests/externalSource/relative_imports.sol index 9a37896bb568..e8e4022294fc 100644 --- a/test/libsolidity/semanticTests/externalSource/relative_imports.sol +++ b/test/libsolidity/semanticTests/externalSource/relative_imports.sol @@ -1,11 +1,11 @@ -==== ExternalSource: _relative_imports/dir/contract.sol ==== -==== ExternalSource: _relative_imports/dir/a.sol ==== -==== ExternalSource: _relative_imports/dir/B/b.sol ==== -==== ExternalSource: _relative_imports/c.sol ==== -==== ExternalSource: _relative_imports/D/d.sol ==== -==== ExternalSource: _relative_imports/dir/G/g.sol ==== -==== ExternalSource: _relative_imports/h.sol ==== -import {A, B, C, D, G, H, Contract} from "_relative_imports/dir/contract.sol"; +==== ExternalSource: _relativeImports/dir/contract.sol ==== +==== ExternalSource: _relativeImports/dir/a.sol ==== +==== ExternalSource: _relativeImports/dir/B/b.sol ==== +==== ExternalSource: _relativeImports/c.sol ==== +==== ExternalSource: _relativeImports/D/d.sol ==== +==== ExternalSource: _relativeImports/dir/G/g.sol ==== +==== ExternalSource: _relativeImports/h.sol ==== +import {A, B, C, D, G, H, Contract} from "_relativeImports/dir/contract.sol"; contract CC { } // ---- diff --git a/test/libsolidity/semanticTests/externalSource/source_name_starting_with_dots.sol b/test/libsolidity/semanticTests/externalSource/source_name_starting_with_dots.sol index b671c94f9f9d..bb325b39110f 100644 --- a/test/libsolidity/semanticTests/externalSource/source_name_starting_with_dots.sol +++ b/test/libsolidity/semanticTests/externalSource/source_name_starting_with_dots.sol @@ -1,9 +1,9 @@ -==== ExternalSource: ./a.sol=_source_name_starting_with_dots/dot_a.sol ==== -==== ExternalSource: ../b.sol=_source_name_starting_with_dots/dot_dot_b.sol ==== -==== ExternalSource: _source_name_starting_with_dots/dir/a.sol ==== -==== ExternalSource: _source_name_starting_with_dots/b.sol ==== -==== ExternalSource: _source_name_starting_with_dots/dir/contract.sol ==== -import {A, B} from "_source_name_starting_with_dots/dir/contract.sol"; +==== ExternalSource: ./a.sol=_sourceNameStartingWithDots/dot_a.sol ==== +==== ExternalSource: ../b.sol=_sourceNameStartingWithDots/dot_dot_b.sol ==== +==== ExternalSource: _sourceNameStartingWithDots/dir/a.sol ==== +==== ExternalSource: _sourceNameStartingWithDots/b.sol ==== +==== ExternalSource: _sourceNameStartingWithDots/dir/contract.sol ==== +import {A, B} from "_sourceNameStartingWithDots/dir/contract.sol"; contract Contract { } // ---- diff --git a/test/libsolidity/semanticTests/freeFunctions/free_runtimecode.sol b/test/libsolidity/semanticTests/freeFunctions/free_runtimecode.sol index 7a05ff5d0270..e414b8205ba7 100644 --- a/test/libsolidity/semanticTests/freeFunctions/free_runtimecode.sol +++ b/test/libsolidity/semanticTests/freeFunctions/free_runtimecode.sol @@ -11,5 +11,7 @@ contract D { return test(); } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> true diff --git a/test/libsolidity/semanticTests/functionCall/bare_call_no_returndatacopy.sol b/test/libsolidity/semanticTests/functionCall/bare_call_no_returndatacopy.sol index 17b6f74c8739..3b3afab3bf07 100644 --- a/test/libsolidity/semanticTests/functionCall/bare_call_no_returndatacopy.sol +++ b/test/libsolidity/semanticTests/functionCall/bare_call_no_returndatacopy.sol @@ -1,6 +1,7 @@ contract C { function f() public returns (bool) { - (bool success, ) = address(1).call(""); + // Random address, no contract deployed to it. + (bool success, ) = address(0xffff).call(""); return success; } } diff --git a/test/libsolidity/semanticTests/functionCall/call_options_overload.sol b/test/libsolidity/semanticTests/functionCall/call_options_overload.sol index b9eb6ca42892..61e979f17536 100644 --- a/test/libsolidity/semanticTests/functionCall/call_options_overload.sol +++ b/test/libsolidity/semanticTests/functionCall/call_options_overload.sol @@ -10,6 +10,8 @@ contract C { function bal() external returns (uint) { return address(this).balance; } receive() external payable {} } +// ==== +// bytecodeFormat: legacy // ---- // (), 1 ether // call() -> 1, 2, 2, 2 diff --git a/test/libsolidity/semanticTests/functionCall/calling_nonexisting_contract_throws.sol b/test/libsolidity/semanticTests/functionCall/calling_nonexisting_contract_throws.sol index 229618384d1e..36dfc844d934 100644 --- a/test/libsolidity/semanticTests/functionCall/calling_nonexisting_contract_throws.sol +++ b/test/libsolidity/semanticTests/functionCall/calling_nonexisting_contract_throws.sol @@ -21,6 +21,8 @@ contract C { return 7; } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> FAILURE // g() -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/eof/call_options_overload.sol b/test/libsolidity/semanticTests/functionCall/eof/call_options_overload.sol new file mode 100644 index 000000000000..1ddc06c1dd2c --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/eof/call_options_overload.sol @@ -0,0 +1,16 @@ +contract C { + function f(uint x) external payable returns (uint) { return 1; } + function f(uint x, uint y) external payable returns (uint) { return 2; } + function call() public payable returns (uint x, uint y) { + x = this.f{value: 10}(2); + y = this.f{value: 10}(2, 3); + } + function bal() external returns (uint) { return address(this).balance; } + receive() external payable {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// (), 1 ether +// call() -> 1, 2 +// bal() -> 1000000000000000000 diff --git a/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol b/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol new file mode 100644 index 000000000000..10b39634d5de --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol @@ -0,0 +1,25 @@ +abstract contract D { + function g() public virtual; +} + + +contract C { + D d = D(address(0x1212)); + + function f() public returns (uint256) { + // This call throws on legacy bytecode because of calling nonexisting contract. Legacy checks that there is + // a non-empty code under under an address. EOF doesn't do it because non-observability assumption + d.g(); + return 7; + } + + function h() public returns (uint256) { + address(d).call(""); // this does not throw (low-level) + return 7; + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// f() -> 7 +// h() -> 7 diff --git a/test/libsolidity/semanticTests/functionCall/eof/external_call_at_construction_time.sol b/test/libsolidity/semanticTests/functionCall/eof/external_call_at_construction_time.sol new file mode 100644 index 000000000000..6235562c990f --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/eof/external_call_at_construction_time.sol @@ -0,0 +1,24 @@ +// This tests skipping the extcodesize check. + +contract T { + constructor() { this.f(); } + function f() external {} +} +contract U { + constructor() { this.f(); } + function f() external returns (uint) {} +} + +contract C { + function f(uint c) external returns (uint) { + if (c == 0) new T(); + else if (c == 1) new U(); + return 1 + c; + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// f(uint256): 0 -> 1 +// f(uint256): 1 -> FAILURE +// f(uint256): 2 -> 3 diff --git a/test/libsolidity/semanticTests/functionCall/eof/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/eof/external_call_to_nonexisting.sol new file mode 100644 index 000000000000..bc39e963344b --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/eof/external_call_to_nonexisting.sol @@ -0,0 +1,39 @@ +// This tests skipping the extcodesize check. + +interface I { + function a() external pure; + function b() external; + function c() external payable; + function x() external returns (uint); + function y() external returns (string memory); +} +contract C { + I i = I(address(0xcafecafe)); + constructor() payable {} + function f(uint c) external returns (uint) { + if (c == 0) i.a(); + else if (c == 1) i.b(); + else if (c == 2) i.c(); + else if (c == 3) i.c{value: 1}(); + else if (c == 4) i.x(); + else if (c == 5) i.y(); + return 1 + c; + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// constructor(), 1 ether -> +// gas irOptimized: 88853 +// gas irOptimized code: 164400 +// gas legacy: 102721 +// gas legacy code: 334400 +// gas legacyOptimized: 91499 +// gas legacyOptimized code: 196400 +// f(uint256): 0 -> 1 +// f(uint256): 1 -> 2 +// f(uint256): 2 -> 3 +// f(uint256): 3 -> 4 +// f(uint256): 4 -> FAILURE +// f(uint256): 5 -> FAILURE +// f(uint256): 6 -> 7 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_at_construction_time.sol b/test/libsolidity/semanticTests/functionCall/external_call_at_construction_time.sol index 6f7f020fe678..c5fa0538e6e7 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_at_construction_time.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_at_construction_time.sol @@ -18,6 +18,7 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // f(uint256): 0 -> FAILURE // f(uint256): 1 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index 472921c1d25c..0031059c021a 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -20,6 +20,8 @@ contract C { return 1 + c; } } +// ==== +// bytecodeFormat: legacy // ---- // constructor(), 1 ether -> // gas irOptimized: 88853 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 d1b6e8e866ae..a8eafb38ea1a 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -23,6 +23,7 @@ contract C { // ==== // EVMVersion: >=byzantium // revertStrings: debug +// bytecodeFormat: legacy // ---- // constructor(), 1 ether -> // gas irOptimized: 98698 diff --git a/test/libsolidity/semanticTests/functionCall/failed_create.sol b/test/libsolidity/semanticTests/functionCall/failed_create.sol index 657b4b5cfff6..87bd12d58b75 100644 --- a/test/libsolidity/semanticTests/functionCall/failed_create.sol +++ b/test/libsolidity/semanticTests/functionCall/failed_create.sol @@ -2,35 +2,35 @@ contract D { constructor() payable {} } contract C { uint public x; constructor() payable {} - function f(uint amount) public returns (D) { + function f(uint amount) public { x++; - return (new D){value: amount}(); + (new D){value: amount, salt: bytes32(x)}(); } - function stack(uint depth) public payable returns (address) { + function stack(uint depth) public payable { if (depth > 0) - return this.stack(depth - 1); + this.stack(depth - 1); else - return address(f(0)); + f(0); } } // ==== -// EVMVersion: >=byzantium +// EVMVersion: >=constantinople // ---- // constructor(), 20 wei -// gas irOptimized: 61548 -// gas irOptimized code: 104600 -// gas legacy: 70147 -// gas legacy code: 215400 -// gas legacyOptimized: 61715 -// gas legacyOptimized code: 106800 -// f(uint256): 20 -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a +// gas irOptimized: 59688 +// gas irOptimized code: 81800 +// gas legacy: 64468 +// gas legacy code: 145400 +// gas legacyOptimized: 60443 +// gas legacyOptimized code: 91200 +// f(uint256): 20 -> // x() -> 1 // f(uint256): 20 -> FAILURE // x() -> 1 // stack(uint256): 1023 -> FAILURE -// gas irOptimized: 252410 -// gas legacy: 476845 -// gas legacyOptimized: 299061 +// gas irOptimized: 298110 +// gas legacy: 527207 +// gas legacyOptimized: 353607 // x() -> 1 -// stack(uint256): 10 -> 0x87948bd7ebbe13a00bfd930c93e4828ab18e3908 +// stack(uint256): 10 -> // x() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index e6187d06e2df..7415accabcd2 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -13,8 +13,6 @@ contract helper { return flag; } } - - contract test { helper h; @@ -36,6 +34,8 @@ contract test { myBal = address(this).balance; } } +// ==== +// bytecodeFormat: legacy // ---- // constructor(), 20 wei -> // gas irOptimized: 120218 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol deleted file mode 100644 index 41079af03955..000000000000 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ /dev/null @@ -1,48 +0,0 @@ -contract helper { - bool flag; - - function getBalance() payable public returns(uint256 myBalance) { - return address(this).balance; - } - - function setFlag() public { - flag = true; - } - - function getFlag() public returns(bool fl) { - return flag; - } -} -contract test { - helper h; - constructor() payable { - h = new helper(); - } - - function sendAmount(uint amount) public payable returns(uint256 bal) { - return h.getBalance{value: amount}(); - } - - function outOfGas() public returns(bool ret) { - h.setFlag { - gas: 2 - }(); // should fail due to OOG - return true; - } - - function checkState() public returns(bool flagAfter, uint myBal) { - flagAfter = h.getFlag(); - myBal = address(this).balance; - } -} -// ---- -// constructor(), 20 wei -> -// gas irOptimized: 120218 -// gas irOptimized code: 132000 -// gas legacy: 130583 -// gas legacy code: 261200 -// gas legacyOptimized: 121069 -// gas legacyOptimized code: 147000 -// sendAmount(uint256): 5 -> 5 -// outOfGas() -> FAILURE # call to helper should not succeed but amount should be transferred anyway # -// checkState() -> false, 15 diff --git a/test/libsolidity/semanticTests/functionTypes/address_member.sol b/test/libsolidity/semanticTests/functionTypes/address_member.sol index a5f56f3dc688..214752a1f45c 100644 --- a/test/libsolidity/semanticTests/functionTypes/address_member.sol +++ b/test/libsolidity/semanticTests/functionTypes/address_member.sol @@ -1,10 +1,10 @@ contract C { function f() public view returns (address a1, address a2) { - a1 = this.f.address; - this.f.address; - [this.f.address][0]; - a2 = [this.f.address][0]; + a1 = C(address(0x1234)).f.address; + C(address(0x1234)).f.address; + [C(address(0x1234)).f.address][0]; + a2 = [C(address(0x1234)).f.address][0]; } } // ---- -// f() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e, 0xc06afe3a8444fc0004668591e8306bfb9968e79e +// f() -> 0x1234, 0x1234 diff --git a/test/libsolidity/semanticTests/functionTypes/function_external_delete_storage.sol b/test/libsolidity/semanticTests/functionTypes/function_external_delete_storage.sol index d5e105e5f536..1d8d1897c8f6 100644 --- a/test/libsolidity/semanticTests/functionTypes/function_external_delete_storage.sol +++ b/test/libsolidity/semanticTests/functionTypes/function_external_delete_storage.sol @@ -1,17 +1,19 @@ contract C { function() external public x; - uint public y = 0; - function increment() public { - ++y; - } + function f() public {} function set() external { - x = this.increment; + x = this.f; + } + + function isF() external returns (bool) { + return x == this.f; } - function incrementIndirectly() public { - x(); + function isZero() external returns (bool) { + function() external zero; + return x == zero; } function deleteFunction() public { @@ -20,18 +22,14 @@ contract C { } } // ---- -// x() -> 0 -// y() -> 0 -// increment() -> -// y() -> 1 +// isF() -> false +// isZero() -> true +// deleteFunction() -> +// isF() -> false +// isZero() -> true // set() -> -// x() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79ed09de08a0000000000000000 -// increment() -> -// y() -> 2 -// incrementIndirectly() -> -// y() -> 3 +// isF() -> true +// isZero() -> false // deleteFunction() -> -// increment() -> -// y() -> 4 -// incrementIndirectly() -> FAILURE -// y() -> 4 +// isF() -> false +// isZero() -> true diff --git a/test/libsolidity/semanticTests/functionTypes/stack_height_check_on_adding_gas_variable_to_function.sol b/test/libsolidity/semanticTests/functionTypes/stack_height_check_on_adding_gas_variable_to_function.sol index f811988fec9a..1ca391e81095 100644 --- a/test/libsolidity/semanticTests/functionTypes/stack_height_check_on_adding_gas_variable_to_function.sol +++ b/test/libsolidity/semanticTests/functionTypes/stack_height_check_on_adding_gas_variable_to_function.sol @@ -19,5 +19,7 @@ contract C { return true; } } +// ==== +// bytecodeFormat: legacy // ---- // test_function() -> true diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index aa8a1ad8a860..515dd41bb1b1 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -18,20 +18,22 @@ contract C { uint public y; constructor() { a = 3; - x = (new A()).f(); - y = (new B()).f(); + x = (new A{salt: hex"00"}()).f(); + y = (new B{salt: hex"00"}()).f(); } function f() public returns (uint256, uint, uint) { - return (a, (new A()).f(), (new B()).f()); + return (a, (new A{salt: hex"01"}()).f(), (new B{salt: hex"01"}()).f()); } } +// ==== +// EVMVersion: >=constantinople // ---- // f() -> 3, 7, 5 -// gas irOptimized: 86796 +// gas irOptimized: 86892 // gas irOptimized code: 37200 -// gas legacy: 87727 +// gas legacy: 87839 // gas legacy code: 60800 -// gas legacyOptimized: 86770 +// gas legacyOptimized: 86870 // gas legacyOptimized code: 37200 // x() -> 7 // y() -> 5 diff --git a/test/libsolidity/semanticTests/immutable/stub.sol b/test/libsolidity/semanticTests/immutable/stub.sol index 092edfab4fa8..c528b1aa7c0e 100644 --- a/test/libsolidity/semanticTests/immutable/stub.sol +++ b/test/libsolidity/semanticTests/immutable/stub.sol @@ -9,5 +9,7 @@ contract C { return (x+x,y); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f() -> 84, 23 diff --git a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol index 0865ed2876ad..90a3f9ec8c1f 100644 --- a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol +++ b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol @@ -11,19 +11,21 @@ contract C { contract D { function f() public returns (uint256) { - return (new C()).balance(); + return (new C{salt: hex"00"}()).balance(); } function g() public returns (uint256) { - return (new C()).transfer(5); + return (new C{salt: hex"01"}()).transfer(5); } } +// ==== +// EVMVersion: >=constantinople // ---- // f() -> 1 // gas irOptimized: 77051 -// gas legacy: 54480 +// gas legacy: 54553 // gas legacy code: 57800 // g() -> 5 // gas irOptimized: 77106 -// gas legacy: 55016 +// gas legacy: 55090 // gas legacy code: 57800 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol b/test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_inheritance_init_order.sol rename to test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order.sol diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol b/test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_2.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol rename to test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_2.sol diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_3_legacy.sol b/test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_3_legacy.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_inheritance_init_order_3_legacy.sol rename to test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_3_legacy.sol diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_3_viaIR.sol b/test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_3_viaIR.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_inheritance_init_order_3_viaIR.sol rename to test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_3_viaIR.sol diff --git a/test/libsolidity/semanticTests/constructor_with_params.sol b/test/libsolidity/semanticTests/inheritance/constructor_with_params.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_with_params.sol rename to test/libsolidity/semanticTests/inheritance/constructor_with_params.sol diff --git a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol b/test/libsolidity/semanticTests/inheritance/constructor_with_params_diamond_inheritance.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol rename to test/libsolidity/semanticTests/inheritance/constructor_with_params_diamond_inheritance.sol diff --git a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol b/test/libsolidity/semanticTests/inheritance/constructor_with_params_inheritance.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_with_params_inheritance.sol rename to test/libsolidity/semanticTests/inheritance/constructor_with_params_inheritance.sol diff --git a/test/libsolidity/semanticTests/constructor_with_params_inheritance_2.sol b/test/libsolidity/semanticTests/inheritance/constructor_with_params_inheritance_2.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_with_params_inheritance_2.sol rename to test/libsolidity/semanticTests/inheritance/constructor_with_params_inheritance_2.sol diff --git a/test/libsolidity/semanticTests/interface_inheritance_conversions.sol b/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol similarity index 76% rename from test/libsolidity/semanticTests/interface_inheritance_conversions.sol rename to test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol index 62e1e4fba6dc..2448b3e03bc2 100644 --- a/test/libsolidity/semanticTests/interface_inheritance_conversions.sol +++ b/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol @@ -10,26 +10,21 @@ interface SubB is Parent { function subBFun() external returns (uint256); } -contract Impl is SubA, SubB { +contract C is SubA, SubB { function parentFun() override external returns (uint256) { return 1; } function subAFun() override external returns (uint256) { return 2; } function subBFun() override external returns (uint256) { return 3; } -} -contract C { function convertParent() public returns (uint256) { - Parent p = new Impl(); - return p.parentFun(); + return this.parentFun(); } function convertSubA() public returns (uint256, uint256) { - SubA sa = new Impl(); - return (sa.parentFun(), sa.subAFun()); + return (this.parentFun(), this.subAFun()); } function convertSubB() public returns (uint256, uint256) { - SubB sb = new Impl(); - return (sb.parentFun(), sb.subBFun()); + return (this.parentFun(), this.subBFun()); } } // ---- diff --git a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol index b9697c5ae1d7..cbedca48c8c4 100644 --- a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol +++ b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol @@ -13,14 +13,16 @@ contract D is M.C { contract A { function g(int p) public returns (int) { - D d = new D(p); + D d = new D{salt: bytes32(uint256(p))}(p); return d.getX(); } } +// ==== +// EVMVersion: >=constantinople // ---- // g(int256): -1 -> -1 -// gas legacy: 77876 +// gas legacy: 77955 // gas legacy code: 24200 // g(int256): 10 -> 10 -// gas legacy: 77504 +// gas legacy: 77583 // gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/state_variables_init_order.sol b/test/libsolidity/semanticTests/inheritance/state_variables_init_order.sol similarity index 100% rename from test/libsolidity/semanticTests/state_variables_init_order.sol rename to test/libsolidity/semanticTests/inheritance/state_variables_init_order.sol diff --git a/test/libsolidity/semanticTests/state_variables_init_order_2.sol b/test/libsolidity/semanticTests/inheritance/state_variables_init_order_2.sol similarity index 100% rename from test/libsolidity/semanticTests/state_variables_init_order_2.sol rename to test/libsolidity/semanticTests/inheritance/state_variables_init_order_2.sol diff --git a/test/libsolidity/semanticTests/state_variables_init_order_3.sol b/test/libsolidity/semanticTests/inheritance/state_variables_init_order_3.sol similarity index 100% rename from test/libsolidity/semanticTests/state_variables_init_order_3.sol rename to test/libsolidity/semanticTests/inheritance/state_variables_init_order_3.sol diff --git a/test/libsolidity/semanticTests/inlineAssembly/blobhash_index_exceeding_blob_count.sol b/test/libsolidity/semanticTests/inlineAssembly/blobhash_index_exceeding_blob_count.sol index 7063978c5c1b..50a2ea7081d4 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/blobhash_index_exceeding_blob_count.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/blobhash_index_exceeding_blob_count.sol @@ -1,7 +1,7 @@ contract C { function f() public view returns (bytes32 ret) { assembly { - // EIP-4844 specifies that if `index < len(tx.blob_versioned_hashes)`, `blobhash(index)` should return 0. + // EIP-4844 specifies that if `index >= len(tx.blob_versioned_hashes)`, `blobhash(index)` should return 0. // Thus, as we injected only two blob hashes in the transaction context in EVMHost, // the return value of the function below MUST be zero. ret := blobhash(2) diff --git a/test/libsolidity/semanticTests/inlineAssembly/external_function_pointer_address.sol b/test/libsolidity/semanticTests/inlineAssembly/external_function_pointer_address.sol index ae891df5dc4f..dd60679ae95b 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/external_function_pointer_address.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/external_function_pointer_address.sol @@ -2,16 +2,16 @@ contract C { function testFunction() external {} function testYul() public returns (address adr) { - function() external fp = this.testFunction; + function() external fp = C(address(0x1234)).testFunction; assembly { adr := fp.address } } function testSol() public returns (address) { - return this.testFunction.address; + return C(address(0x1234)).testFunction.address; } } // ---- -// testYul() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e -// testSol() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e +// testYul() -> 0x1234 +// testSol() -> 0x1234 diff --git a/test/libsolidity/semanticTests/asmForLoop/for_loop_break.sol b/test/libsolidity/semanticTests/inlineAssembly/for_loop_break.sol similarity index 100% rename from test/libsolidity/semanticTests/asmForLoop/for_loop_break.sol rename to test/libsolidity/semanticTests/inlineAssembly/for_loop_break.sol diff --git a/test/libsolidity/semanticTests/asmForLoop/for_loop_continue.sol b/test/libsolidity/semanticTests/inlineAssembly/for_loop_continue.sol similarity index 100% rename from test/libsolidity/semanticTests/asmForLoop/for_loop_continue.sol rename to test/libsolidity/semanticTests/inlineAssembly/for_loop_continue.sol diff --git a/test/libsolidity/semanticTests/asmForLoop/for_loop_nested.sol b/test/libsolidity/semanticTests/inlineAssembly/for_loop_nested.sol similarity index 100% rename from test/libsolidity/semanticTests/asmForLoop/for_loop_nested.sol rename to test/libsolidity/semanticTests/inlineAssembly/for_loop_nested.sol diff --git a/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_in_modifiers.sol b/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_in_modifiers.sol index e050d2b52220..bed3add8a6fe 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_in_modifiers.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_in_modifiers.sol @@ -27,6 +27,8 @@ contract C { return true; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f() -> true // g() -> FAILURE diff --git a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol index e43fc475740a..d3714e7dfca5 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol @@ -27,7 +27,7 @@ contract C { function testDelegateCall() external returns (bool) { this.set(5); - D d = new D(); + D d = new D{salt: hex"00"}(); // Caller contract is the owner of the transient storage (bool success, ) = address(d).delegatecall(abi.encodeCall(d.addOne, ())); require(success); @@ -37,7 +37,7 @@ contract C { function testCall() external returns (bool) { this.set(5); - D d = new D(); + D d = new D{salt: hex"01"}(); // Callee/Target contract is the owner of the transient storage (bool success, ) = address(d).call(abi.encodeCall(d.addOne, ())); require(success); @@ -47,7 +47,7 @@ contract C { function tloadAllowedStaticCall() external returns (bool) { this.set(5); - D d = new D(); + D d = new D{salt: hex"02"}(); (bool success, bytes memory result) = address(d).staticcall(abi.encodeCall(d.get, ())); require(success); require(abi.decode(result, (uint)) == 0); @@ -55,7 +55,7 @@ contract C { } function tstoreNotAllowedStaticCall() external returns (bool) { - D d = new D(); + D d = new D{salt: hex"03"}(); (bool success, ) = address(d).staticcall(abi.encodeCall(d.addOne, ())); require(!success); return true; @@ -68,9 +68,9 @@ contract C { // testCall() -> true // tloadAllowedStaticCall() -> true // tstoreNotAllowedStaticCall() -> true -// gas irOptimized: 98419720 +// gas irOptimized: 98419721 // gas irOptimized code: 19000 -// gas legacy: 98409086 +// gas legacy: 98409087 // gas legacy code: 30000 // gas legacyOptimized: 98420962 // gas legacyOptimized code: 17800 diff --git a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol index c2066ef8be1e..26bb09edca7a 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol @@ -38,6 +38,7 @@ contract D { } // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // constructor() -> // gas irOptimized: 127596 diff --git a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol index 1240a8251427..92d358294a1d 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -1,30 +1,9 @@ -contract Other { +contract C { constructor() payable { - } - function getAddress() public returns (address) { - return address(this); - } -} -contract ClientReceipt { - Other other; - constructor() payable { - other = new Other{value:500}(); - } - function getAddress() public returns (address) { - return other.getAddress(); + payable(address(0x1234)).transfer(500); } } // ---- // constructor(), 2000 wei -> -// gas irOptimized: 114353 -// gas irOptimized code: 58800 -// gas legacy: 118617 -// gas legacy code: 111400 -// gas legacyOptimized: 114067 -// gas legacyOptimized code: 59800 // balance -> 1500 -// gas irOptimized: 191881 -// gas legacy: 235167 -// gas legacyOptimized: 180756 -// getAddress() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a -// balance: 0x137aa4dfc0911524504fcd4d98501f179bc13b4a -> 500 +// balance: 0x0000000000000000000000000000000000001234 -> 500 diff --git a/test/libsolidity/semanticTests/empty_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/empty_contract.sol similarity index 100% rename from test/libsolidity/semanticTests/empty_contract.sol rename to test/libsolidity/semanticTests/isoltestTesting/empty_contract.sol diff --git a/test/libsolidity/semanticTests/isoltestFormatting.sol b/test/libsolidity/semanticTests/isoltestTesting/isoltestFormatting.sol similarity index 100% rename from test/libsolidity/semanticTests/isoltestFormatting.sol rename to test/libsolidity/semanticTests/isoltestTesting/isoltestFormatting.sol diff --git a/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol b/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol new file mode 100644 index 000000000000..ef6abb9a9140 --- /dev/null +++ b/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol @@ -0,0 +1,34 @@ +contract C { + function ecRecover(uint[4] memory input) public returns (bytes memory) { + (bool success, bytes memory encodedOutput) = address(1).call(abi.encode(input)); + require(success); + return encodedOutput; + } + + function ecAdd(uint[4] memory input) public returns (bytes memory) { + (bool success, bytes memory encodedOutput) = address(6).call(abi.encode(input)); + require(success); + return encodedOutput; + } + + function ecMul(uint[3] memory input) public returns (bytes memory) { + (bool success, bytes memory encodedOutput) = address(7).call(abi.encode(input)); + require(success); + return encodedOutput; + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// ecRecover(uint256[4]): 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c, 0x000000000000000000000000000000000000000000000000000000000000001c, 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f, 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549 -> 0x20, 0x20, 966588469268559010541288244128342317224451555083 +// ecRecover(uint256[4]): 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c, 0x000000000000000000000000000000000000000000000000000000000000001c, 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f, 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549, 0x01, 0x02, 0x03 -> 0x20, 0x20, 966588469268559010541288244128342317224451555083 + +// ecAdd(uint256[4]): 0x01, 0x02, 0x01, 0x02 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecAdd(uint256[4]): 0x01, 0x02, 0x01, 0x02, 0x01 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecAdd(uint256[4]): 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecAdd(uint256[4]): 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 + +// ecMul(uint256[3]): 0x01, 0x02, 0x02 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecMul(uint256[3]): 0x01, 0x02, 0x02, 0x01 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecMul(uint256[3]): 0x01, 0x02, 0x02, 0x01, 0x02 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecMul(uint256[3]): 0x01, 0x02, 0x02, 0x01, 0x02, 0x03 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 diff --git a/test/libsolidity/semanticTests/libraries/library_address.sol b/test/libsolidity/semanticTests/libraries/library_address.sol index 6ca064445012..af3a45a97304 100644 --- a/test/libsolidity/semanticTests/libraries/library_address.sol +++ b/test/libsolidity/semanticTests/libraries/library_address.sol @@ -36,6 +36,7 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy,>=EOFv1 // ---- // library: L // addr() -> false diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol index ec41099eecbb..364e589e55c1 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol @@ -39,27 +39,29 @@ function loadAdder() pure returns (IAdder adder) { contract C { function testMul(Int32 x, Int32 y) public returns (Int32) { - storeAdder(new Adder()); + storeAdder(new Adder{salt: hex"00"}()); return x + y; } function testInc(Int32 x) public returns (Int32) { - storeAdder(new Adder()); + storeAdder(new Adder{salt: hex"01"}()); return -x; } } +// ==== +// EVMVersion: >=constantinople // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 56978 +// gas legacy: 57117 // gas legacy code: 127000 -// gas legacyOptimized: 55161 +// gas legacyOptimized: 55246 // gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 56238 +// gas legacy: 56378 // gas legacy code: 127000 -// gas legacyOptimized: 54851 +// gas legacyOptimized: 54943 // gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol index 7e70eb091bf6..54048113c323 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol @@ -45,27 +45,29 @@ function loadAdder() pure returns (IAdderPure adder) { contract C { function testMul(Int32 x, Int32 y) public returns (Int32) { - storeAdder(new Adder()); + storeAdder(new Adder{salt: hex"00"}()); return x + y; } function testInc(Int32 x) public returns (Int32) { - storeAdder(new Adder()); + storeAdder(new Adder{salt: hex"01"}()); return -x; } } +// ==== +// EVMVersion: >=constantinople // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 56978 +// gas legacy: 57117 // gas legacy code: 127000 -// gas legacyOptimized: 55161 +// gas legacyOptimized: 55246 // gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 56238 +// gas legacy: 56378 // gas legacy code: 127000 -// gas legacyOptimized: 54851 +// gas legacyOptimized: 54943 // gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/unused_store_storage_removal_bug.sol b/test/libsolidity/semanticTests/optimizer/unused_store_storage_removal_bug.sol similarity index 100% rename from test/libsolidity/semanticTests/unused_store_storage_removal_bug.sol rename to test/libsolidity/semanticTests/optimizer/unused_store_storage_removal_bug.sol diff --git a/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol b/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol index 110b1e50c724..d9a6549252f1 100644 --- a/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol +++ b/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol @@ -8,5 +8,6 @@ contract C { // ==== // EVMVersion: >=byzantium // revertStrings: debug +// bytecodeFormat: legacy // ---- // g() -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/reverts/eof/revert_return_area.sol b/test/libsolidity/semanticTests/reverts/eof/revert_return_area.sol new file mode 100644 index 000000000000..8cec1ca1d66c --- /dev/null +++ b/test/libsolidity/semanticTests/reverts/eof/revert_return_area.sol @@ -0,0 +1,19 @@ +contract C { + fallback() external { + revert("abc"); + } + + function f() public returns (uint s, uint r) { + address x = address(this); + assembly { + mstore(0, 7) + s := extcall(x, 0, 0, 0) + returndatacopy(0, 0, 32) + r := mload(0) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// f() -> 0x01, 0x08c379a000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/reverts/revert_return_area.sol b/test/libsolidity/semanticTests/reverts/revert_return_area.sol index 8ab4ca22722c..5f276f91c948 100644 --- a/test/libsolidity/semanticTests/reverts/revert_return_area.sol +++ b/test/libsolidity/semanticTests/reverts/revert_return_area.sol @@ -14,5 +14,6 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // f() -> 0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/saltedCreate/eof/salted_create_with_value.sol b/test/libsolidity/semanticTests/saltedCreate/eof/salted_create_with_value.sol new file mode 100644 index 000000000000..e6c6f6eb0772 --- /dev/null +++ b/test/libsolidity/semanticTests/saltedCreate/eof/salted_create_with_value.sol @@ -0,0 +1,23 @@ +contract B +{ + uint x; + function getBalance() public view returns (uint) { + return address(this).balance * 1000 + x; + } + constructor(uint _x) payable { + x = _x; + } +} + +contract A { + function f() public payable returns (uint, uint, uint) { + B x = new B{salt: "abc1", value: 3}(7); + B y = new B{value: 3, salt: "abc2"}(8); + B z = new B{salt: "abc3", value: 3}(9); + return (x.getBalance(), y.getBalance(), z.getBalance()); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// f(), 10 ether -> 3007, 3008, 3009 diff --git a/test/libsolidity/semanticTests/salted_create/prediction_example.sol b/test/libsolidity/semanticTests/saltedCreate/prediction_example.sol similarity index 96% rename from test/libsolidity/semanticTests/salted_create/prediction_example.sol rename to test/libsolidity/semanticTests/saltedCreate/prediction_example.sol index 7d0e3c8b0dbc..f1f62db03230 100644 --- a/test/libsolidity/semanticTests/salted_create/prediction_example.sol +++ b/test/libsolidity/semanticTests/saltedCreate/prediction_example.sol @@ -24,6 +24,7 @@ contract C { // ==== // EVMVersion: >=constantinople // compileViaYul: also +// bytecodeFormat: legacy // ---- // createDSalted(bytes32,uint256): 42, 64 -> // gas legacy: 78573 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create.sol b/test/libsolidity/semanticTests/saltedCreate/salted_create.sol similarity index 100% rename from test/libsolidity/semanticTests/salted_create/salted_create.sol rename to test/libsolidity/semanticTests/saltedCreate/salted_create.sol diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol similarity index 96% rename from test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol rename to test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol index 25d1935770d1..c810000e5b3c 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol @@ -19,6 +19,7 @@ contract A { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // f(), 10 ether -> 3007, 3008, 3009 // gas irOptimized: 187022 diff --git a/test/libsolidity/semanticTests/c99_scoping_activation.sol b/test/libsolidity/semanticTests/scoping/c99_scoping_activation.sol similarity index 100% rename from test/libsolidity/semanticTests/c99_scoping_activation.sol rename to test/libsolidity/semanticTests/scoping/c99_scoping_activation.sol diff --git a/test/libsolidity/semanticTests/shanghai/evmone_support.sol b/test/libsolidity/semanticTests/shanghai/evmone_support.sol index 359dc516ffcd..4f3c0ee1ba6a 100644 --- a/test/libsolidity/semanticTests/shanghai/evmone_support.sol +++ b/test/libsolidity/semanticTests/shanghai/evmone_support.sol @@ -26,6 +26,7 @@ contract Test { // ==== // compileViaYul: also // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // bytecode() -> 0x20, 4, 0x60205ff300000000000000000000000000000000000000000000000000000000 // isPush0Supported() -> true diff --git a/test/libsolidity/semanticTests/state/gasleft.sol b/test/libsolidity/semanticTests/state/gasleft.sol index 6ce623ce81ea..2d4a37b48d8b 100644 --- a/test/libsolidity/semanticTests/state/gasleft.sol +++ b/test/libsolidity/semanticTests/state/gasleft.sol @@ -3,6 +3,8 @@ contract C { return gasleft() > 0; } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> true // f() -> true diff --git a/test/libsolidity/semanticTests/empty_for_loop.sol b/test/libsolidity/semanticTests/statements/empty_for_loop.sol similarity index 100% rename from test/libsolidity/semanticTests/empty_for_loop.sol rename to test/libsolidity/semanticTests/statements/empty_for_loop.sol diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/base_slot_max_value.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/base_slot_max_value.sol new file mode 100644 index 000000000000..e465437626b3 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/base_slot_max_value.sol @@ -0,0 +1,7 @@ +contract C layout at 2**256 - 1 { + function f(uint a) public pure returns (uint) { + return a * 2; + } +} +// ---- +// f(uint256): 4 -> 8 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/constructor.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/constructor.sol new file mode 100644 index 000000000000..c30f9dab98a7 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/constructor.sol @@ -0,0 +1,29 @@ +contract A { + uint public x; +} + +contract B is A { + int8 public y; +} + +contract C is B layout at 7 { + uint32 public z; + + constructor(uint _x, int8 _y, uint32 _z) { + x = _x + 1; + y = _y + 2; + z = _z + 3; + } + +} +// ---- +// constructor(): 1, 2, 3 +// gas irOptimized: 104178 +// gas irOptimized code: 30000 +// gas legacy: 114749 +// gas legacy code: 71400 +// gas legacyOptimized: 106296 +// gas legacyOptimized code: 31400 +// x() -> 2 +// y() -> 4 +// z() -> 6 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/delete.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/delete.sol new file mode 100644 index 000000000000..a6cc84cce511 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/delete.sol @@ -0,0 +1,30 @@ +contract C layout at 42 { + uint[] public array; + + function fillArray() public returns (uint) { + array.push(1); + array.push(2); + array.push(3); + return array.length; + } + function deleteLast() public { + delete array[array.length - 1]; + } + function deleteArray() public { + delete array; + } + function arrayLength() public returns (uint) { + return array.length; + } +} +// ---- +// fillArray() -> 3 +// gas irOptimized: 111121 +// gas legacy: 110730 +// gas legacyOptimized: 110307 +// arrayLength() -> 3 +// array(uint256): 2 -> 3 +// deleteLast() -> +// array(uint256): 2 -> 0 +// deleteArray() -> +// arrayLength() -> 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/delete_transient_storage.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/delete_transient_storage.sol new file mode 100644 index 000000000000..b651e0e888b9 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/delete_transient_storage.sol @@ -0,0 +1,20 @@ +contract C layout at 42 { + uint transient x; + address transient a; + + function f() public { + g(); + delete x; + delete a; + assert(x == 0); + assert(a == address(0)); + } + function g() public { + x = 99; + a = address(0x1234); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> \ No newline at end of file diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/dynamic_array_storage_end.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/dynamic_array_storage_end.sol new file mode 100644 index 000000000000..54eabe844702 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/dynamic_array_storage_end.sol @@ -0,0 +1,29 @@ +contract C layout at 2**256 - 2 { + uint[] array; + + function init() public { + for (uint i = 0; i < 1000; ++i) + array.push(i + 1); + } + function validate() public { + for (uint i = 0; i < 1000; ++i) + require(array[i] == i + 1); + } + function clear() public { + for (uint i = 0; i < 1000; ++i) + array.pop(); + } +} +// ---- +// init() -> +// gas irOptimized: 22738151 +// gas legacy: 22699167 +// gas legacyOptimized: 22541160 +// validate() -> +// gas irOptimized: 2444232 +// gas legacy: 2560245 +// gas legacyOptimized: 2442238 +// clear() -> +// gas irOptimized: 4449608 +// gas legacy: 4300019 +// gas legacyOptimized: 4302413 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/function_from_base_contract.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/function_from_base_contract.sol new file mode 100644 index 000000000000..004997c221bc --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/function_from_base_contract.sol @@ -0,0 +1,30 @@ +contract A { + uint public x; + function f() public returns (uint) { + x = x + 1; + return x; + } +} + +contract B is A { + uint public y; + function g() public virtual returns (uint) { + y = y + 2; + return y; + } +} + +contract C is B layout at 42 { + uint public z; + function test() public returns (uint){ + z = super.g() + A.f(); + return z; + } +} +// ---- +// f() -> 1 +// g() -> 2 +// test() -> 6 +// x() -> 2 +// y() -> 4 +// z() -> 6 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/getters.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/getters.sol new file mode 100644 index 000000000000..62a75e7d5342 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/getters.sol @@ -0,0 +1,9 @@ +contract C layout at 7 { + uint public x = 1; + int8 public y = 2; + uint32 public z = 3; +} +// ---- +// x() -> 1 +// y() -> 2 +// z() -> 3 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_abstract_contract.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_abstract_contract.sol new file mode 100644 index 000000000000..fdf68994be7e --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_abstract_contract.sol @@ -0,0 +1,17 @@ +abstract contract A { + uint public x; +} + +contract C is A layout at 42 { + uint public y; + function f() public returns (uint) { + x = 12; + x = x - 4; + y = x + 2; + return y; + } +} +// ---- +// f() -> 10 +// x() -> 8 +// y() -> 10 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_interface.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_interface.sol new file mode 100644 index 000000000000..8874f28f2fd4 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_interface.sol @@ -0,0 +1,15 @@ +interface I { + function f(uint x) external returns (uint); +} + +contract C is I layout at 42 { + uint public y; + function f(uint x) public returns (uint) { + x = x - 4; + y = x + 2; + return y; + } +} +// ---- +// f(uint256): 8 -> 6 +// y() -> 6 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_same_base_state_var_slots.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_same_base_state_var_slots.sol new file mode 100644 index 000000000000..554c3fcd7e2b --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_same_base_state_var_slots.sol @@ -0,0 +1,47 @@ +contract A { + uint public x; + function xSlot() public view returns (uint xs) { + assembly { + xs := x.slot + } + } +} + +contract B is A layout at 5 { + uint public y; + function xAndYSlots() public view returns (uint xs, uint ys) { + assembly { + xs := x.slot + ys := y.slot + } + } +} + +contract C is A layout at 9 { + uint public z; + function xAndZSlots() public view returns (uint xs, uint zs) { + assembly { + xs := x.slot + zs := z.slot + } + } +} + +contract Test { + A a = new A(); + B b = new B(); + C c = new C(); + function contractASlots() public view returns (uint) { + return a.xSlot(); + } + function contractBSlots() public view returns (uint, uint) { + return b.xAndYSlots(); + } + function contractCSlots() public view returns (uint, uint) { + return c.xAndZSlots(); + } +} +// ---- +// contractASlots() -> 0 +// contractBSlots() -> 5, 6 +// contractCSlots() -> 9, 10 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_simple.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_simple.sol new file mode 100644 index 000000000000..a4eeee5f28db --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_simple.sol @@ -0,0 +1,16 @@ +contract A { + uint public x = 10; +} + +contract C is A layout at 42 { + uint public y; + function f() public returns (uint) { + x = x - 4; + y = x + 2; + return y; + } +} +// ---- +// f() -> 8 +// x() -> 6 +// y() -> 8 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_state_variable_slot_offset.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_state_variable_slot_offset.sol new file mode 100644 index 000000000000..73304d622965 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_state_variable_slot_offset.sol @@ -0,0 +1,19 @@ +contract A { + uint x; + uint128 y; +} + +contract C is A layout at 7 { + uint32 w; + uint z; + + function xSlotOffset() public returns(uint s, uint o) { assembly { s := x.slot o := x.offset } } + function ySlotOffset() public returns(uint s, uint o) { assembly { s := y.slot o := y.offset } } + function wSlotOffset() public returns(uint s, uint o) { assembly { s := w.slot o := w.offset } } + function zSlotOffset() public returns(uint s, uint o) { assembly { s := z.slot o := z.offset } } +} +// ---- +// xSlotOffset() -> 7, 0 +// ySlotOffset() -> 8, 0 +// wSlotOffset() -> 8, 16 +// zSlotOffset() -> 9, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_load.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_load.sol new file mode 100644 index 000000000000..9f5a5491d202 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_load.sol @@ -0,0 +1,12 @@ +contract C layout at 42 { + uint public x; + function f() public returns (uint r) { + x = 16; + assembly { + r := sload(42) + } + } +} +// ---- +// f() -> 16 +// x() -> 16 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_store.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_store.sol new file mode 100644 index 000000000000..6ea695e6625d --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_store.sol @@ -0,0 +1,12 @@ +contract C layout at 42 { + uint public x; + function f() public returns (uint) { + assembly { + sstore(42, 16) + } + return x; + } +} +// ---- +// f() -> 16 +// x() -> 16 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/last_allowed_storage_slot.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/last_allowed_storage_slot.sol new file mode 100644 index 000000000000..89900c0f6d0b --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/last_allowed_storage_slot.sol @@ -0,0 +1,10 @@ +contract C layout at 2**256 - 2 { + uint public x; + function f(uint a) public returns (uint) { + x = a * 2; + return x; + } +} +// ---- +// f(uint256): 4 -> 8 +// x() -> 8 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/mapping_storage_end.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/mapping_storage_end.sol new file mode 100644 index 000000000000..9745850c0091 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/mapping_storage_end.sol @@ -0,0 +1,22 @@ +contract C layout at 2**256 - 2 { + mapping(uint => uint) m; + + function init() public { + for (uint i = 0; i < 1000; ++i) + m[i] = i + 1; + } + + function validate() public { + for (uint i = 0; i < 1000; ++i) + require(m[i] == i + 1); + } +} +// ---- +// init() -> +// gas irOptimized: 22266229 +// gas legacy: 22447245 +// gas legacyOptimized: 22310238 +// validate() -> +// gas irOptimized: 2279210 +// gas legacy: 2456223 +// gas legacyOptimized: 2327216 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol new file mode 100644 index 000000000000..1b24b4961dbf --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol @@ -0,0 +1,40 @@ +contract A { + uint public x; + function f(uint a) public { + x = a; + } +} + +contract B is A { + uint public y; + function g(uint a) public { + f(x + a); + y = x + 1; + } +} + +contract C is B { + uint public w; + function h(uint a) public { + g(a); + w = x + y; + } +} + +contract D is A, B, C layout at 42 { + uint public z; + function test() public returns (uint, uint, uint, uint) { + h(1); + z = w + 2; + return (x, y, w, z); + } +} +// ---- +// test() -> 1, 2, 3, 5 +// gas irOptimized: 110112 +// gas legacy: 111881 +// gas legacyOptimized: 110945 +// x() -> 1 +// y() -> 2 +// w() -> 3 +// z() -> 5 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance_state_var_slots.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance_state_var_slots.sol new file mode 100644 index 000000000000..dd75b1d25648 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance_state_var_slots.sol @@ -0,0 +1,24 @@ +contract A { + uint x; +} + +contract B is A { + uint32 y; +} + +contract C is B { + uint160 w; +} + +contract D is A, B, C layout at 2 { + uint z; + function xSlotOffset() public view returns (uint s, uint o) { assembly { s := x.slot o := x.offset } } + function ySlotOffset() public view returns (uint s, uint o) { assembly { s := y.slot o := y.offset } } + function wSlotOffset() public view returns (uint s, uint o) { assembly { s := w.slot o := w.offset } } + function zSlotOffset() public view returns (uint s, uint o) { assembly { s := z.slot o := z.offset } } +} +// ---- +// xSlotOffset() -> 2, 0 +// ySlotOffset() -> 3, 0 +// wSlotOffset() -> 3, 4 +// zSlotOffset() -> 4, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_arithmetic_expression.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_arithmetic_expression.sol new file mode 100644 index 000000000000..5dacc81ba6e1 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_arithmetic_expression.sol @@ -0,0 +1,20 @@ +contract C layout at 7 { + uint public x; + uint public y; + uint public z; + + function f(uint a) public returns (uint) { + x = x + a; + y = y + x; + z = y - 2; + + return z; + } +} +// ---- +// f(uint256): 2 -> 0 +// f(uint256): 3 -> 5 +// f(uint256): 5 -> 15 +// x() -> 10 +// y() -> 17 +// z() -> 15 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_constant_and_immutable.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_constant_and_immutable.sol new file mode 100644 index 000000000000..6489b1e6b2fb --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_constant_and_immutable.sol @@ -0,0 +1,16 @@ +contract C layout at 42 { + uint constant x = 10; + uint immutable y = 100; + + function f() public view returns (uint) { + require(x > 9); + return x + 1; + } + function g() public view returns (uint) { + require(y > 99); + return y * 2; + } +} +// ---- +// f() -> 11 +// g() -> 200 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol new file mode 100644 index 000000000000..1737c35bb87c --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol @@ -0,0 +1,50 @@ +contract A { + uint[] public arrayA; +} + +contract C is A layout at 42 { + uint[] public arrayC; + + function initA() public returns (uint, uint, uint) { + arrayA.push(1); + arrayA.push(2); + arrayA.push(3); + + return (arrayA[0], arrayA[1], arrayA[2]); + } + function initCFromAInReverse() public returns (uint, uint, uint) { + arrayC = new uint[](3); + arrayC[0] = arrayA[2]; + arrayC[1] = arrayA[1]; + arrayC[2] = arrayA[0]; + + return (arrayC[0], arrayC[1], arrayC[2]); + } + function clearA () public { + arrayA.pop(); + arrayA.pop(); + arrayA.pop(); + } + function arrayALength() public returns (uint) { + return arrayA.length; + } + function arrayCLength() public returns (uint) { + return arrayC.length; + } +} +// ---- +// initA() -> 1, 2, 3 +// gas irOptimized: 111986 +// gas legacy: 111679 +// gas legacyOptimized: 111150 +// arrayA(uint256): 0 -> 1 +// arrayALength() -> 3 +// arrayCLength() -> 0 +// initCFromAInReverse() -> 3, 2, 1 +// gas irOptimized: 121276 +// gas legacy: 121213 +// gas legacyOptimized: 120843 +// clearA() -> +// arrayC(uint256): 0 -> 3 +// arrayALength() -> 0 +// arrayCLength() -> 3 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_enum.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_enum.sol new file mode 100644 index 000000000000..66328261617d --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_enum.sol @@ -0,0 +1,18 @@ +enum Color {Red, Blue, Green } +contract C layout at 42 { + Color c; + function cSlotOffset() public returns(uint s, uint o) { + assembly { s := c.slot o := c.offset } + } + function setBlue() public { + c = Color.Blue; + } + function checkBlue() public view returns (bool) { + return c == Color.Blue; + } +} +// ---- +// cSlotOffset() -> 42, 0 +// checkBlue() -> false +// setBlue() -> +// checkBlue() -> true diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol new file mode 100644 index 000000000000..e33df29ea604 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol @@ -0,0 +1,33 @@ +contract A { + mapping(uint => bool) locked; +} +contract C layout at 42 is A { + mapping(uint => string) rooms; + + function setup() public { + locked[0] = true; + locked[1] = false; + locked[2] = true; + locked[3] = false; + + rooms[0] = "Empty"; + rooms[1] = "Monster"; + rooms[2] = "Treasure"; + rooms[3] = "Empty"; + } + function open(uint x) public view returns (string memory) { + if (locked[x]) + return "Locked"; + + require(!locked[x]); + return rooms[x]; + } +} +// ---- +// setup() -> +// gas irOptimized: 159082 +// gas legacy: 161738 +// gas legacyOptimized: 160222 +// open(uint256): 3 -> 0x20, 5, "Empty" +// open(uint256): 2 -> 0x20, 6, "Locked" +// open(uint256): 1 -> 0x20, 7, "Monster" diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_reference_types_slot_offset.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_reference_types_slot_offset.sol new file mode 100644 index 000000000000..30cbed7f3ca2 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_reference_types_slot_offset.sol @@ -0,0 +1,33 @@ +struct S { + uint x; + address a; + bool b; +} + +contract A { + S public s1; + uint transient t1; +} + +contract C is A layout at 42 { + uint transient t2; + S[][5] dArray; + uint[10][2] sArray; + bytes bArray; + string str; + + + function s1SlotOffset() public returns (uint s, uint o) { assembly { s:= s1.slot o:= s1.offset } } + function dArraySlotOffset() public returns (uint s, uint o) { assembly { s:= dArray.slot o:= dArray.offset } } + function sArraySlotOffset() public returns (uint s, uint o) { assembly { s:= sArray.slot o:= sArray.offset } } + function bArraySlotOffset() public returns (uint s, uint o) { assembly { s:= bArray.slot o:= bArray.offset } } + function strSlotOffset() public returns (uint s, uint o) { assembly { s:= str.slot o:= str.offset } } +} +// ==== +// EVMVersion: >=cancun +// ---- +// s1SlotOffset() -> 42, 0 +// dArraySlotOffset() -> 44, 0 +// sArraySlotOffset() -> 49, 0 +// bArraySlotOffset() -> 69, 0 +// strSlotOffset() -> 70, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_slot_offset.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_slot_offset.sol new file mode 100644 index 000000000000..1ce5207eb181 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_slot_offset.sol @@ -0,0 +1,13 @@ +contract C layout at 7 { + int8 public x; + int32 public y; + uint256 public z; + + function xSlotOffset() public returns(uint s, uint o) { assembly { s := x.slot o := x.offset } } + function ySlotOffset() public returns(uint s, uint o) { assembly { s := y.slot o := y.offset } } + function zSlotOffset() public returns(uint s, uint o) { assembly { s := z.slot o := z.offset } } +} +// ---- +// xSlotOffset() -> 7, 0 +// ySlotOffset() -> 7, 1 +// zSlotOffset() -> 8, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_struct.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_struct.sol new file mode 100644 index 000000000000..5b2b6d5582df --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_struct.sol @@ -0,0 +1,39 @@ +struct S { + uint x; + address a; + bool b; +} + +contract A { + S public s1; + uint transient t1; +} + +contract C is A layout at 42 { + uint y; + uint8 z; + uint transient t2; + S public s2; + + function initS1() public returns (uint, address, bool) { + s1.x = 7; + s1.a = address(0xABC); + s1.b = true; + + return (s1.x, s1.a, s1.b); + } + function initS2() public returns (uint, address, bool) { + s2.x = 8; + s2.a = address(0xDEF); + s2.b = false; + + return (s2.x, s2.a, s2.b); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// initS1() -> 7, 0x0abc, 1 +// initS2() -> 8, 0x0def, 0 +// s1() -> 7, 0x0abc, 1 +// s2() -> 8, 0x0def, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variables_transient.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variables_transient.sol new file mode 100644 index 000000000000..0c1e0a78a554 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variables_transient.sol @@ -0,0 +1,23 @@ +contract C layout at 42 { + int x; + bool transient lock; + + function test() public returns(int) { + x = -1; + lock = true; + f(); + return x; + } + function f() private { + lock = false; + setX(); + } + function setX() private { + require(!lock); + x = 2; + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// test() -> 2 \ No newline at end of file diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_array.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_array.sol new file mode 100644 index 000000000000..db14ef55874c --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_array.sol @@ -0,0 +1,21 @@ +contract C layout at 42 { + uint[] public array; + function initUsingReference() public { + uint[] storage ptr = array; + for(uint i = 0; i < 10; ++i) + ptr.push(i + 1); + + validate(array); + } + function validate(uint[] memory ptr) public pure { + for(uint i = 0; i < 10; ++i) + require(ptr[i] == i + 1); + } +} +// ---- +// initUsingReference() -> +// gas irOptimized: 273556 +// gas legacy: 274795 +// gas legacyOptimized: 271954 +// array(uint256): 0 -> 1 +// array(uint256): 9 -> 10 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_inheritance.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_inheritance.sol new file mode 100644 index 000000000000..1a4ee2e6f9d7 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_inheritance.sol @@ -0,0 +1,25 @@ +pragma abicoder v2; +contract A { + struct S { + uint x; + bool b; + } + S public s; +} + +contract C is A layout at 42 { + function InitUsingReference() public { + S storage ptr = s; + ptr.x = 2; + ptr.b = true; + + validate(s); + } + function validate(S memory ptr) public pure { + require(ptr.x == 2); + require(ptr.b); + } +} +// ---- +// InitUsingReference() -> +// s() -> 2, true diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_library_function.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_library_function.sol new file mode 100644 index 000000000000..2d17de248c34 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_library_function.sol @@ -0,0 +1,31 @@ +pragma abicoder v2; + +struct S { + uint x; + bool b; +} + +library L { + function validate(S memory ptr) public { + require(ptr.x == 2); + require(ptr.b); + } +} + +contract A { + S public s; +} + +contract C is A layout at 42 { + function initUsingReference() public { + S storage ptr = s; + ptr.x = 2; + ptr.b = true; + + L.validate(s); + } +} +// ---- +// library: L +// initUsingReference() -> +// s() -> 2, true diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/transient_state_variable_slot_offset.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/transient_state_variable_slot_offset.sol new file mode 100644 index 000000000000..c1d8f911d7c3 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/transient_state_variable_slot_offset.sol @@ -0,0 +1,18 @@ +contract C layout at 7 { + int transient x; + int y; + uint transient w; + uint256 z; + + function xSlotOffset() public returns(uint s, uint o) { assembly { s := x.slot o := x.offset } } + function ySlotOffset() public returns(uint s, uint o) { assembly { s := y.slot o := y.offset } } + function wSlotOffset() public returns(uint s, uint o) { assembly { s := w.slot o := w.offset } } + function zSlotOffset() public returns(uint s, uint o) { assembly { s := z.slot o := z.offset } } +} +// ==== +// EVMVersion: >=cancun +// ---- +// xSlotOffset() -> 0, 0 +// ySlotOffset() -> 7, 0 +// wSlotOffset() -> 1, 0 +// zSlotOffset() -> 8, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup.sol new file mode 100644 index 000000000000..33ffc59939e9 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup.sol @@ -0,0 +1,15 @@ +contract C layout at 42 { + uint8 x; + int8 y; + bytes2 b; + // Note the return types are larger than the state variable ones + function f(uint _x, int _y, bytes3 _b) public returns (uint16, int32, bytes32) { + x = uint8(_x); + y = int8(_y); + b = bytes2(_b); + require(b == "ab"); + return (x, y, b); + } +} +// ---- +// f(uint256,int256,bytes3): 0x0100, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f, "abc" -> 0x00, 0x7f, "ab" diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup_sstore.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup_sstore.sol new file mode 100644 index 000000000000..bda660d056a4 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup_sstore.sol @@ -0,0 +1,20 @@ +contract C layout at 42 { + uint8 x; + int8 y; + bytes2 b; + // Note the return types are larger than the state variable ones + function f() public returns (uint16, int32, bytes16) { + uint32 z = 0; + z = z | 0x10; + z = z | 0x7f00; + z = z | 0x61620000; + + assembly { + sstore(x.slot, z) + } + require(b == "ab"); + return (x, y, b); + } +} +// ---- +// f() -> 0x10, 127, "ab" diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/virtual_functions.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/virtual_functions.sol new file mode 100644 index 000000000000..42c917d18279 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/virtual_functions.sol @@ -0,0 +1,34 @@ +abstract contract A { + uint public x; + function f() public virtual returns (uint); +} + +contract B is A { + uint public y; + function f() public override returns (uint) { + x = 1; + return x; + } + function g() public virtual returns (uint) { + return y; + } +} + +contract C is B layout at 42 { + uint public z; + function g() public override returns (uint) { + y = x + 2; + return y; + } + function h() public returns (uint) { + z = g() + 3; + return z; + } +} +// ---- +// f() -> 1 +// g() -> 3 +// h() -> 6 +// x() -> 1 +// y() -> 3 +// z() -> 6 diff --git a/test/libsolidity/semanticTests/tryCatch/assert.sol b/test/libsolidity/semanticTests/tryCatch/assert.sol index 8b6a7b99692e..335ef26bfba6 100644 --- a/test/libsolidity/semanticTests/tryCatch/assert.sol +++ b/test/libsolidity/semanticTests/tryCatch/assert.sol @@ -3,14 +3,15 @@ contract C { assert(x); } function f(bool x) public returns (uint) { - // Set the gas to make this work on pre-byzantium VMs - try this.g{gas: 8000}(x) { + try this.g(x) { return 1; } catch { return 2; } } } +// ==== +// EVMVersion: >=byzantium // ---- // f(bool): true -> 1 // f(bool): false -> 2 diff --git a/test/libsolidity/semanticTests/tryCatch/assert_pre_byzantium.sol b/test/libsolidity/semanticTests/tryCatch/assert_pre_byzantium.sol new file mode 100644 index 000000000000..a683f531fc0e --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/assert_pre_byzantium.sol @@ -0,0 +1,18 @@ +contract C { + function g(bool x) public pure { + assert(x); + } + function f(bool x) public returns (uint) { + // Set the gas to make this work on pre-byzantium VMs + try this.g{gas: 8000}(x) { + return 1; + } catch { + return 2; + } + } +} +// ==== +// EVMVersion: 1 +// f(bool): false -> 2 diff --git a/test/libsolidity/semanticTests/tryCatch/create.sol b/test/libsolidity/semanticTests/tryCatch/create.sol index 43d0f22f6506..4ad40d531872 100644 --- a/test/libsolidity/semanticTests/tryCatch/create.sol +++ b/test/libsolidity/semanticTests/tryCatch/create.sol @@ -6,19 +6,19 @@ contract Succeeds { } contract C { - function f() public returns (Reverts x, uint, string memory txt) { + function f() public returns (bool created, string memory txt) { uint i = 3; try new Reverts(i) returns (Reverts r) { - x = r; + created = (address(r) != address(0)); txt = "success"; } catch Error(string memory s) { txt = s; } } - function g() public returns (Succeeds x, uint, string memory txt) { + function g() public returns (bool created, string memory txt) { uint i = 8; try new Succeeds(i) returns (Succeeds r) { - x = r; + created = (address(r) != address(0)); txt = "success"; } catch Error(string memory s) { txt = s; @@ -28,5 +28,5 @@ contract C { // ==== // EVMVersion: >=byzantium // ---- -// f() -> 0, 0, 96, 13, "test message." -// g() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a, 0, 96, 7, "success" +// f() -> false, 0x40, 13, "test message." +// g() -> true, 0x40, 7, "success" diff --git a/test/libsolidity/semanticTests/tryCatch/super_trivial.sol b/test/libsolidity/semanticTests/tryCatch/require.sol similarity index 87% rename from test/libsolidity/semanticTests/tryCatch/super_trivial.sol rename to test/libsolidity/semanticTests/tryCatch/require.sol index 98fbcddb21b5..730243208e55 100644 --- a/test/libsolidity/semanticTests/tryCatch/super_trivial.sol +++ b/test/libsolidity/semanticTests/tryCatch/require.sol @@ -1,5 +1,5 @@ contract C { - function g(bool x) external pure { + function g(bool x) public pure { require(x); } function f(bool x) public returns (uint) { diff --git a/test/libsolidity/semanticTests/tryCatch/trivial.sol b/test/libsolidity/semanticTests/tryCatch/require_pre_byzantium.sol similarity index 91% rename from test/libsolidity/semanticTests/tryCatch/trivial.sol rename to test/libsolidity/semanticTests/tryCatch/require_pre_byzantium.sol index d43477e994ab..eb9251ec7048 100644 --- a/test/libsolidity/semanticTests/tryCatch/trivial.sol +++ b/test/libsolidity/semanticTests/tryCatch/require_pre_byzantium.sol @@ -11,6 +11,8 @@ contract C { } } } +// ==== +// EVMVersion: 1 // f(bool): false -> 2 diff --git a/test/libsolidity/semanticTests/tryCatch/return_function.sol b/test/libsolidity/semanticTests/tryCatch/return_function.sol index 6aac30fe4617..396633655e10 100644 --- a/test/libsolidity/semanticTests/tryCatch/return_function.sol +++ b/test/libsolidity/semanticTests/tryCatch/return_function.sol @@ -1,7 +1,7 @@ contract C { function g() public returns (uint a, function() external h, uint b) { a = 1; - h = this.fun; + h = C(address(0x1234)).fun; b = 9; } function f() public returns (uint, function() external, uint) { @@ -14,4 +14,4 @@ contract C { function fun() public pure {} } // ---- -// f() -> 0x1, 0xc06afe3a8444fc0004668591e8306bfb9968e79e946644cd0000000000000000, 9 +// f() -> 0x1, 0x1234946644cd0000000000000000, 9 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 549512eb3e44..4d810f970987 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -12,6 +12,8 @@ contract C { function g() public view returns (uint) { return address(0).code.length; } function h() public view returns (uint) { return address(1).code.length; } } +// ==== +// bytecodeFormat: legacy // ---- // constructor() -> // gas irOptimized: 70760 diff --git a/test/libsolidity/semanticTests/various/address_code_complex.sol b/test/libsolidity/semanticTests/various/address_code_complex.sol index f2d21c9069b3..d228d99d1767 100644 --- a/test/libsolidity/semanticTests/various/address_code_complex.sol +++ b/test/libsolidity/semanticTests/various/address_code_complex.sol @@ -12,6 +12,8 @@ contract C { function f() public returns (bytes memory) { return address(new A()).code; } function g() public returns (uint) { return address(new A()).code.length; } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> 0x20, 0x20, 0x48aa5566000000 // g() -> 0x20 diff --git a/test/libsolidity/semanticTests/various/code_access_content.sol b/test/libsolidity/semanticTests/various/code_access_content.sol index 22ceff337f89..b8b13b3c677f 100644 --- a/test/libsolidity/semanticTests/various/code_access_content.sol +++ b/test/libsolidity/semanticTests/various/code_access_content.sol @@ -36,6 +36,8 @@ contract C { return true; } } +// ==== +// bytecodeFormat: legacy // ---- // testRuntime() -> true // gas legacy: 76575 diff --git a/test/libsolidity/semanticTests/various/code_access_create.sol b/test/libsolidity/semanticTests/various/code_access_create.sol index f5f0b8644423..e3a6e03728e9 100644 --- a/test/libsolidity/semanticTests/various/code_access_create.sol +++ b/test/libsolidity/semanticTests/various/code_access_create.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test when eofcreate will be allowed in inline assembly. contract D { uint256 x; @@ -21,6 +22,8 @@ contract C { return d.f(); } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> 7 // gas legacy: 76647 diff --git a/test/libsolidity/semanticTests/various/code_access_padding.sol b/test/libsolidity/semanticTests/various/code_access_padding.sol index 831d4bde4ab4..6c07fb4e089e 100644 --- a/test/libsolidity/semanticTests/various/code_access_padding.sol +++ b/test/libsolidity/semanticTests/various/code_access_padding.sol @@ -14,5 +14,7 @@ contract C { } } } +// ==== +// bytecodeFormat: legacy // ---- // diff() -> 0 # This checks that the allocation function pads to multiples of 32 bytes # diff --git a/test/libsolidity/semanticTests/various/code_access_runtime.sol b/test/libsolidity/semanticTests/various/code_access_runtime.sol index 10d7c1852e95..0c848fc592eb 100644 --- a/test/libsolidity/semanticTests/various/code_access_runtime.sol +++ b/test/libsolidity/semanticTests/various/code_access_runtime.sol @@ -21,6 +21,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // test() -> 42 // gas legacy: 76034 diff --git a/test/libsolidity/semanticTests/various/code_length.sol b/test/libsolidity/semanticTests/various/code_length.sol index 844a0f65706f..08065b302c99 100644 --- a/test/libsolidity/semanticTests/various/code_length.sol +++ b/test/libsolidity/semanticTests/various/code_length.sol @@ -57,6 +57,8 @@ contract C { } } +// ==== +// bytecodeFormat: legacy // ---- // constructor() // gas legacy: 66989 diff --git a/test/libsolidity/semanticTests/various/code_length_contract_member.sol b/test/libsolidity/semanticTests/various/code_length_contract_member.sol index ff883139a46e..79e940080f02 100644 --- a/test/libsolidity/semanticTests/various/code_length_contract_member.sol +++ b/test/libsolidity/semanticTests/various/code_length_contract_member.sol @@ -11,5 +11,7 @@ contract C { return (s.code.length, s.another.length, address(this).code.length > 50); } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> 0x20, 0x20, true diff --git a/test/libsolidity/semanticTests/various/codehash.sol b/test/libsolidity/semanticTests/various/codehash.sol index fa7dab9dab9f..465e2ee31b51 100644 --- a/test/libsolidity/semanticTests/various/codehash.sol +++ b/test/libsolidity/semanticTests/various/codehash.sol @@ -13,6 +13,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // f() -> 0x0 // g() -> 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 diff --git a/test/libsolidity/semanticTests/various/codehash_assembly.sol b/test/libsolidity/semanticTests/various/codehash_assembly.sol index fe2210fa107a..81c2286d5e44 100644 --- a/test/libsolidity/semanticTests/various/codehash_assembly.sol +++ b/test/libsolidity/semanticTests/various/codehash_assembly.sol @@ -17,6 +17,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // f() -> 0 // g() -> 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 diff --git a/test/libsolidity/semanticTests/various/create_calldata.sol b/test/libsolidity/semanticTests/various/create_calldata.sol index a5f61d2ddd67..7e3e326228a7 100644 --- a/test/libsolidity/semanticTests/various/create_calldata.sol +++ b/test/libsolidity/semanticTests/various/create_calldata.sol @@ -6,6 +6,8 @@ contract C { assert(msg.data.length == 0); } } +// ==== +// bytecodeFormat: legacy // ---- // constructor(): 42 -> // gas irOptimized: 68239 diff --git a/test/libsolidity/semanticTests/various/create_random.sol b/test/libsolidity/semanticTests/various/create_random.sol index 676ec32a89ae..b053deb442ed 100644 --- a/test/libsolidity/semanticTests/various/create_random.sol +++ b/test/libsolidity/semanticTests/various/create_random.sol @@ -33,6 +33,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // addr() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e // testRunner() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a, 0x2c1c30623ddd93e0b765a6caaca0c859eeb0644d diff --git a/test/libsolidity/semanticTests/various/eof/create_calldata.sol b/test/libsolidity/semanticTests/various/eof/create_calldata.sol new file mode 100644 index 000000000000..ae1fc39ec6c8 --- /dev/null +++ b/test/libsolidity/semanticTests/various/eof/create_calldata.sol @@ -0,0 +1,21 @@ +contract C { + bytes public s; + constructor(uint256 x, bytes memory b) { + // On EOF msg.data contains constructor arguments, while on legacy it's empty + // (arguments are appended to the code). + s = msg.data; + assert(msg.data.length == 288); + uint y; + bytes memory d; + (y, d) = abi.decode(msg.data, (uint256, bytes)); + assert(x == y); + assert(b.length == d.length); + for (uint i = 0; i < b.length; ++i) + assert(b[i] == d[i]); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// constructor(): 42, 0x20, 0xc0, 1, 2, 3, 4, 5, 6 -> +// s() -> 0x20, 0x0120, 42, 0x20, 0xc0, 1, 2, 3, 4, 5, 6 diff --git a/test/libsolidity/semanticTests/various/gasleft_decrease.sol b/test/libsolidity/semanticTests/various/gasleft_decrease.sol index ab7302743f64..ea891edc4e5f 100644 --- a/test/libsolidity/semanticTests/various/gasleft_decrease.sol +++ b/test/libsolidity/semanticTests/various/gasleft_decrease.sol @@ -14,6 +14,8 @@ contract C { return true; } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> true // g() -> true diff --git a/test/libsolidity/semanticTests/various/many_subassemblies.sol b/test/libsolidity/semanticTests/various/many_subassemblies.sol index b270c7006694..a320a2aa3eca 100644 --- a/test/libsolidity/semanticTests/various/many_subassemblies.sol +++ b/test/libsolidity/semanticTests/various/many_subassemblies.sol @@ -15,24 +15,26 @@ contract D { // This is primarily meant to test assembly import via --import-asm-json. // The exported JSON will fail the reimport unless the subassembly indices are parsed // correctly - as hex numbers. - new C0(); - new C1(); - new C2(); - new C3(); - new C4(); - new C5(); - new C6(); - new C7(); - new C8(); - new C9(); - new C10(); + new C0{salt: hex"00"}(); + new C1{salt: hex"01"}(); + new C2{salt: hex"02"}(); + new C3{salt: hex"03"}(); + new C4{salt: hex"04"}(); + new C5{salt: hex"05"}(); + new C6{salt: hex"06"}(); + new C7{salt: hex"07"}(); + new C8{salt: hex"08"}(); + new C9{salt: hex"09"}(); + new C10{salt: hex"0a"}(); } } +// ==== +// EVMVersion: >=constantinople // ---- // run() -> -// gas irOptimized: 374934 +// gas irOptimized: 375192 // gas irOptimized code: 6600 -// gas legacy: 375119 +// gas legacy: 375404 // gas legacy code: 17600 -// gas legacyOptimized: 375119 +// gas legacyOptimized: 375464 // gas legacyOptimized code: 17600 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol index 4cb5c8c713bf..bf70caee5b54 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol @@ -62,6 +62,7 @@ contract D { } // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // constructor(), 1 ether -> // gas irOptimized: 67028 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol index a582649196c3..7629fabc1ce2 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol @@ -33,6 +33,7 @@ contract D { } // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // constructor(), 2 ether -> // gas irOptimized: 108104 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol index dd550d31a0cf..c9f50046c07d 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol @@ -80,6 +80,7 @@ contract D { // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // constructor(), 1 ether -> // gas irOptimized: 132974 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol deleted file mode 100644 index 4639d34c7071..000000000000 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ /dev/null @@ -1,28 +0,0 @@ -contract helper { - function getBalance() public payable returns (uint256 myBalance) { - return address(this).balance; - } -} - - -contract test { - helper h; - - constructor() payable { - h = new helper(); - } - - function sendAmount(uint256 amount) public payable returns (uint256 bal) { - uint256 someStackElement = 20; - return h.getBalance{value: amount + 3, gas: 1000}(); - } -} -// ---- -// constructor(), 20 wei -> -// gas irOptimized: 114463 -// gas irOptimized code: 58800 -// gas legacy: 120091 -// gas legacy code: 132400 -// gas legacyOptimized: 114536 -// gas legacyOptimized code: 65800 -// sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/various/value_insane.sol b/test/libsolidity/semanticTests/various/value_insane.sol deleted file mode 100644 index bc6a803de92f..000000000000 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ /dev/null @@ -1,27 +0,0 @@ -contract helper { - function getBalance() public payable returns (uint256 myBalance) { - return address(this).balance; - } -} - - -contract test { - helper h; - - constructor() payable { - h = new helper(); - } - - function sendAmount(uint256 amount) public returns (uint256 bal) { - return h.getBalance{value: amount + 3, gas: 1000}(); - } -} -// ---- -// constructor(), 20 wei -> -// gas irOptimized: 114527 -// gas irOptimized code: 59600 -// gas legacy: 120199 -// gas legacy code: 133600 -// gas legacyOptimized: 114568 -// gas legacyOptimized code: 66200 -// sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/viaYul/conversion/function_cast.sol b/test/libsolidity/semanticTests/viaYul/conversion/function_cast.sol index 843376baa553..7aaaa648f659 100644 --- a/test/libsolidity/semanticTests/viaYul/conversion/function_cast.sol +++ b/test/libsolidity/semanticTests/viaYul/conversion/function_cast.sol @@ -9,13 +9,14 @@ contract C { return this.g()(x) + 1; } function t() external view returns ( - function(uint) external returns (uint) a, - function(uint) external view returns (uint) b) { - a = this.f; - b = this.f; + function(uint) external returns (uint) a, + function(uint) external view returns (uint) b + ) { + a = C(address(0x1234)).f; + b = C(address(0x1234)).f; } } // ---- // f(uint256): 2 -> 4 // h(uint256): 2 -> 5 -// t() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79eb3de648b0000000000000000, 0xc06afe3a8444fc0004668591e8306bfb9968e79eb3de648b0000000000000000 +// t() -> 0x1234b3de648b0000000000000000, 0x1234b3de648b0000000000000000 diff --git a/test/libsolidity/semanticTests/viaYul/function_address.sol b/test/libsolidity/semanticTests/viaYul/function_address.sol index 0c1c58dd821d..a781db753e30 100644 --- a/test/libsolidity/semanticTests/viaYul/function_address.sol +++ b/test/libsolidity/semanticTests/viaYul/function_address.sol @@ -1,15 +1,18 @@ contract C { function f() external returns (address) { - return this.f.address; + return C(address(0x1234)).f.address; } - function g() external returns (bool) { - return this.f.address == address(this); + function g() external returns (bool, bool) { + return ( + this.f.address == address(this), + C(address(0x1234)).f.address == address(0x1234) + ); } function h(function() external a) public returns (address) { - return a.address; + return a.address; } } // ---- -// f() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e -// g() -> true +// f() -> 0x1234 +// g() -> true, true // h(function): left(0x1122334400112233445566778899AABBCCDDEEFF42424242) -> 0x1122334400112233445566778899AABBCCDDEEFF diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol index ed6f627b5adb..25f08dff48ee 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol @@ -25,7 +25,10 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTIgnoreOS: macos // ---- // Warning 6328: (325-355): CHC: Assertion violation happens here. // Warning 6328: (578-608): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (691-721): CHC: Assertion violation happens here. +// Warning 6328: (959-989): CHC: Assertion violation happens here. +// Warning 6328: (1079-1109): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol index c13e9ce07fc7..d2446c5f92e6 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol @@ -23,9 +23,12 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTIgnoreCex: yes +// SMTIgnoreOS: macos // ---- // Warning 6328: (326-356): CHC: Assertion violation happens here. // Warning 6328: (579-609): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (692-722): CHC: Assertion violation happens here. +// Warning 6328: (960-990): CHC: Assertion violation happens here. +// Warning 6328: (1080-1110): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol index 4b4f7a3ace98..e4b42c926378 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol @@ -12,4 +12,4 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 6328: (330-360): CHC: Assertion violation might happen here. -// Warning 7812: (330-360): BMC: Assertion violation might happen here. +// Warning 4661: (330-360): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol index b2d1b4acc6d0..3bc9da4d63fe 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol @@ -23,8 +23,12 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTIgnoreOS: macos +// SMTIgnoreCex: yes // ---- -// Warning 6328: (334-364): CHC: Assertion violation happens here.\nCounterexample:\n\ndata = [0x4f]\nb2 = [0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c]\nb3 = []\nb4 = []\nx = 0\ny = 0\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeSlice(sig, [0x4f]) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (334-364): CHC: Assertion violation happens here. // Warning 6328: (588-618): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (702-732): CHC: Assertion violation happens here. +// Warning 6328: (971-1001): CHC: Assertion violation happens here. +// Warning 6328: (1086-1116): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol index 4c21a02a6bbb..dbf28814d0ea 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol @@ -23,8 +23,12 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTIgnoreOS: macos +// SMTIgnoreCex: yes // ---- -// Warning 6328: (335-365): CHC: Assertion violation happens here.\nCounterexample:\n\ndata = [36]\nb3 = []\nb4 = []\nx = 0\ny = 0\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeSlice(sig, [36]) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (335-365): CHC: Assertion violation happens here. // Warning 6328: (589-619): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (703-733): CHC: Assertion violation happens here. +// Warning 6328: (972-1002): CHC: Assertion violation happens here. +// Warning 6328: (1087-1117): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/compound_bitwise_or_uint_3.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/compound_bitwise_or_uint_3.sol index 02d538d7d64c..9562653806df 100644 --- a/test/libsolidity/smtCheckerTests/bmc_coverage/compound_bitwise_or_uint_3.sol +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/compound_bitwise_or_uint_3.sol @@ -12,4 +12,4 @@ contract C { // SMTEngine: bmc // SMTShowUnproved: no // ---- -// Warning 2788: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/cross_contract_getter_call.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/cross_contract_getter_call.sol new file mode 100644 index 000000000000..f36647ed2b04 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/cross_contract_getter_call.sol @@ -0,0 +1,22 @@ +contract C { + D internal d; + constructor() { + d = new D(); + } + function invokeAndCheck() public { + d.set(); + assert(d.n() <= 1); + } +} + +contract D { + uint public n; + function set() external { + n = 1; + } +} +// ==== +// SMTEngine: bmc +// ---- +// Warning 8729: (51-58): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 4661: (112-130): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol index 9e5123ab5bd5..67e7899db3f2 100644 --- a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol +++ b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol @@ -5,19 +5,25 @@ contract C { assert(k1 == k2); } - function c2() public pure { + function c2() public pure { bytes32 s1 = sha256("10"); bytes32 s2 = sha256("10"); assert(s1 == s2); } - function c3() public pure { + function c3() public pure { bytes32 r1 = ripemd160("100"); bytes32 r2 = ripemd160("100"); assert(r1 == r2); } + + function c4() public pure { + address e1 = ecrecover("a", 1, hex"bb", unicode"c"); + address e2 = ecrecover("a", 1, hex"bb", unicode"c"); + assert(e1 == e2); + } } // ==== // SMTEngine: chc // ---- -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol index 813185adf497..b785895947f5 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol @@ -7,10 +7,9 @@ contract C { } } // ==== -// SMTEngine: all -// SMTIgnoreOS: macos +// SMTEngine: chc +// SMTSolvers: eld // ---- // Warning 9302: (96-117): Return value of low-level calls not used. -// Warning 6328: (121-156): CHC: Assertion violation might happen here. // Warning 6328: (175-211): CHC: Assertion violation happens here. -// Warning 4661: (121-156): BMC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_2.sol b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_2.sol index 968095bb2b19..ef4b19c1d41c 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_2.sol @@ -7,9 +7,9 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTSolvers: eld // ---- // Warning 9302: (96-116): Return value of low-level calls not used. -// Warning 6328: (120-156): CHC: Assertion violation might happen here. // Warning 6328: (175-210): CHC: Assertion violation happens here. -// Warning 4661: (120-156): BMC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external.sol b/test/libsolidity/smtCheckerTests/external_calls/external.sol index 5ddb61a2226d..3e6dbe6411c5 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external.sol @@ -15,7 +15,9 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTTargets: assert +// SMTIgnoreCex: yes +// SMTIgnoreOS: linux // ---- -// Warning 6328: (167-181): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (167-181): CHC: Assertion violation happens here.\nCounterexample:\nx = 10, d = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, d = 0\nC.f()\nState: x = 1, d = 0\nC.f()\nState: x = 2, d = 0\nC.f()\nState: x = 3, d = 0\nC.f()\nState: x = 4, d = 0\nC.f()\nState: x = 5, d = 0\nC.f()\nState: x = 6, d = 0\nC.g()\n d.d() -- untrusted external call, synthesized as:\n C.f() -- reentrant call\n C.f() -- reentrant call\nState: x = 8, d = 0\nC.g()\n d.d() -- untrusted external call, synthesized as:\n C.f() -- reentrant call\n C.f() -- reentrant call diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_1.sol new file mode 100644 index 000000000000..a071d0f150cc --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_1.sol @@ -0,0 +1,9 @@ +contract C { + function f() external {} + function g() public { + (this.f)(); + } +} +// ==== +// SMTEngine: chc +// ---- diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_2.sol new file mode 100644 index 000000000000..bbff78aa73f3 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_2.sol @@ -0,0 +1,12 @@ +contract D { + function f() external {} +} + +contract C { + function g(D d) public { + ((d.f))(); + } +} +// ==== +// SMTEngine: chc +// ---- diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol index dd8a529a2f1f..65cd7b72cc3d 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol @@ -35,8 +35,7 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted -// SMTIgnoreOS: macos // ---- // Warning 6328: (256-277): CHC: Assertion violation happens here. -// Warning 6328: (533-554): CHC: Assertion violation happens here. +// Warning 6328: (533-554): CHC: Assertion violation might happen here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol index c1d567cfec7d..16779bb89a1f 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol @@ -47,7 +47,8 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted +// SMTIgnoreOS: macos // ---- // Warning 6328: (434-455): CHC: Assertion violation happens here. -// Warning 6328: (1270-1291): CHC: Assertion violation might happen here. +// Warning 6328: (1270-1291): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol index d7721037fb88..3e8e4f409650 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol @@ -40,6 +40,7 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted +// SMTIgnoreOS: macos // ---- // Warning 6328: (561-582): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_2.sol index 2b94abc0e02b..256a8870e10b 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_2.sol @@ -11,9 +11,9 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTIgnoreCex: yes +// SMTSolvers: eld // ---- -// Warning 6328: (150-186): CHC: Assertion violation might happen here. // Warning 6328: (205-240): CHC: Assertion violation happens here. -// Warning 4661: (150-186): BMC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol index 2a535329aca4..7d87fb07c405 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol @@ -11,9 +11,8 @@ contract C { } } // ==== -// SMTEngine: all -// SMTIgnoreOS: macos +// SMTEngine: chc +// SMTSolvers: eld // ---- -// Warning 6328: (150-183): CHC: Assertion violation might happen here. -// Warning 6328: (202-236): CHC: Assertion violation happens here.\nCounterexample:\n\ni = 0\n\nTransaction trace:\nC.constructor()\nC.g(0)\n i.f{value: 20}() -- untrusted external call -// Warning 4661: (150-183): BMC: Assertion violation happens here. +// Warning 6328: (202-236): CHC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol index 80e27e7e2a77..182bf15cc026 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol @@ -39,7 +39,8 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTSolvers: eld // SMTIgnoreInv: yes // ---- // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol index 34df5c0e0fb9..3b6630e6db47 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol @@ -33,6 +33,6 @@ contract C { // SMTContract: C // SMTEngine: chc // SMTExtCalls: trusted +// SMTSolvers: eld // ---- -// Warning 6328: (314-328): CHC: Assertion violation might happen here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol index bfc95b35a2fd..8afc574a8b9e 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol @@ -6,15 +6,16 @@ contract C { uint x; D d; function f() public { - if (x < 5) + if (x < 4) ++x; } function g() public { d.d(); - assert(x < 6); + assert(x < 5); } } // ==== // SMTEngine: all +// SMTTargets: assert // ---- -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/free_function_multiple_contracts.sol b/test/libsolidity/smtCheckerTests/functions/free_function_multiple_contracts.sol new file mode 100644 index 000000000000..49ca28f5c8d0 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/free_function_multiple_contracts.sol @@ -0,0 +1,20 @@ +function check(uint x) pure { + assert(x > 0); +} + +contract C { + function a() public pure { + check(1); + } +} + +contract D { + function b(uint x) public pure { + check(x); + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreCex: no +// ---- +// Warning 6328: (31-44): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nD.constructor()\nD.b(0)\n check(0) -- internal call diff --git a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol index 9f2fca60cefb..10a07e13648a 100644 --- a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol +++ b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol @@ -17,7 +17,7 @@ contract C is A { // ==== // SMTEngine: all // ---- -// Warning 6328: (49-63): CHC: Assertion violation happens here. -// Warning 6328: (115-129): CHC: Assertion violation happens here. -// Warning 6328: (147-161): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (49-63): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\nTransaction trace:\nC.constructor() +// Warning 6328: (115-129): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nC.constructor() +// Warning 6328: (147-161): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nC.constructor() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/library_constant.sol b/test/libsolidity/smtCheckerTests/functions/library_constant.sol index 53349f0b6c30..22fccbe70d6c 100644 --- a/test/libsolidity/smtCheckerTests/functions/library_constant.sol +++ b/test/libsolidity/smtCheckerTests/functions/library_constant.sol @@ -19,6 +19,6 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (103-122): CHC: Assertion violation happens here. -// Warning 4984: (196-201): CHC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (103-122): CHC: Assertion violation happens here.\nCounterexample:\nTON = 1000\n\nTransaction trace:\nl1.constructor()\nState: TON = 1000\nl1.f1() +// Warning 4984: (196-201): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\n\nx = 115792089237316195423570985008687907853269984665640564039457584007913129639935\n\nTransaction trace:\nC.constructor()\nC.f(115792089237316195423570985008687907853269984665640564039457584007913129639935)\n l1.f2(115792089237316195423570985008687907853269984665640564039457584007913129639935, 1) -- internal call +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/imports/import_library_2.sol b/test/libsolidity/smtCheckerTests/imports/import_library_2.sol index a1c3160ea23a..1046e6a49b11 100644 --- a/test/libsolidity/smtCheckerTests/imports/import_library_2.sol +++ b/test/libsolidity/smtCheckerTests/imports/import_library_2.sol @@ -25,5 +25,4 @@ contract ERC20 { // ==== // SMTEngine: all // ---- -// Warning 3944: (ERC20.sol:157-162): CHC: Underflow (resulting value less than 0) happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 3944: (ERC20.sol:157-162): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\n\namount = 1\n\nTransaction trace:\nERC20.constructor()\nERC20.transferFrom(1){ msg.sender: 0x2e15 }\n SafeMath.sub(0, 1) -- internal call diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_1.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_1.sol index 6ecfed7914a6..d8838195f544 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_1.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_1.sol @@ -17,4 +17,3 @@ contract C is B { // SMTIgnoreCex: no // ---- // Warning 6328: (52-66): CHC: Assertion violation happens here.\nCounterexample:\ny = 0, x = 1\n\nTransaction trace:\nC.constructor()\nState: y = 0, x = 0\nC.g()\n B.f() -- internal call -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_2.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_2.sol index 85e2677f782a..026ad07ab674 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_2.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_2.sol @@ -24,4 +24,3 @@ contract C is B { // SMTIgnoreCex: no // ---- // Warning 6328: (54-68): CHC: Assertion violation happens here.\nCounterexample:\ny = 0, z = 0, w = 0, a = 0, b = 0, x = 1\n\nTransaction trace:\nC.constructor()\nState: y = 0, z = 0, w = 0, a = 0, b = 0, x = 0\nC.g()\n A.f() -- internal call -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_3.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_3.sol index f1481197f11f..cc5115052c6e 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_3.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_3.sol @@ -30,4 +30,4 @@ contract C is B { // SMTIgnoreCex: no // ---- // Warning 6328: (64-78): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.g()\n B.f() -- internal call\n A.f() -- internal call\n C.v() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_4.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_4.sol index 04b7ea7480e9..adfcb5e2301a 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_4.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_4.sol @@ -37,4 +37,4 @@ contract C is B, A1 { // SMTIgnoreCex: no // ---- // Warning 6328: (64-78): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.g()\n C.f() -- internal call\n A1.f() -- internal call\n B.f() -- internal call\n A.f() -- internal call\n C.v() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_5.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_5.sol index e386c4b445b3..89bc75398604 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_5.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_5.sol @@ -31,4 +31,4 @@ contract C is B { // SMTIgnoreCex: no // ---- // Warning 6328: (97-111): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.g()\n B.f() -- internal call\n A.f() -- internal call\n C.v() -- internal call\n A.v() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_7.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_7.sol index 45cf7fe186ad..9c2981bf10b1 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_7.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_7.sol @@ -24,4 +24,4 @@ contract C is A { // SMTIgnoreCex: no // ---- // Warning 6328: (56-70): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.g()\n A.f() -- internal call\n C.v() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_9.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_9.sol index 9972c7e3ff26..36b22040a2a5 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_9.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_9.sol @@ -31,4 +31,3 @@ contract C is B { // ---- // Warning 6328: (62-76): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nB.f()\n A.f() -- internal call\n C.v() -- internal call // Warning 6328: (131-145): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nA.constructor()\nState: x = 0\nA.f()\n A.v() -- internal call -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_diamond_middle.sol b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_diamond_middle.sol index 8590b0bcfa86..e80e398fe924 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_diamond_middle.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_diamond_middle.sol @@ -25,6 +25,6 @@ contract D is B, C { // ==== // SMTEngine: all // ---- -// Warning 6328: (134-148): CHC: Assertion violation happens here. -// Warning 6328: (223-237): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (134-148): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nD.constructor() +// Warning 6328: (223-237): CHC: Assertion violation happens here.\nCounterexample:\nx = 3\n\nTransaction trace:\nD.constructor() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/invariants/array_access_2.sol b/test/libsolidity/smtCheckerTests/invariants/array_access_2.sol new file mode 100644 index 000000000000..891662f65af1 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/invariants/array_access_2.sol @@ -0,0 +1,22 @@ +contract C { + constructor() { + int8 v; + (v *= v); + } +} + +contract D { + bool[2] internal a; + + function f() internal view { + do {} while(!(a[1])); + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreInv: no +// SMTSolvers: z3 +// SMTTargets: overflow +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1180: Contract invariant(s) for :D:\n(true || true)\nReentrancy property(ies) for :C:\n(( = 0) && (x!5 = x!4))\nReentrancy property(ies) for :D:\n(( = 0) && (x!6 = x!4) && (a' = a))\n = 0 -> no errors\n = 1 -> Overflow at v *= v\n diff --git a/test/libsolidity/smtCheckerTests/invariants/solver_response_involves_bv2int.sol b/test/libsolidity/smtCheckerTests/invariants/solver_response_involves_bv2int.sol new file mode 100644 index 000000000000..54609b86a23c --- /dev/null +++ b/test/libsolidity/smtCheckerTests/invariants/solver_response_involves_bv2int.sol @@ -0,0 +1,16 @@ +// Taken from issue #15770 +contract c { + function f(uint len) public pure returns (bytes memory) { + bytes memory x = new bytes(len); + for (uint i = 0; i < len; i++) { + x[i] = bytes1(uint8(i)); + } + return x; + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreInv: no +// SMTSolvers: z3 +// ---- +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol index 652dd811f3d4..d0e82665ccfc 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol @@ -36,7 +36,7 @@ contract D is B,C { // ==== // SMTEngine: all // ---- -// Warning 6328: (160-174): CHC: Assertion violation happens here. -// Warning 6328: (193-207): CHC: Assertion violation happens here. -// Warning 6328: (226-240): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (160-174): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\nTransaction trace:\nB.constructor()\nState: x = 0\nA.f() +// Warning 6328: (193-207): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nA.f() +// Warning 6328: (226-240): CHC: Assertion violation happens here.\nCounterexample:\nx = 3\n\nTransaction trace:\nD.constructor()\nState: x = 0\nA.f() +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_two_invocations_2.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_two_invocations_2.sol index d6bc51ffd5c3..a41c918571a9 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_two_invocations_2.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_two_invocations_2.sol @@ -16,5 +16,5 @@ contract C // ==== // SMTEngine: all // ---- -// Warning 6328: (76-90): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (76-90): CHC: Assertion violation happens here.\nCounterexample:\nx = 3\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/assignment_chain_tuple_contract_3.sol b/test/libsolidity/smtCheckerTests/operators/assignment_chain_tuple_contract_3.sol index e53436a0f66c..1f0fd5829e84 100644 --- a/test/libsolidity/smtCheckerTests/operators/assignment_chain_tuple_contract_3.sol +++ b/test/libsolidity/smtCheckerTests/operators/assignment_chain_tuple_contract_3.sol @@ -23,4 +23,4 @@ contract D is C { // ---- // Warning 6328: (95-109): CHC: Assertion violation happens here.\nCounterexample:\ny = 3, x = 3\n\nTransaction trace:\nD.constructor()\nState: y = 3, x = 3\nC.f() // Warning 6328: (180-194): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 2\nC.g() -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_uint_3.sol b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_uint_3.sol index 2650b08975bd..ff246b362c54 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_uint_3.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_uint_3.sol @@ -12,4 +12,4 @@ contract C { // SMTEngine: all // ---- // Warning 6328: (125-140): CHC: Assertion violation might happen here. -// Warning 7812: (125-140): BMC: Assertion violation might happen here. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_add.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_add.sol new file mode 100644 index 000000000000..b174b9478810 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_add.sol @@ -0,0 +1,11 @@ +contract C { + uint8 constant N = 255; + + function f() public pure returns (uint8) { + return N + 1; + } +} +// ==== +// SMTEngine: chc +// ---- +// Warning 4984: (104-109): CHC: Overflow (resulting value larger than 255) happens here.\nCounterexample:\nN = 255\n = 0\n\nTransaction trace:\nC.constructor()\nState: N = 255\nC.f() diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_bitwise_not.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_bitwise_not.sol new file mode 100644 index 000000000000..54159b18074d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_bitwise_not.sol @@ -0,0 +1,9 @@ +contract C { + uint256 constant largeConstant = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + function test() public pure returns (uint256) { + return ~largeConstant; + } +} +// ==== +// SMTEngine: chc +// ---- diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_sub.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_sub.sol new file mode 100644 index 000000000000..39a9b7cac396 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_sub.sol @@ -0,0 +1,11 @@ +contract C { + uint256 public constant B = 1; + + function f() public pure returns (uint256) { + return B - 112; + } +} +// ==== +// SMTEngine: chc +// ---- +// Warning 3944: (113-120): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\nB = 1\n = 0\n\nTransaction trace:\nC.constructor()\nState: B = 1\nC.f() diff --git a/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol b/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol index b18d5426f5b8..ef02b7839d60 100644 --- a/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol +++ b/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol @@ -5,7 +5,7 @@ contract C { } } // ==== -// SMTEngine: all -// SMTIgnoreOS: macos +// SMTEngine: chc +// SMTSolvers: eld // ---- // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol b/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol index 644ecdb122f8..3057ae0ec4f6 100644 --- a/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol +++ b/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol @@ -21,5 +21,6 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTTargets: assert // ---- -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol b/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol index 50438175895e..2134068db614 100644 --- a/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol +++ b/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol @@ -8,4 +8,4 @@ contract C { // SMTEngine: all // ---- // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-80): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index 76ad6db55384..76078a582198 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -52,11 +52,9 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTTargets: assert // ---- // Warning 6328: (2209-2235): CHC: Assertion violation might happen here. // Warning 6328: (2245-2271): CHC: Assertion violation might happen here. // Info 1391: CHC: 14 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 7812: (2245-2271): BMC: Assertion violation might happen here. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/out_of_bounds/array_2d_4.sol b/test/libsolidity/smtCheckerTests/out_of_bounds/array_2d_4.sol index 2a9f39d1a2fa..e4d9bfdff56c 100644 --- a/test/libsolidity/smtCheckerTests/out_of_bounds/array_2d_4.sol +++ b/test/libsolidity/smtCheckerTests/out_of_bounds/array_2d_4.sol @@ -15,13 +15,11 @@ contract C { // SMTEngine: all // ---- // Warning 4984: (184-197): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 4984: (199-202): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6368: (228-232): CHC: Out of bounds access happens here. +// Warning 6368: (228-232): CHC: Out of bounds access happens here.\nCounterexample:\na = []\ni = 0\nj = 0\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.r() // Warning 4984: (228-244): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 4984: (246-249): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6368: (255-259): CHC: Out of bounds access happens here. +// Warning 6368: (255-259): CHC: Out of bounds access happens here.\nCounterexample:\na = []\ni = 0\nj = 0\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.r() // Warning 6368: (255-262): CHC: Out of bounds access happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. // Warning 2661: (184-197): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. // Warning 2661: (228-244): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Info 6002: BMC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/special/blobhash_beyond_limit.sol b/test/libsolidity/smtCheckerTests/special/blobhash_beyond_limit.sol new file mode 100644 index 000000000000..b68a9aa4b464 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/blobhash_beyond_limit.sol @@ -0,0 +1,11 @@ +contract C { + function f(uint index) public view { + uint limit = 9; // Since PECTRA + require(index >= limit); + assert(blobhash(index) == 0); + } +} +// ==== +// SMTEngine: all +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_2.sol b/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_2.sol index 942607bd8a6f..f6c182c1e91c 100644 --- a/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_2.sol +++ b/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_2.sol @@ -14,6 +14,5 @@ contract C is A { // ==== // SMTEngine: all // ---- -// Warning 6328: (60-74): CHC: Assertion violation happens here. -// Warning 6328: (240-254): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (60-74): CHC: Assertion violation happens here.\nCounterexample:\nv = 0, x = 115792089237316195423570985008687907853269984665640564039457584007913129637498\n\nTransaction trace:\nC.constructor(){ msg.value: 115792089237316195423570985008687907853269984665640564039457584007913129637498 } +// Warning 6328: (240-254): CHC: Assertion violation happens here.\nCounterexample:\nv = 115792089237316195423570985008687907853269984665640564039457584007913129637498, x = 115792089237316195423570985008687907853269984665640564039457584007913129637498\n\nTransaction trace:\nC.constructor(){ msg.value: 115792089237316195423570985008687907853269984665640564039457584007913129637498 } diff --git a/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_3.sol b/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_3.sol index fc8d6e08f300..4a659978f9f4 100644 --- a/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_3.sol +++ b/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_3.sol @@ -18,5 +18,5 @@ contract C is A, B { // ==== // SMTEngine: all // ---- -// Warning 6328: (60-74): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (60-74): CHC: Assertion violation happens here.\nCounterexample:\nx = 115792089237316195423570985008687907853269984665640564039457584007913129637498\n\nTransaction trace:\nC.constructor(){ msg.value: 115792089237316195423570985008687907853269984665640564039457584007913129637498 } +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol b/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol index c66ce565393a..e2e7e9ebd290 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol @@ -1,5 +1,8 @@ contract C { - bytes32 bhash; + bytes32 blob_hash; + bytes32 block_hash; + uint bfee; + uint blobfee; address coin; uint dif; uint prevrandao; @@ -14,7 +17,10 @@ contract C { address origin; function f() public payable { - bhash = blockhash(12); + blob_hash = blobhash(1); + block_hash = blockhash(12); + bfee = block.basefee; + blobfee = block.blobbasefee; coin = block.coinbase; dif = block.difficulty; prevrandao = block.prevrandao; @@ -30,7 +36,10 @@ contract C { fi(); - assert(bhash == blockhash(12)); + assert(blob_hash == blobhash(1)); + assert(block_hash == blockhash(12)); + assert(bfee == block.basefee); + assert(blobfee == block.blobbasefee); assert(coin == block.coinbase); assert(dif == block.difficulty); assert(prevrandao == block.prevrandao); @@ -46,7 +55,10 @@ contract C { } function fi() internal view { - assert(bhash == blockhash(12)); + assert(blob_hash == blobhash(1)); + assert(block_hash == blockhash(12)); + assert(bfee == block.basefee); + assert(blobfee == block.blobbasefee); assert(coin == block.coinbase); assert(dif == block.difficulty); assert(prevrandao == block.prevrandao); @@ -64,7 +76,7 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 8417: (293-309): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (645-661): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (1127-1143): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Info 1391: CHC: 26 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 8417: (432-448): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (898-914): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1494-1510): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Info 1391: CHC: 32 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol b/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol index 2b16f2d1aab7..be8436e82673 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol @@ -1,5 +1,8 @@ contract C { - bytes32 bhash; + bytes32 blob_hash; + bytes32 block_hash; + uint bfee; + uint blobfee; address coin; uint dif; uint prevrandao; @@ -14,7 +17,10 @@ contract C { address origin; function f() public payable { - bhash = blockhash(12); + blob_hash = blobhash(1); + block_hash = blockhash(12); + bfee = block.basefee; + blobfee = block.blobbasefee; coin = block.coinbase; dif = block.difficulty; prevrandao = block.prevrandao; @@ -30,8 +36,11 @@ contract C { fi(); - assert(bhash == blockhash(122)); - assert(coin != block.coinbase); + assert(blob_hash == blobhash(2)); + assert(block_hash == blockhash(122)); + assert(bfee != block.basefee); + assert(blobfee != block.blobbasefee); + assert(coin != block.coinbase); assert(dif != block.difficulty); assert(prevrandao != block.prevrandao); assert(glimit != block.gaslimit); @@ -46,7 +55,10 @@ contract C { } function fi() internal view { - assert(bhash == blockhash(122)); + assert(blob_hash == blobhash(2)); + assert(block_hash == blockhash(122)); + assert(bfee != block.basefee); + assert(blobfee != block.blobbasefee); assert(coin != block.coinbase); assert(dif != block.difficulty); assert(prevrandao != block.prevrandao); @@ -65,32 +77,38 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 8417: (293-309): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (646-662): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (1129-1145): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 6328: (563-594): CHC: Assertion violation happens here. -// Warning 6328: (598-628): CHC: Assertion violation happens here. -// Warning 6328: (632-663): CHC: Assertion violation happens here. -// Warning 6328: (667-705): CHC: Assertion violation happens here. -// Warning 6328: (709-741): CHC: Assertion violation happens here. -// Warning 6328: (745-775): CHC: Assertion violation happens here. -// Warning 6328: (779-812): CHC: Assertion violation happens here. -// Warning 6328: (816-855): CHC: Assertion violation happens here. -// Warning 6328: (859-887): CHC: Assertion violation happens here. -// Warning 6328: (891-913): CHC: Assertion violation happens here. -// Warning 6328: (917-943): CHC: Assertion violation happens here. -// Warning 6328: (947-976): CHC: Assertion violation happens here. -// Warning 6328: (980-1007): CHC: Assertion violation happens here. -// Warning 6328: (1046-1077): CHC: Assertion violation happens here. -// Warning 6328: (1081-1111): CHC: Assertion violation happens here. -// Warning 6328: (1115-1146): CHC: Assertion violation happens here. -// Warning 6328: (1150-1188): CHC: Assertion violation happens here. -// Warning 6328: (1192-1224): CHC: Assertion violation happens here. -// Warning 6328: (1228-1258): CHC: Assertion violation happens here. -// Warning 6328: (1262-1295): CHC: Assertion violation happens here. -// Warning 6328: (1299-1338): CHC: Assertion violation happens here. -// Warning 6328: (1342-1370): CHC: Assertion violation happens here. -// Warning 6328: (1374-1396): CHC: Assertion violation happens here. -// Warning 6328: (1400-1426): CHC: Assertion violation happens here. -// Warning 6328: (1430-1459): CHC: Assertion violation happens here. -// Warning 6328: (1463-1490): CHC: Assertion violation happens here. +// Warning 8417: (474-490): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (969-985): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1580-1596): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 6328: (744-776): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (780-816): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (820-849): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2e16, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (867-903): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (921-951): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (955-986): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (990-1028): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1032-1064): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1068-1098): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1102-1135): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1139-1178): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1182-1210): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1214-1236): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1240-1266): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1270-1299): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1303-1330): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1369-1401): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1405-1441): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0986, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1445-1474): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1492-1528): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1532-1562): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1566-1597): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0986, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1601-1639): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1643-1675): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1679-1709): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1713-1746): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1750-1789): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0986, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1793-1821): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1825-1847): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1851-1877): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0986, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1881-1910): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1914-1941): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call diff --git a/test/libsolidity/smtCheckerTests/typecast/fixed_bytes_array_from_strig_inline_array.sol b/test/libsolidity/smtCheckerTests/typecast/fixed_bytes_array_from_strig_inline_array.sol new file mode 100644 index 000000000000..c92fe2a7e356 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/typecast/fixed_bytes_array_from_strig_inline_array.sol @@ -0,0 +1,14 @@ +contract D { + function test() public pure { + bytes7[2] memory dummyBytes = [bytes7("A"), "B"]; + assert(uint56(dummyBytes[0]) == 0x41000000000000); + assert(uint56(dummyBytes[1]) == 0x42000000000000); + assert(uint56(dummyBytes[1]) == 0x41000000000000); // Should fail + } +} +// ==== +// SMTEngine: chc +// SMTTargets: assert +// ---- +// Warning 6328: (231-280): CHC: Assertion violation happens here.\nCounterexample:\n\ndummyBytes = [0x41000000000000, 0x42000000000000]\n\nTransaction trace:\nD.constructor()\nD.test() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/typecast/string_literal_to_fixed_bytes_constructor_for_deployment.sol b/test/libsolidity/smtCheckerTests/typecast/string_literal_to_fixed_bytes_constructor_for_deployment.sol new file mode 100644 index 000000000000..5226f886d959 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/typecast/string_literal_to_fixed_bytes_constructor_for_deployment.sol @@ -0,0 +1,21 @@ +contract A { + bytes3 public a; + + constructor(bytes3 _a) payable { + a = _a; + } +} + +contract B { + A a; + + constructor() payable { + a = (new A){value: 10}("abc"); + assert(a.a() == 0x616263); + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_mapping_aliasing_2.sol b/test/libsolidity/smtCheckerTests/types/array_mapping_aliasing_2.sol index fce586987795..bbc3a79cf1a1 100644 --- a/test/libsolidity/smtCheckerTests/types/array_mapping_aliasing_2.sol +++ b/test/libsolidity/smtCheckerTests/types/array_mapping_aliasing_2.sol @@ -34,16 +34,7 @@ contract C // ==== // SMTEngine: all // SMTIgnoreCex: yes -// SMTIgnoreOS: macos +// SMTTargets: assert // ---- -// Warning 6368: (439-453): CHC: Out of bounds access happens here. -// Warning 6368: (465-480): CHC: Out of bounds access might happen here. -// Warning 6368: (492-508): CHC: Out of bounds access happens here. -// Warning 6368: (492-511): CHC: Out of bounds access happens here. -// Warning 6368: (622-636): CHC: Out of bounds access happens here. -// Warning 6368: (737-752): CHC: Out of bounds access might happen here. -// Warning 6368: (850-866): CHC: Out of bounds access happens here. -// Warning 6368: (850-869): CHC: Out of bounds access happens here. -// Warning 6328: (936-956): CHC: Assertion violation happens here. -// Warning 6368: (1029-1043): CHC: Out of bounds access might happen here. +// Warning 6328: (936-956): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nC.constructor()\nC.g(0)\n C.f(map) -- counterexample incomplete; parameter name used instead of value -- internal call // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol b/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol index d5daba699912..5f4fad62abca 100644 --- a/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol +++ b/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol @@ -14,6 +14,7 @@ contract C } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTTargets: assert // ---- -// Info 1391: CHC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/tuple_assignment_array_empty.sol b/test/libsolidity/smtCheckerTests/types/tuple_assignment_array_empty.sol index 79be48b3ae81..3b9a4798688a 100644 --- a/test/libsolidity/smtCheckerTests/types/tuple_assignment_array_empty.sol +++ b/test/libsolidity/smtCheckerTests/types/tuple_assignment_array_empty.sol @@ -16,6 +16,7 @@ contract C // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTTargets: assert // ---- -// Warning 6328: (198-215): CHC: Assertion violation happens here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (198-215): CHC: Assertion violation happens here.\nCounterexample:\na = [3212, 4]\nx = 0\ny = 1\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.f(3212)\nState: a = [3212]\nC.f(1573)\nState: a = [3212, 1573]\nC.g(0, 1) +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/syntaxTests/tight_packing_literals.sol b/test/libsolidity/syntaxTests/abiEncoder/tight_packing_literals.sol similarity index 100% rename from test/libsolidity/syntaxTests/tight_packing_literals.sol rename to test/libsolidity/syntaxTests/abiEncoder/tight_packing_literals.sol diff --git a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol b/test/libsolidity/syntaxTests/abiEncoder/tight_packing_literals_fine.sol similarity index 100% rename from test/libsolidity/syntaxTests/tight_packing_literals_fine.sol rename to test/libsolidity/syntaxTests/abiEncoder/tight_packing_literals_fine.sol diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol index f324d2c33e30..036a2597616c 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol @@ -13,4 +13,6 @@ contract D { return a + b; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol index b21b7cfaff5e..03fb9bae673b 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol @@ -19,4 +19,6 @@ contract Test { L.set(item); } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol index 41bc072a5949..01d9658ce2cf 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol @@ -19,4 +19,6 @@ contract Test { L.get(item); } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol index 78d7b0512414..ef066593c4bc 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol @@ -25,4 +25,6 @@ contract C is B { validate() {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol index 1ac5d713b104..b937d1e2d1a2 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol @@ -32,4 +32,6 @@ import "B"; contract D is C { constructor() validate B() validate C() validate {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol index 073a125be984..9743d5318ca0 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol @@ -23,4 +23,6 @@ pragma abicoder v1; import "A"; contract C is B {} +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol index 963ed33c70e6..e4492a4ef742 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol @@ -13,4 +13,6 @@ pragma abicoder v1; import "A"; contract D is C {} +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol index 8aa2f8552c2b..5ae4cb0ed836 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol @@ -19,4 +19,6 @@ pragma abicoder v1; import "A"; contract D is C {} +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol index dd102cf51378..9a809b50a2fe 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol @@ -27,4 +27,6 @@ contract C is B { _; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol index e5df9cc82237..6665c42efd49 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol @@ -52,4 +52,6 @@ struct Data { contract X { function get() public view returns (Data memory) {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol b/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol index 18bf550c066b..e9ef53842c81 100644 --- a/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol +++ b/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol @@ -5,5 +5,7 @@ contract C { function i(uint[][2] calldata s) external { tmp_i = s; } } +// ==== +// compileViaYul: false // ---- -// UnimplementedFeatureError 1834: Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. +// UnimplementedFeatureError 1834: (35-127): Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. diff --git a/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol b/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol index 9f5bb8eab5b1..5db87f0d4edb 100644 --- a/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol +++ b/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol @@ -5,5 +5,7 @@ contract C { function i(uint[][] calldata s) external { tmp_i = s; } } +// ==== +// compileViaYul: false // ---- -// UnimplementedFeatureError 1834: Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. +// UnimplementedFeatureError 1834: (35-125): Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. diff --git a/test/libsolidity/syntaxTests/bytecodeReferences/circular_reference_internal_function.sol b/test/libsolidity/syntaxTests/bytecodeReferences/circular_reference_internal_function.sol index 0b06b2b7ae12..f25690aadc57 100644 --- a/test/libsolidity/syntaxTests/bytecodeReferences/circular_reference_internal_function.sol +++ b/test/libsolidity/syntaxTests/bytecodeReferences/circular_reference_internal_function.sol @@ -1,6 +1,6 @@ contract C { - // Internal uncalled function should not cause an cyclic dep. error + // Internal uncalled function should not cause a cyclic dep. error function foo() internal { new D(); } function callFoo() virtual public { foo(); } } diff --git a/test/libsolidity/syntaxTests/bytecodeReferences/library_non_called.sol b/test/libsolidity/syntaxTests/bytecodeReferences/library_non_called.sol index b7392ff3ee74..1374c3110d35 100644 --- a/test/libsolidity/syntaxTests/bytecodeReferences/library_non_called.sol +++ b/test/libsolidity/syntaxTests/bytecodeReferences/library_non_called.sol @@ -7,5 +7,7 @@ library L2 { contract A { function f() public pure { type(L2).creationCode; } } +// ==== +// bytecodeFormat: legacy // ---- // Warning 6133: (157-178): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/multiline_comments.sol b/test/libsolidity/syntaxTests/comments/multiline_comments.sol similarity index 100% rename from test/libsolidity/syntaxTests/multiline_comments.sol rename to test/libsolidity/syntaxTests/comments/multiline_comments.sol diff --git a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol index 5c127eb4a253..b7a4b4518473 100644 --- a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol +++ b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol @@ -4,5 +4,7 @@ contract C { fixed a3 = 0 / 0.123; fixed a4 = 0 / -0.123; } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (28-53): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/constructor/constructer_internal_function_abstract.sol b/test/libsolidity/syntaxTests/constructor/constructor_internal_function_abstract.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor/constructer_internal_function_abstract.sol rename to test/libsolidity/syntaxTests/constructor/constructor_internal_function_abstract.sol diff --git a/test/libsolidity/syntaxTests/constructor_this.sol b/test/libsolidity/syntaxTests/constructor/constructor_this.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor_this.sol rename to test/libsolidity/syntaxTests/constructor/constructor_this.sol diff --git a/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol b/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol index 2ca22790c128..ca52859ff928 100644 --- a/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol +++ b/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol @@ -2,4 +2,6 @@ pragma abicoder v1; abstract contract C { constructor(uint[][][] memory t) {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifer.sol b/test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifier.sol similarity index 100% rename from test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifer.sol rename to test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifier.sol diff --git a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol index ed7db1ec6c8b..74a659cd8b83 100644 --- a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol +++ b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol @@ -32,6 +32,7 @@ contract C { // ==== // EVMVersion: >=constantinople // compileViaYul: true +// bytecodeFormat: legacy // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. // Info 4164: (31-61): Inferred type: void @@ -89,4 +90,4 @@ contract C { // Info 4164: (563-574): Inferred type: (bool, word) -> word // Info 4164: (563-567): Inferred type: (?bm:type, ?bn:type) // Info 4164: (575-576): Inferred type: (bool, word) -// UnimplementedFeatureError 1834: No support for calling functions pointers yet. +// UnimplementedFeatureError 1834: (267-586): No support for calling functions pointers yet. diff --git a/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol b/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol index fc75e85947eb..72af2133f206 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol @@ -13,6 +13,7 @@ contract C // ==== // EVMVersion: >=constantinople // compileViaYul: true +// bytecodeFormat: legacy // ---- // Warning 2264: (std.stub:63-92): Experimental features are turned on. Do not use experimental features on live deployments. // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/functionCalls/calloptions_duplicated.sol b/test/libsolidity/syntaxTests/functionCalls/calloptions_duplicated.sol index 3b162a7f220a..417eea14d609 100644 --- a/test/libsolidity/syntaxTests/functionCalls/calloptions_duplicated.sol +++ b/test/libsolidity/syntaxTests/functionCalls/calloptions_duplicated.sol @@ -8,6 +8,8 @@ contract C { } } // ==== +// bytecodeFormat: legacy +// ==== // EVMVersion: >=constantinople // ---- // TypeError 9886: (78-101): Duplicate option "gas". diff --git a/test/libsolidity/syntaxTests/functionCalls/calloptions_on_delegatecall.sol b/test/libsolidity/syntaxTests/functionCalls/calloptions_on_delegatecall.sol index d719fdcd9bb7..858b9a1d2e89 100644 --- a/test/libsolidity/syntaxTests/functionCalls/calloptions_on_delegatecall.sol +++ b/test/libsolidity/syntaxTests/functionCalls/calloptions_on_delegatecall.sol @@ -3,6 +3,8 @@ contract C { address(10).delegatecall{value: 7, gas: 3}(""); } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 6189: (56-98): Cannot set option "value" for delegatecall. // Warning 9302: (56-102): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/functionCalls/calloptions_on_staticcall.sol b/test/libsolidity/syntaxTests/functionCalls/calloptions_on_staticcall.sol index e128f03f1f21..c525542c7e0b 100644 --- a/test/libsolidity/syntaxTests/functionCalls/calloptions_on_staticcall.sol +++ b/test/libsolidity/syntaxTests/functionCalls/calloptions_on_staticcall.sol @@ -5,6 +5,7 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // TypeError 2842: (56-96): Cannot set option "value" for staticcall. // Warning 9302: (56-100): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/functionCalls/calloptions_repeated.sol b/test/libsolidity/syntaxTests/functionCalls/calloptions_repeated.sol index 4356efcf95d5..0961881a1257 100644 --- a/test/libsolidity/syntaxTests/functionCalls/calloptions_repeated.sol +++ b/test/libsolidity/syntaxTests/functionCalls/calloptions_repeated.sol @@ -10,6 +10,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // TypeError 1645: (78-110): Function call options have already been set, you have to combine them into a single {...}-option. // TypeError 1645: (120-154): Function call options have already been set, you have to combine them into a single {...}-option. diff --git a/test/libsolidity/syntaxTests/functionCalls/empty_call_options.sol b/test/libsolidity/syntaxTests/functionCalls/empty_call_options.sol new file mode 100644 index 000000000000..6a14c1198c84 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/empty_call_options.sol @@ -0,0 +1,8 @@ +contract C { + function f() external payable returns (uint) { return 1; } + function g() public { + this.f{}(); + } +} +// ---- +// ParserError 2314: (116-117): Expected ';' but got '{' diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_delegatecall.sol b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_delegatecall.sol new file mode 100644 index 000000000000..fdbb79b96970 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_delegatecall.sol @@ -0,0 +1,11 @@ +contract C { + function foo() pure internal { + address(10).delegatecall{value: 7, gas: 3}(""); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 6189: (56-98): Cannot set option "value" for delegatecall. +// TypeError 3765: (56-98): Function call option "gas" cannot be used when compiling to EOF. +// Warning 9302: (56-102): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol new file mode 100644 index 000000000000..d43fb5969d72 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol @@ -0,0 +1,11 @@ +contract C { + function foo() pure internal { + address(10).staticcall{value: 7, gas: 3}(""); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 2842: (56-96): Cannot set option "value" for staticcall. +// TypeError 3765: (56-96): Function call option "gas" cannot be used when compiling to EOF. +// Warning 9302: (56-100): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/external_call_with_gas_option.sol b/test/libsolidity/syntaxTests/functionCalls/eof/external_call_with_gas_option.sol new file mode 100644 index 000000000000..9443bac0605f --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/eof/external_call_with_gas_option.sol @@ -0,0 +1,12 @@ +contract C { + function g(bool x) public pure { + require(x); + } + function f(bool x) public returns (uint) { + this.g{gas: 8000}(x); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 3765: (131-148): Function call option "gas" cannot be used when compiling to EOF. diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/lowlevel_call_options.sol b/test/libsolidity/syntaxTests/functionCalls/eof/lowlevel_call_options.sol new file mode 100644 index 000000000000..4bc515d7c54c --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/eof/lowlevel_call_options.sol @@ -0,0 +1,9 @@ +contract C { + function foo() internal { + (bool success, ) = address(10).call{value: 7}(""); + success; + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libsolidity/syntaxTests/functionCalls/lowlevel_call_options.sol b/test/libsolidity/syntaxTests/functionCalls/lowlevel_call_options.sol index da5c17a20ac0..c5ec6de71380 100644 --- a/test/libsolidity/syntaxTests/functionCalls/lowlevel_call_options.sol +++ b/test/libsolidity/syntaxTests/functionCalls/lowlevel_call_options.sol @@ -4,4 +4,6 @@ contract C { success; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/functionTypes/call_gas_on_function.sol b/test/libsolidity/syntaxTests/functionTypes/call_gas_on_function.sol index 6b926e2ddecb..e92d1cfb0489 100644 --- a/test/libsolidity/syntaxTests/functionTypes/call_gas_on_function.sol +++ b/test/libsolidity/syntaxTests/functionTypes/call_gas_on_function.sol @@ -4,5 +4,6 @@ contract C { x{gas: 2}(1); } } - +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_call_options.sol b/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_call_options.sol new file mode 100644 index 000000000000..da84e6ada8f1 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_call_options.sol @@ -0,0 +1,12 @@ +contract C { + function external_test_function() payable external {} + function comparison_operator_for_external_function_with_extra_slots() external returns (bool) { + return ( + (this.external_test_function{value: 4} == this.external_test_function) && + (this.external_test_function{value: 4} == this.external_test_function{value: 4}) + ); + } +} +// ---- +// TypeError 2271: (201-269): Built-in binary operator == cannot be applied to types function () payable external and function () payable external. +// TypeError 2271: (287-365): Built-in binary operator == cannot be applied to types function () payable external and function () payable external. diff --git a/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_extra_gas_slots.sol b/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_extra_gas_slots.sol deleted file mode 100644 index 12cbe2939bc3..000000000000 --- a/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_extra_gas_slots.sol +++ /dev/null @@ -1,12 +0,0 @@ -contract C { - function external_test_function() external {} - function comparison_operator_for_external_function_with_extra_slots() external returns (bool) { - return ( - (this.external_test_function{gas: 4} == this.external_test_function) && - (this.external_test_function{gas: 4} == this.external_test_function{gas: 4}) - ); - } -} -// ---- -// TypeError 2271: (193-259): Built-in binary operator == cannot be applied to types function () external and function () external. -// TypeError 2271: (277-351): Built-in binary operator == cannot be applied to types function () external and function () external. diff --git a/test/libsolidity/syntaxTests/functionTypes/eof/call_gas_on_function.sol b/test/libsolidity/syntaxTests/functionTypes/eof/call_gas_on_function.sol new file mode 100644 index 000000000000..c4f00843d597 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/eof/call_gas_on_function.sol @@ -0,0 +1,10 @@ +contract C { + function (uint) external returns (uint) x; + function f() public { + x{gas: 2}(1); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 3765: (94-103): Function call option "gas" cannot be used when compiling to EOF. diff --git a/test/libsolidity/syntaxTests/functionTypes/external_functions_with_variable_number_of_stack_slots.sol b/test/libsolidity/syntaxTests/functionTypes/external_functions_with_variable_number_of_stack_slots.sol index 8593bdbf4fed..a6d8d7c1d31c 100644 --- a/test/libsolidity/syntaxTests/functionTypes/external_functions_with_variable_number_of_stack_slots.sol +++ b/test/libsolidity/syntaxTests/functionTypes/external_functions_with_variable_number_of_stack_slots.sol @@ -1,8 +1,7 @@ contract C { - function f (address) external returns (bool) { - this.f{gas: 42}.address; + function f (address) payable external returns (bool) { + this.f{value: 42}.address; } } // ---- -// Warning 6321: (56-60): Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable. -// Warning 2018: (17-102): Function state mutability can be restricted to view +// Warning 6321: (64-68): Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable. diff --git a/test/libsolidity/syntaxTests/deprecated_functions.sol b/test/libsolidity/syntaxTests/globalFunctions/deprecated_functions.sol similarity index 100% rename from test/libsolidity/syntaxTests/deprecated_functions.sol rename to test/libsolidity/syntaxTests/globalFunctions/deprecated_functions.sol diff --git a/test/libsolidity/syntaxTests/cycle_checker_function_type.sol b/test/libsolidity/syntaxTests/iceRegressionTests/cycle_checker_function_type.sol similarity index 100% rename from test/libsolidity/syntaxTests/cycle_checker_function_type.sol rename to test/libsolidity/syntaxTests/iceRegressionTests/cycle_checker_function_type.sol diff --git a/test/libsolidity/syntaxTests/missing_functions_duplicate_bug.sol b/test/libsolidity/syntaxTests/iceRegressionTests/missing_functions_duplicate_bug.sol similarity index 100% rename from test/libsolidity/syntaxTests/missing_functions_duplicate_bug.sol rename to test/libsolidity/syntaxTests/iceRegressionTests/missing_functions_duplicate_bug.sol diff --git a/test/libsolidity/syntaxTests/immutable/creationCode.sol b/test/libsolidity/syntaxTests/immutable/creationCode.sol index 0a2282695cda..32fb4edea8bb 100644 --- a/test/libsolidity/syntaxTests/immutable/creationCode.sol +++ b/test/libsolidity/syntaxTests/immutable/creationCode.sol @@ -7,4 +7,6 @@ contract Test { return type(A).creationCode; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/immutable/no_assignments.sol b/test/libsolidity/syntaxTests/immutable/no_assignments.sol index 7357d174a8d5..92bcac8cfb7d 100644 --- a/test/libsolidity/syntaxTests/immutable/no_assignments.sol +++ b/test/libsolidity/syntaxTests/immutable/no_assignments.sol @@ -1,3 +1,4 @@ +// TODO: This test case should work the same way for EOF but EOF immutables support is not in its final state yet. contract C { uint immutable x; constructor() { @@ -8,6 +9,7 @@ contract C { function f() external view returns(uint) { return x; } } // ==== +// bytecodeFormat: legacy // optimize-yul: true // ---- -// CodeGenerationError 1284: Some immutables were read from but never assigned, possibly because of optimization. +// CodeGenerationError 1284: (115-283): Some immutables were read from but never assigned, possibly because of optimization. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/ancestor.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/ancestor.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi_no_constructor.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi_no_constructor.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi_no_constructor_modifier_style.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi_no_constructor_modifier_style.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_inheritance_definition.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_inheritance_definition.sol new file mode 100644 index 000000000000..1701f7723610 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_inheritance_definition.sol @@ -0,0 +1,5 @@ +contract A {} +contract B {} +contract C is A, B is B{ } +// ---- +// ParserError 6668: (47-49): More than one inheritance list. diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_overrides_receive.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_overrides_receive.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_overrides_receive.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_overrides_receive.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_with_override.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_with_override.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_with_override.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_with_override.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_with_override_intermediate.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_with_override_intermediate.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_with_override_intermediate.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_with_override_intermediate.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_without_override.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_without_override.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_without_override.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_without_override.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_without_override_intermediate.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_without_override_intermediate.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_without_override_intermediate.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_without_override_intermediate.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_overrides_fallback.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_overrides_fallback.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_overrides_fallback.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_overrides_fallback.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_parameter.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_parameter.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_parameter.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_parameter.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_return_parameter.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_return_parameter.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_return_parameter.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_return_parameter.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_unimplemented.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_unimplemented.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_unimplemented.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_unimplemented.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_with_override.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_with_override.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_with_override.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_with_override.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_with_override_intermediate.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_with_override_intermediate.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_with_override_intermediate.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_with_override_intermediate.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_without_override.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_without_override.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_without_override.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_without_override.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_without_override_intermediate.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_without_override_intermediate.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_without_override_intermediate.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_without_override_intermediate.sol diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/abstract_needed.sol b/test/libsolidity/syntaxTests/inheritance/override/interfaceException/abstract_needed.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/override/interface_exception/abstract_needed.sol rename to test/libsolidity/syntaxTests/inheritance/override/interfaceException/abstract_needed.sol diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/diamond_needed.sol b/test/libsolidity/syntaxTests/inheritance/override/interfaceException/diamond_needed.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/override/interface_exception/diamond_needed.sol rename to test/libsolidity/syntaxTests/inheritance/override/interfaceException/diamond_needed.sol diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/regular_optional.sol b/test/libsolidity/syntaxTests/inheritance/override/interfaceException/regular_optional.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/override/interface_exception/regular_optional.sol rename to test/libsolidity/syntaxTests/inheritance/override/interfaceException/regular_optional.sol diff --git a/test/libsolidity/syntaxTests/inheritance/override/public_var_parallel_funciton.sol b/test/libsolidity/syntaxTests/inheritance/override/public_var_parallel_function.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/override/public_var_parallel_funciton.sol rename to test/libsolidity/syntaxTests/inheritance/override/public_var_parallel_function.sol diff --git a/test/libsolidity/syntaxTests/inheritance/repeated_inheritance_definition.sol b/test/libsolidity/syntaxTests/inheritance/repeated_inheritance_definition.sol new file mode 100644 index 000000000000..87af62c6753d --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/repeated_inheritance_definition.sol @@ -0,0 +1,7 @@ +contract A {} +contract B {} +contract C is A is B is B is A{ } +// ---- +// ParserError 6668: (44-46): More than one inheritance list. +// ParserError 6668: (49-51): More than one inheritance list. +// ParserError 6668: (54-56): More than one inheritance list. diff --git a/test/libsolidity/syntaxTests/inline_arrays/dynamic_inline_array.sol b/test/libsolidity/syntaxTests/inlineArrays/dynamic_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/dynamic_inline_array.sol rename to test/libsolidity/syntaxTests/inlineArrays/dynamic_inline_array.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_and_passing_implicit_conversion.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_and_passing_implicit_conversion.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_int_conversion.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_const_int_conversion.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_int_conversion.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_const_int_conversion.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_string_conversion.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_const_string_conversion.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_string_conversion.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_const_string_conversion.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_no_type.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_no_type.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type_strings.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_no_type_strings.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type_strings.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_no_type_strings.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol similarity index 70% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol index 604f9b029800..7c67a647a3e2 100644 --- a/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol +++ b/test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol @@ -3,7 +3,9 @@ contract test { fixed[3] memory a = [fixed(3.5), fixed(-4.25), fixed(967.125)]; } } +// ==== +// compileViaYul: true // ---- // Warning 2072: (50-67): Unused local variable. // Warning 2018: (20-119): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (71-81): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_of_mapping_type.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_of_mapping_type.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_of_mapping_type.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_of_mapping_type.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol similarity index 70% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol index 63df5c044916..20e9de7649ca 100644 --- a/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol +++ b/test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol @@ -3,7 +3,9 @@ contract test { ufixed128x3[4] memory a = [ufixed128x3(3.5), 4.125, 2.5, 4.0]; } } +// ==== +// compileViaYul: true // ---- // Warning 2072: (50-73): Unused local variable. // Warning 2018: (20-118): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (77-93): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/inline_arrays/invalid_types_in_inline_array.sol b/test/libsolidity/syntaxTests/inlineArrays/invalid_types_in_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/invalid_types_in_inline_array.sol rename to test/libsolidity/syntaxTests/inlineArrays/invalid_types_in_inline_array.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/lvalues_as_inline_array.sol b/test/libsolidity/syntaxTests/inlineArrays/lvalues_as_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/lvalues_as_inline_array.sol rename to test/libsolidity/syntaxTests/inlineArrays/lvalues_as_inline_array.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/unnamed_type_tuple_in_inline_array.sol b/test/libsolidity/syntaxTests/inlineArrays/unnamed_type_tuple_in_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/unnamed_type_tuple_in_inline_array.sol rename to test/libsolidity/syntaxTests/inlineArrays/unnamed_type_tuple_in_inline_array.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_1.sol b/test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_1.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_1.sol rename to test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_1.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_2.sol b/test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_2.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_2.sol rename to test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_2.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_3.sol b/test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_3.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_3.sol rename to test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_3.sol diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol index 522ca801d975..801bdd7eea18 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol @@ -8,4 +8,6 @@ contract C { } } } +// ==== +// compileViaYul: false // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/basefee_reserved_london.sol b/test/libsolidity/syntaxTests/inlineAssembly/basefee_reserved_london.sol index 00ecaf01a426..1235dd547c18 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/basefee_reserved_london.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/basefee_reserved_london.sol @@ -10,3 +10,4 @@ contract C { // EVMVersion: =london // ---- // ParserError 5568: (98-105): Cannot use builtin function name "basefee" as identifier name. +// ParserError 7104: (137-144): Builtin function "basefee" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol index 0bab7e36c74e..4e81c4865407 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol @@ -10,3 +10,4 @@ contract C { // EVMVersion: >=cancun // ---- // ParserError 5568: (98-109): Cannot use builtin function name "blobbasefee" as identifier name. +// ParserError 7104: (141-152): Builtin function "blobbasefee" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol new file mode 100644 index 000000000000..9b6ee266c3ed --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol @@ -0,0 +1,10 @@ +contract C { + function f() public pure { + // NOTE: memoryguard is a builtin but only in pure Yul, not inline assembly. + // NOTE: memoryguard is not a reserved identifier. + assembly { function memoryguard() {} } + assembly { function f(memoryguard) {} } + assembly { function f() -> memoryguard {} } + assembly { let memoryguard } + } +} diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol new file mode 100644 index 000000000000..9dbf877d6bc2 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol @@ -0,0 +1,15 @@ +contract C { + function f() public view { + assembly { + // NOTE: All EVM instruction names are reserved identifiers in Yul. + // NOTE: We do provide builtins corresponding to these instructions. + function add(mstore) -> sstore {} + let coinbase + } + } +} +// ---- +// ParserError 5568: (245-248): Cannot use builtin function name "add" as identifier name. +// ParserError 5568: (249-255): Cannot use builtin function name "mstore" as identifier name. +// ParserError 5568: (260-266): Cannot use builtin function name "sstore" as identifier name. +// ParserError 5568: (286-294): Cannot use builtin function name "coinbase" as identifier name. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_non_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_non_builtin.sol new file mode 100644 index 000000000000..52f3a4320e96 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_non_builtin.sol @@ -0,0 +1,15 @@ +contract C { + function f() public pure { + assembly { + // NOTE: All EVM instruction names are reserved identifiers in Yul. + // NOTE: We don't provide builtins corresponding to these instructions. + function dup1(dup2) -> dup3 {} + let dup4 + } + } +} +// ---- +// DeclarationError 5017: (239-269): The identifier "dup1" is reserved and can not be used. +// DeclarationError 5017: (253-257): The identifier "dup2" is reserved and can not be used. +// DeclarationError 5017: (262-266): The identifier "dup3" is reserved and can not be used. +// DeclarationError 5017: (286-290): The identifier "dup4" is reserved and can not be used. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_pure_yul_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_pure_yul_builtin.sol new file mode 100644 index 000000000000..45b9df386aa3 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_pure_yul_builtin.sol @@ -0,0 +1,15 @@ +contract C { + function f() public view { + assembly { + // NOTE: These are builtins but only in pure Yul, not inline assembly. + // NOTE: Names of these builtins are also reserved identifiers. + function loadimmutable(setimmutable) -> datasize {} + let dataoffset + } + } +} +// ---- +// DeclarationError 5017: (234-285): The identifier "loadimmutable" is reserved and can not be used. +// DeclarationError 5017: (257-269): The identifier "setimmutable" is reserved and can not be used. +// DeclarationError 5017: (274-282): The identifier "datasize" is reserved and can not be used. +// DeclarationError 5017: (302-312): The identifier "dataoffset" is reserved and can not be used. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol b/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol index 96a384c54d20..0468ef093f52 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol @@ -6,4 +6,5 @@ contract c { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol index a177e8f63099..d55935aad27a 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol @@ -19,3 +19,4 @@ contract C { // EVMVersion: =byzantium +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol index 2aff4351ae8b..ddfa80d7fc7e 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol @@ -19,4 +19,5 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol b/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol index 8b34ab906d4a..8ee7f644be0e 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol @@ -7,4 +7,5 @@ contract c { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol b/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol index 038e8c4ff99e..915048905dbc 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol @@ -1,10 +1,9 @@ contract C { function f() public pure { assembly { - switch codesize() + switch calldataload(0) case hex"00" {} case hex"1122" {} } } } -// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol new file mode 100644 index 000000000000..617aeff98929 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol @@ -0,0 +1,15 @@ +contract C { + function f() view public { + assembly { + eofcreate("a", 0, 0, 0, 0) + returncontract("a", 0) + auxdataloadn(0) + } + } +} +// ==== +// bytecodeFormat: legacy +// ---- +// DeclarationError 7223: (75-84): Builtin function "eofcreate" is only available in EOF. +// DeclarationError 7223: (114-128): Builtin function "returncontract" is only available in EOF. +// DeclarationError 7223: (149-161): Builtin function "auxdataloadn" is only available in EOF. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol new file mode 100644 index 000000000000..a2a6540efde5 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol @@ -0,0 +1,16 @@ +// TODO: They should be available in some way in the context of inline assembly. For now it's disallowed them. +contract C { + function f() view public { + assembly { + eofcreate("a", 0, 0, 0, 0) + returncontract("a", 0) + auxdataloadn(0) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 4619: (186-195): Function "eofcreate" not found. +// DeclarationError 4619: (225-239): Function "returncontract" not found. +// DeclarationError 4619: (260-272): Function "auxdataloadn" not found. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/pc_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/pc_disallowed.sol index 816bb1c0d5f4..1178e9a2b907 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/pc_disallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/pc_disallowed.sol @@ -5,5 +5,7 @@ contract C { } } } +// ==== +// bytecodeFormat: legacy // ---- // SyntaxError 2450: (61-63): PC instruction is a low-level EVM feature. Because of that PC is disallowed in strict assembly. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/mcopy_reserved_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/mcopy_reserved_cancun.sol index b31bbffd85fe..4ebafc3ade57 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/mcopy_reserved_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/mcopy_reserved_cancun.sol @@ -19,3 +19,4 @@ contract C { // EVMVersion: >=cancun // ---- // ParserError 5568: (101-106): Cannot use builtin function name "mcopy" as identifier name. +// ParserError 7104: (134-139): Builtin function "mcopy" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol index 6c284a005956..7924f52e2340 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol @@ -19,3 +19,4 @@ contract C { // EVMVersion: >=paris // ---- // ParserError 5568: (101-111): Cannot use builtin function name "prevrandao" as identifier name. +// ParserError 7104: (143-153): Builtin function "prevrandao" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/string_literal_switch_case.sol b/test/libsolidity/syntaxTests/inlineAssembly/string_literal_switch_case.sol index 0a63987e143e..d612d10d0abb 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/string_literal_switch_case.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/string_literal_switch_case.sol @@ -1,10 +1,9 @@ contract C { function f() public pure { assembly { - switch codesize() + switch calldataload(0) case "1" {} case "2" {} } } } -// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/tload_reserved_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/tload_reserved_cancun.sol index 77c988577620..b8c09fd59c1a 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/tload_reserved_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/tload_reserved_cancun.sol @@ -10,3 +10,4 @@ contract C { // EVMVersion: >=cancun // ---- // ParserError 5568: (98-103): Cannot use builtin function name "tload" as identifier name. +// ParserError 7104: (135-140): Builtin function "tload" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/tstore_reserved_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/tstore_reserved_cancun.sol index 9f08d985aa38..9944c84f54c2 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/tstore_reserved_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/tstore_reserved_cancun.sol @@ -10,3 +10,4 @@ contract C { // EVMVersion: >=cancun // ---- // ParserError 5568: (98-104): Cannot use builtin function name "tstore" as identifier name. +// ParserError 7104: (136-142): Builtin function "tstore" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/use_msize_without_optimizer.sol b/test/libsolidity/syntaxTests/inlineAssembly/use_msize_without_optimizer.sol index 8cdf96641ada..d356fe299ae9 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/use_msize_without_optimizer.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/use_msize_without_optimizer.sol @@ -7,4 +7,5 @@ contract C { } // ==== // optimize-yul: false +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/stopAfterAnalysisError.sol b/test/libsolidity/syntaxTests/isoltestTesting/stopAfterAnalysisError.sol similarity index 100% rename from test/libsolidity/syntaxTests/stopAfterAnalysisError.sol rename to test/libsolidity/syntaxTests/isoltestTesting/stopAfterAnalysisError.sol diff --git a/test/libsolidity/syntaxTests/stopAfterParsingAnalysisErrorNotShowing.sol b/test/libsolidity/syntaxTests/isoltestTesting/stopAfterParsingAnalysisErrorNotShowing.sol similarity index 100% rename from test/libsolidity/syntaxTests/stopAfterParsingAnalysisErrorNotShowing.sol rename to test/libsolidity/syntaxTests/isoltestTesting/stopAfterParsingAnalysisErrorNotShowing.sol diff --git a/test/libsolidity/syntaxTests/stopAfterParsingError.sol b/test/libsolidity/syntaxTests/isoltestTesting/stopAfterParsingError.sol similarity index 100% rename from test/libsolidity/syntaxTests/stopAfterParsingError.sol rename to test/libsolidity/syntaxTests/isoltestTesting/stopAfterParsingError.sol diff --git a/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol b/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol new file mode 100644 index 000000000000..43acb5b14f7e --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol @@ -0,0 +1,9 @@ +contract C { + uint[2**256 - 1] x; + uint transient y; +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 3495: (0-60): This contract is very close to the end of storage. This limits its future upgradability. +// Warning 7325: (17-33): Type uint256[115792089237316195423570985008687907853269984665640564039457584007913129639935] covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/largeTypes/oversized_array_1d.sol b/test/libsolidity/syntaxTests/largeTypes/oversized_array_1d.sol new file mode 100644 index 000000000000..d46bdd9c3872 --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/oversized_array_1d.sol @@ -0,0 +1,5 @@ +contract C { + uint[2**256] x; +} +// ---- +// TypeError 1847: (22-28): Array length too large, maximum is 2**256 - 1. diff --git a/test/libsolidity/syntaxTests/largeTypes/oversized_array.sol b/test/libsolidity/syntaxTests/largeTypes/oversized_array_2d.sol similarity index 100% rename from test/libsolidity/syntaxTests/largeTypes/oversized_array.sol rename to test/libsolidity/syntaxTests/largeTypes/oversized_array_2d.sol diff --git a/test/libsolidity/syntaxTests/literal_comparisons.sol b/test/libsolidity/syntaxTests/literalOperations/literal_comparisons.sol similarity index 100% rename from test/libsolidity/syntaxTests/literal_comparisons.sol rename to test/libsolidity/syntaxTests/literalOperations/literal_comparisons.sol diff --git a/test/libsolidity/syntaxTests/upper_case_hex_literals.sol b/test/libsolidity/syntaxTests/literals/upper_case_hex_literals.sol similarity index 100% rename from test/libsolidity/syntaxTests/upper_case_hex_literals.sol rename to test/libsolidity/syntaxTests/literals/upper_case_hex_literals.sol diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol index e90443e14ef5..6136665e34bd 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol @@ -9,4 +9,6 @@ contract Test { contract Other { function f(uint) public pure returns (uint) {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol index 2f5c356c08d0..22f81cfb0241 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol @@ -6,5 +6,7 @@ contract Test { abstract contract Other { function f(uint) public returns (uint); } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9582: (97-121): Member "creationCode" not found or not visible after argument-dependent lookup in type(contract Other). diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol index 538a26e78941..8019dabb2176 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol @@ -6,5 +6,7 @@ contract Test { abstract contract Other { function f(uint) public returns (uint); } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9582: (91-114): Member "runtimeCode" not found or not visible after argument-dependent lookup in type(contract Other). diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol index c202046cc4d0..c4b3efedd77d 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol @@ -21,6 +21,8 @@ contract Test4 is Base { return type(Base).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 7813: (166-190): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode". // TypeError 7813: (300-323): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode". diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol index 57e3263e3249..4a5a760f792b 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol @@ -8,6 +8,8 @@ contract B { type(A).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 7813: (52-71): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode". // TypeError 7813: (133-152): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode". diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol index cda5d5c349f7..96303396e032 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol @@ -4,4 +4,6 @@ contract Test { } contract B { function f() public pure {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol index f746dc35d1de..8c707006891b 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol @@ -9,4 +9,6 @@ contract Test { contract Library { function f(uint) public pure returns (uint) {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccess_super.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccess_super.sol index 7d057e132b17..a8fef765eea1 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccess_super.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccess_super.sol @@ -9,5 +9,7 @@ contract SuperTest is Other { return type(super).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 4259: (177-182): Invalid type for argument in the function call. An enum type, contract type or an integer type is required, but type(contract super SuperTest) provided. diff --git a/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol b/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol index c9cade179f55..2a51276414d9 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol @@ -5,6 +5,8 @@ contract Test { } } contract C {} +// ==== +// bytecodeFormat: legacy // ---- // TypeError 4247: (55-75): Expression has to be an lvalue. // TypeError 4247: (100-119): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol b/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol index 40eaee040cbe..8e6fcf64e34a 100644 --- a/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol +++ b/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol @@ -12,6 +12,8 @@ contract C { contract D is C { constructor() {} } +// ==== +// bytecodeFormat: legacy // ---- // Warning 6417: (77-96): The constructor of the contract (or its base) uses inline assembly. Because of that, it might be that the deployed bytecode is different from type(...).runtimeCode. // Warning 6417: (118-137): The constructor of the contract (or its base) uses inline assembly. Because of that, it might be that the deployed bytecode is different from type(...).runtimeCode. diff --git a/test/libsolidity/syntaxTests/metaTypes/type_runtimecode.sol b/test/libsolidity/syntaxTests/metaTypes/type_runtimecode.sol index 6b054b4dacfb..d110b2c8ec37 100644 --- a/test/libsolidity/syntaxTests/metaTypes/type_runtimecode.sol +++ b/test/libsolidity/syntaxTests/metaTypes/type_runtimecode.sol @@ -6,4 +6,6 @@ contract C { return type(A).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/type_runtimecode_from_ternary_expression_.sol b/test/libsolidity/syntaxTests/metaTypes/type_runtimecode_from_ternary_expression_.sol index 8fcf65480e12..f802b9a00508 100644 --- a/test/libsolidity/syntaxTests/metaTypes/type_runtimecode_from_ternary_expression_.sol +++ b/test/libsolidity/syntaxTests/metaTypes/type_runtimecode_from_ternary_expression_.sol @@ -9,6 +9,8 @@ contract C { return (getA ? type(A) : type(B)).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9717: (126-133): Invalid mobile type in true expression. // TypeError 3703: (136-143): Invalid mobile type in false expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol index 58c74b9ad0b8..41bb9e046ce0 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol @@ -7,6 +7,8 @@ contract test { c; d; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-147): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (93-104): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol index 404cbc4bce0d..2809575b6c44 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol @@ -5,6 +5,8 @@ contract test { c; d; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-104): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (50-61): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol index b113c6bcce52..0a13eedcc372 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol @@ -5,6 +5,8 @@ contract test { a; d; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-108): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (50-63): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol index e80024a98ad8..d0d11105bd1c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol @@ -5,5 +5,7 @@ contract test { a; b; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (55-74): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol index 20be0208c11f..c1586595b154 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol @@ -7,5 +7,7 @@ contract A { a; b; c; d; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (52-70): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol index 7415ed6e85f0..07c4017e0d5f 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol @@ -4,6 +4,8 @@ contract test { ufixed32x1 b = 0; b; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-104): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (50-65): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol index fa32ec7dd86a..84e5b764027c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol @@ -5,6 +5,8 @@ contract test { ufixed8x1 c = ufixed8x1(1/3); c; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-182): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (67-84): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol index cb730221dfcd..9a714f6b9d6d 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol @@ -4,5 +4,7 @@ contract test { fixedString[0.5] = "Half"; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (96-112): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol index 9bc6243029d1..f0ec56875d7c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol @@ -5,5 +5,7 @@ contract test { } myStruct a = myStruct(3.125, 3); } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (94-112): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol index 8391734aec0f..7293e0f42528 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol @@ -10,7 +10,9 @@ contract test { a; b; c; d; e; f; g; } } +// ==== +// compileViaYul: true // ---- // Warning 2519: (238-252): This declaration shadows an existing declaration. // Warning 2018: (20-339): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (50-72): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol index 15ca25931efd..27133cf1d923 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol @@ -3,7 +3,9 @@ contract test { ufixed a = uint64(1) + ufixed(2); } } +// ==== +// compileViaYul: true // ---- // Warning 2072: (50-58): Unused local variable. // Warning 2018: (20-89): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (73-82): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol index 3d5acac99be3..7a5254a1a127 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol @@ -1,4 +1,6 @@ contract C { function f() public view returns (uint256 val) { return gasleft(); } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/negation.sol b/test/libsolidity/syntaxTests/operators/negation.sol similarity index 100% rename from test/libsolidity/syntaxTests/negation.sol rename to test/libsolidity/syntaxTests/operators/negation.sol diff --git a/test/libsolidity/syntaxTests/signed_rational_modulus.sol b/test/libsolidity/syntaxTests/operators/signed_rational_modulus.sol similarity index 100% rename from test/libsolidity/syntaxTests/signed_rational_modulus.sol rename to test/libsolidity/syntaxTests/operators/signed_rational_modulus.sol diff --git a/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol b/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol index ea41bbf3ec7a..2518a4b57e47 100644 --- a/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol +++ b/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol @@ -11,4 +11,4 @@ contract A { // Warning 2072: (93-104): Unused local variable. // Warning 2072: (114-121): Unused local variable. // Warning 2018: (41-128): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Fixed point types not implemented. +// UnimplementedFeatureError 1834: (0-130): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/parsing/invalid_variable_mutablity.sol b/test/libsolidity/syntaxTests/parsing/invalid_variable_mutability.sol similarity index 100% rename from test/libsolidity/syntaxTests/parsing/invalid_variable_mutablity.sol rename to test/libsolidity/syntaxTests/parsing/invalid_variable_mutability.sol diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol index 9932c4c3d48b..2e1c746baf4e 100644 --- a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol @@ -6,5 +6,7 @@ contract C { f1; f2; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (46-64): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/unexpected.sol b/test/libsolidity/syntaxTests/parsing/unexpected.sol similarity index 100% rename from test/libsolidity/syntaxTests/unexpected.sol rename to test/libsolidity/syntaxTests/parsing/unexpected.sol diff --git a/test/libsolidity/syntaxTests/double_stateVariable_declaration.sol b/test/libsolidity/syntaxTests/scoping/double_stateVariable_declaration.sol similarity index 100% rename from test/libsolidity/syntaxTests/double_stateVariable_declaration.sol rename to test/libsolidity/syntaxTests/scoping/double_stateVariable_declaration.sol diff --git a/test/libsolidity/syntaxTests/double_variable_declaration.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration.sol similarity index 100% rename from test/libsolidity/syntaxTests/double_variable_declaration.sol rename to test/libsolidity/syntaxTests/scoping/double_variable_declaration.sol diff --git a/test/libsolidity/syntaxTests/duplicate_contract.sol b/test/libsolidity/syntaxTests/scoping/duplicate_contract.sol similarity index 100% rename from test/libsolidity/syntaxTests/duplicate_contract.sol rename to test/libsolidity/syntaxTests/scoping/duplicate_contract.sol diff --git a/test/libsolidity/syntaxTests/missing_state_variable.sol b/test/libsolidity/syntaxTests/scoping/missing_state_variable.sol similarity index 100% rename from test/libsolidity/syntaxTests/missing_state_variable.sol rename to test/libsolidity/syntaxTests/scoping/missing_state_variable.sol diff --git a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol index f22b9755d652..5ac74bba7cb7 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol @@ -8,5 +8,6 @@ contract test { } // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // Warning 5574: (21-27154): Contract code size is 27164 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol index a0c7267d0d20..f3091ebf5351 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol @@ -8,5 +8,6 @@ contract test { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Warning 5574: (21-27154): Contract code size is 27205 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libsolidity/syntaxTests/sizeLimits/eof/bytecode_too_large.sol b/test/libsolidity/syntaxTests/sizeLimits/eof/bytecode_too_large.sol new file mode 100644 index 000000000000..e7c369577ce8 --- /dev/null +++ b/test/libsolidity/syntaxTests/sizeLimits/eof/bytecode_too_large.sol @@ -0,0 +1,14 @@ +// TODO: Change to proper error when all optimizations implemented for EOF +pragma abicoder v2; + +contract test { + function f() public pure returns (string memory ret) { + // 27000 bytes long data + ret = "........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................"; + } +} +// ==== +// EVMVersion: >=cancun +// bytecodeFormat: >=EOFv1 +// ---- +// CodeGenerationError 2703: (96-27229): Relative jump too far diff --git a/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol b/test/libsolidity/syntaxTests/sizeLimits/more_than_256_declarationerrors.sol similarity index 100% rename from test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol rename to test/libsolidity/syntaxTests/sizeLimits/more_than_256_declarationerrors.sol diff --git a/test/libsolidity/syntaxTests/more_than_256_importerrors.sol b/test/libsolidity/syntaxTests/sizeLimits/more_than_256_importerrors.sol similarity index 100% rename from test/libsolidity/syntaxTests/more_than_256_importerrors.sol rename to test/libsolidity/syntaxTests/sizeLimits/more_than_256_importerrors.sol diff --git a/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol b/test/libsolidity/syntaxTests/sizeLimits/more_than_256_syntaxerrors.sol similarity index 100% rename from test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol rename to test/libsolidity/syntaxTests/sizeLimits/more_than_256_syntaxerrors.sol diff --git a/test/libsolidity/syntaxTests/smoke_test.sol b/test/libsolidity/syntaxTests/smoke/smoke_test.sol similarity index 100% rename from test/libsolidity/syntaxTests/smoke_test.sol rename to test/libsolidity/syntaxTests/smoke/smoke_test.sol diff --git a/test/libsolidity/syntaxTests/specialFunctions/functionCallOptions_err.sol b/test/libsolidity/syntaxTests/specialFunctions/functionCallOptions_err.sol index 071859e53fb7..8e5ebcdeb97a 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/functionCallOptions_err.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/functionCallOptions_err.sol @@ -5,6 +5,8 @@ contract C { abi.encode(this.f{value: 2, gas: 1}); } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 2056: (60-76): This type cannot be encoded. // TypeError 2056: (92-106): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol index 6ecb4e4ff869..a69dcfa924b8 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol @@ -1,11 +1,11 @@ contract C { - function f() public pure { - bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f{gas: 2}, blockhash)); + function f() payable public { + bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f{value: 2}, blockhash)); h; } } // ---- -// TypeError 2056: (91-100): This type cannot be encoded. -// TypeError 2056: (102-103): This type cannot be encoded. -// TypeError 2056: (105-119): This type cannot be encoded. -// TypeError 2056: (121-130): This type cannot be encoded. +// TypeError 2056: (94-103): This type cannot be encoded. +// TypeError 2056: (105-106): This type cannot be encoded. +// TypeError 2056: (108-124): This type cannot be encoded. +// TypeError 2056: (126-135): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol new file mode 100644 index 000000000000..920e8d252c2b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol @@ -0,0 +1,3 @@ +contract C layout at abi.decode(abi.encode(42), (uint)) {} +// ---- +// TypeError 6396: (21-55): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol new file mode 100644 index 000000000000..3f87f87bb394 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol @@ -0,0 +1,3 @@ +abstract contract C layout at 42 { } +// ---- +// TypeError 7587: (20-32): Storage layout cannot be specified for abstract contracts. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract_inheriting_from_non_abstract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract_inheriting_from_non_abstract.sol new file mode 100644 index 000000000000..73dfa42f3a1b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract_inheriting_from_non_abstract.sol @@ -0,0 +1,4 @@ +contract A layout at 0x1234 {} +abstract contract C is A { } +// ---- +// TypeError 8894: (54-55): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol new file mode 100644 index 000000000000..fded26fadd0d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol @@ -0,0 +1,3 @@ +contract C layout at address(0x1234) {} +// ---- +// TypeError 6396: (21-36): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol new file mode 100644 index 000000000000..39e3fcec982e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol @@ -0,0 +1,7 @@ +contract A {} + +contract C layout at address(new A()) {} +contract D layout at uint160(address(this)) {} +// ---- +// TypeError 1139: (36-52): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (77-99): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol new file mode 100644 index 000000000000..af6b9424f607 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol @@ -0,0 +1,3 @@ +contract C layout at [1, 2, 3] {} +// ---- +// TypeError 6396: (21-30): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/assignment.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/assignment.sol new file mode 100644 index 000000000000..2849dea65212 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/assignment.sol @@ -0,0 +1,4 @@ +contract C layout at 1 = 2 { } +// ---- +// TypeError 4247: (21-22): Expression has to be an lvalue. +// TypeError 7407: (25-26): Type int_const 2 is not implicitly convertible to expected type int_const 1. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/at_before_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/at_before_layout.sol new file mode 100644 index 000000000000..fc6b53c364f5 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/at_before_layout.sol @@ -0,0 +1,3 @@ +contract C at layout 0x1234ABC { } +// ---- +// ParserError 2314: (11-13): Expected '{' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol new file mode 100644 index 000000000000..6ccb2ff7a1c8 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol @@ -0,0 +1,3 @@ +contract C layout at ~uint(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {} +// ---- +// TypeError 6396: (21-94): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol new file mode 100644 index 000000000000..083977c7ae15 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol @@ -0,0 +1,3 @@ +contract C layout at true {} +// ---- +// TypeError 6396: (21-25): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol new file mode 100644 index 000000000000..7c1bfc1e60d2 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol @@ -0,0 +1,30 @@ +contract A layout at block.basefee { } +contract B layout at block.chainid { } +contract C layout at block.number { } +contract D layout at uint160(address(block.coinbase)) { } +contract E layout at block.prevrandao { } +contract F layout at uint(blockhash(0)) { } +contract G layout at msg.value { } +contract H layout at msg.sender { } +contract I layout at msg.data { } +contract J layout at tx.gasprice { } +contract K layout at uint160(tx.origin) { } +contract L layout at address(this).balance { } +contract M layout at uint(address(this).codehash) { } + +// ==== +// EVMVersion: >=paris +// ---- +// TypeError 1139: (21-34): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (60-73): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (99-111): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (137-169): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (195-211): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (237-255): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (281-290): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (316-326): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (352-360): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (386-397): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (423-441): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (467-488): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (514-542): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol new file mode 100644 index 000000000000..f49e6c2dbda2 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol @@ -0,0 +1,3 @@ +contract C layout at bytes("ABCD").length {} +// ---- +// TypeError 1139: (21-41): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol new file mode 100644 index 000000000000..b9cdd9dfaae2 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol @@ -0,0 +1,4 @@ +uint constant N = 100; +contract C layout at N / ~N {} +// ---- +// TypeError 6396: (44-50): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol new file mode 100644 index 000000000000..bb97172d996c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol @@ -0,0 +1,4 @@ +uint constant N = 100; +contract C layout at N / 0 {} +// ---- +// TypeError 6396: (44-49): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol new file mode 100644 index 000000000000..e06deeaaf2dc --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol @@ -0,0 +1,7 @@ +contract A { + uint constant x = 10; +} + +contract C is A layout at A.x { } +// ---- +// TypeError 6396: (68-71): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol new file mode 100644 index 000000000000..e215c26cff3e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol @@ -0,0 +1,4 @@ +contract C layout at 2**256 - 1 { +} +// ---- +// Warning 3495: (11-31): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol new file mode 100644 index 000000000000..89012b781d80 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol @@ -0,0 +1,9 @@ +contract C layout at 2**256 - 1 { + uint transient x; + uint transient y; + uint transient z; +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 3495: (11-31): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_extends_past_storage_end.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_extends_past_storage_end.sol new file mode 100644 index 000000000000..a3efe6d3a0de --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_extends_past_storage_end.sol @@ -0,0 +1,6 @@ +contract C layout at 2**256 - 2 { + uint x; + bool b; +} +// ---- +// TypeError 5015: (21-31): Contract extends past the end of storage when this base slot value is specified. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol new file mode 100644 index 000000000000..c5127249ab68 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol @@ -0,0 +1,2 @@ +contract at layout at 0x1234ABC { } +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol new file mode 100644 index 000000000000..111a4fc365f8 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol @@ -0,0 +1,2 @@ +contract layout layout at 0x1234ABC { } +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_too_large_for_storage.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_too_large_for_storage.sol new file mode 100644 index 000000000000..cfbfd539de28 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_too_large_for_storage.sol @@ -0,0 +1,6 @@ +contract C layout at 1 { + uint[2**256 - 1] x; + uint y; +} +// ---- +// TypeError 7676: (0-62): Contract requires too much storage. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol new file mode 100644 index 000000000000..7e448bba7fd5 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol @@ -0,0 +1,5 @@ +contract C layout at 0x1234 { + uint layout; + function at() public pure { } +} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/delete.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/delete.sol new file mode 100644 index 000000000000..b6926b51ff8f --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/delete.sol @@ -0,0 +1,4 @@ +contract C layout at delete 2 { } +// ---- +// TypeError 4247: (28-29): Expression has to be an lvalue. +// TypeError 9767: (21-29): Built-in unary operator delete cannot be applied to type int_const 2. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/division_by_zero.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/division_by_zero.sol new file mode 100644 index 000000000000..51ddd9d6c4c7 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/division_by_zero.sol @@ -0,0 +1,3 @@ +contract A layout at 1 / 0 {} +// ---- +// TypeError 2271: (21-26): Built-in binary operator / cannot be applied to types int_const 1 and int_const 0. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_definition.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_definition.sol new file mode 100644 index 000000000000..4781b87fabe0 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_definition.sol @@ -0,0 +1,3 @@ +contract C layout at 0x1234 is A, B layout at 0xABC { } +// ---- +// ParserError 8714: (36-42): More than one storage layout definition. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_keyword.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_keyword.sol new file mode 100644 index 000000000000..416ca0f64670 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_keyword.sol @@ -0,0 +1,4 @@ +contract C layout layout at 0x1234ABC { } +// ---- +// ParserError 1994: (18-24): Expected 'at' but got identifier +// ParserError 2314: (28-37): Expected '{' but got 'Number' diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol new file mode 100644 index 000000000000..9a264247c8d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol @@ -0,0 +1,5 @@ +enum Color {Red, Green, Blue} + +contract C layout at Color.Red {} +// ---- +// TypeError 6396: (52-61): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol new file mode 100644 index 000000000000..a3256f2df237 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol @@ -0,0 +1,7 @@ +contract A { + function f() public pure {} +} + +contract C is A layout at this.f.address {} +// ---- +// TypeError 1139: (74-88): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_specified.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_specified.sol new file mode 100644 index 000000000000..7f433dabb253 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_specified.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure layout at 32 { } +} +// ---- +// ParserError 2314: (52-54): Expected '{' but got 'Number' diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_with_no_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_with_no_expression.sol new file mode 100644 index 000000000000..c28596af7d3c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_with_no_expression.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure layout at { } +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol new file mode 100644 index 000000000000..68b2e2460471 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol @@ -0,0 +1,7 @@ +contract A { + function f() external pure {} +} + +contract C layout at A.f { } +// ---- +// TypeError 6396: (71-74): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol new file mode 100644 index 000000000000..98c7b6057abe --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol @@ -0,0 +1,6 @@ +contract A { + function f() public {} +} +contract C is A layout at uint32(this.f.selector) {} +// ---- +// TypeError 6396: (68-91): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol new file mode 100644 index 000000000000..9e63740d89f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol @@ -0,0 +1,3 @@ +contract C layout at 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF {} +// ---- +// TypeError 6396: (21-63): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol new file mode 100644 index 000000000000..194f0df0ea9a --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol @@ -0,0 +1,3 @@ +contract C layout at hex"616263" {} +// ---- +// TypeError 6396: (21-32): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol new file mode 100644 index 000000000000..a803d005f7dd --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol @@ -0,0 +1,3 @@ +contract at layout at uint40(bytes5(hex"0011223344")) { } +// ---- +// TypeError 6396: (22-53): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/increment_operator.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/increment_operator.sol new file mode 100644 index 000000000000..b5d0b0651c64 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/increment_operator.sol @@ -0,0 +1,4 @@ +contract C layout at ++2 { } +// ---- +// TypeError 4247: (23-24): Expression has to be an lvalue. +// TypeError 9767: (21-24): Built-in unary operator ++ cannot be applied to type int_const 2. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol new file mode 100644 index 000000000000..32d6839abd06 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol @@ -0,0 +1,4 @@ +abstract contract A { } + +contract C layout at 42 is A { } +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol new file mode 100644 index 000000000000..c0ac98f57a89 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol @@ -0,0 +1,4 @@ +interface I { } + +contract C layout at 42 is I { } +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_itself.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_itself.sol new file mode 100644 index 000000000000..e0e6625abd7d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_itself.sol @@ -0,0 +1,3 @@ +contract C layout at 42 is C { } +// ---- +// TypeError 2449: (27-28): Definition of base has to precede definition of derived contract diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/interface.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/interface.sol new file mode 100644 index 000000000000..2c853e837cfe --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/interface.sol @@ -0,0 +1,3 @@ +interface I layout at 42 { } +// ---- +// ParserError 2314: (12-18): Expected '{' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol new file mode 100644 index 000000000000..dd298820cd93 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol @@ -0,0 +1,4 @@ +contract A layout at (2**256 + 1) * 2 - 2**256 - 3 {} +contract B layout at (2**2 - 2**3) * (2**5 - 2**8) {} +// ---- +// Warning 3495: (11-51): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol new file mode 100644 index 000000000000..3d60cc38d51a --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol @@ -0,0 +1,7 @@ +contract A layout at 0x1234 {} + +contract B is A {} + +contract C is B layout at 0xABCD {} +// ---- +// TypeError 8894: (46-47): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol new file mode 100644 index 000000000000..a3238257466e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol @@ -0,0 +1,3 @@ +contract C layout at ~0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE {} +// ---- +// TypeError 6753: (21-88): The base slot of the storage layout evaluates to -2**256 + 1, which is outside the range of type uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol new file mode 100644 index 000000000000..1f2e1ecd4eda --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol @@ -0,0 +1,11 @@ +contract A layout at 3/2 {} +contract B layout at 4.2 {} +contract C layout at .1 {} +contract D layout at 42e-10 {} +contract E layout at 1_7e-10 {} +// ---- +// TypeError 1763: (21-24): The base slot of the storage layout must evaluate to an integer. +// TypeError 1763: (49-52): The base slot of the storage layout must evaluate to an integer. +// TypeError 1763: (77-79): The base slot of the storage layout must evaluate to an integer. +// TypeError 1763: (104-110): The base slot of the storage layout must evaluate to an integer. +// TypeError 1763: (135-142): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol new file mode 100644 index 000000000000..fffea1458e87 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol @@ -0,0 +1,2 @@ +contract C layout at 0xffff * (0x123 + 0xABC) { } +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol new file mode 100644 index 000000000000..f0c6a00985ea --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol @@ -0,0 +1,6 @@ +function f() pure returns (uint256) { + return 128; +} +contract C layout at f() { } +// ---- +// TypeError 1139: (77-80): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol new file mode 100644 index 000000000000..6f9b39703afa --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol @@ -0,0 +1,4 @@ +bytes32 constant b = "bytes"; +contract A layout at b[1] {} +// ---- +// TypeError 6396: (51-55): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol new file mode 100644 index 000000000000..8e6d37ad6e1f --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol @@ -0,0 +1,4 @@ +uint constant X = 42; +contract C layout at 0xffff * (50 - X) { } +// ---- +// TypeError 6396: (43-60): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol new file mode 100644 index 000000000000..cfdefa1ed144 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol @@ -0,0 +1,3 @@ +contract C layout at 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF {} +// ---- +// Warning 3495: (11-87): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_no_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_no_expression.sol new file mode 100644 index 000000000000..5123678b6d8a --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_no_expression.sol @@ -0,0 +1,3 @@ +contract C layout at { } +// ---- +// ParserError 6933: (21-22): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol new file mode 100644 index 000000000000..9901af417570 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol @@ -0,0 +1,5 @@ +contract A layout at 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 1 {} +contract B layout at 2**256 {} +// ---- +// TypeError 6753: (21-91): The base slot of the storage layout evaluates to 2**256, which is outside the range of type uint256. +// TypeError 6753: (116-122): The base slot of the storage layout evaluates to 2**256, which is outside the range of type uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol new file mode 100644 index 000000000000..e1f1b0914a9c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol @@ -0,0 +1,5 @@ +contract A layout at 0 - 1 {} +contract B layout at 2**8 - 2**16 {} +// ---- +// TypeError 6753: (21-26): The base slot of the storage layout evaluates to -1, which is outside the range of type uint256. +// TypeError 6753: (51-63): The base slot of the storage layout evaluates to -65280, which is outside the range of type uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol new file mode 100644 index 000000000000..3b1cf05ce321 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol @@ -0,0 +1,13 @@ +==== Source: C ==== +import "M" as M; +import "N" as N; + +contract C is M.A, N.A layout at 0xABCD {} +==== Source: M ==== +contract A layout at 0x1234 {} + +==== Source: N ==== +contract A {} + +// ---- +// TypeError 8894: (C:49-52): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol new file mode 100644 index 000000000000..8b41095fb51d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol @@ -0,0 +1,16 @@ +contract A layout at 1 {} +contract B is A layout at 2 {} + +contract C1 is B {} +contract C2 is A, B {} +contract C3 is B {} + +contract D1 is C1 {} +contract D2 is C2 {} +contract D3 is C3 {} +// ---- +// TypeError 8894: (40-41): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (73-74): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (93-94): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (96-97): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (116-117): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol new file mode 100644 index 000000000000..6c38d15988d7 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol @@ -0,0 +1,12 @@ +library L { + function f(uint x) public pure returns (uint) { + return x * 2; + } +} + + +contract C layout at 2.f() { + using L for *; +} +// ---- +// TypeError 1139: (117-122): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol new file mode 100644 index 000000000000..d341a5a764d2 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol @@ -0,0 +1,3 @@ +contract C layout at uint64(bytes8(bytes.concat("ABCD", "EFGH"))) {} +// ---- +// TypeError 1139: (21-65): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_empty_braces.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_empty_braces.sol new file mode 100644 index 000000000000..96a65ff9844a --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_empty_braces.sol @@ -0,0 +1,3 @@ +contract C layout at { } { } +// ---- +// ParserError 6933: (21-22): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_error.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_error.sol new file mode 100644 index 000000000000..c73dc480d912 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_error.sol @@ -0,0 +1,4 @@ +error MyError(); +contract C layout at MyError() {} +// ---- +// TypeError 7757: (38-47): Errors can only be used with revert statements: "revert MyError(args);", or require functions: "require(condition, MyError(args))". diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_event.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_event.sol new file mode 100644 index 000000000000..7560fb83bbea --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_event.sol @@ -0,0 +1,4 @@ +event MyEvent(); +contract C layout at MyEvent() {} +// ---- +// TypeError 3132: (38-47): Event invocations have to be prefixed by "emit". diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol new file mode 100644 index 000000000000..c7a72f727749 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol @@ -0,0 +1,4 @@ +function f(uint x) returns (uint) { return x + 1; } +contract A layout at f(2) {} +// ---- +// TypeError 1139: (73-77): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol new file mode 100644 index 000000000000..69df5d7752c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol @@ -0,0 +1,6 @@ +contract A layout at 42 {} +contract B is A {} +contract C is B {} +contract D is C {} +// ---- +// TypeError 8894: (41-42): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol new file mode 100644 index 000000000000..e0b1f4e5cb61 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol @@ -0,0 +1,6 @@ +contract A { + function f() external pure returns (uint) {} +} +contract C is A layout at this.f{}() {} +// ---- +// ParserError 7858: (98-99): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol new file mode 100644 index 000000000000..f0b2a2b68b04 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol @@ -0,0 +1,6 @@ +contract A { + function f() external payable returns (uint) {} +} +contract C is A layout at this.f{value:123}() {} +// ---- +// TypeError 1139: (93-112): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol new file mode 100644 index 000000000000..12304ba8a0bd --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol @@ -0,0 +1,5 @@ +interface I {} + +contract C layout at uint(bytes32(type(I).interfaceId)) { } +// ---- +// TypeError 6396: (37-71): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol new file mode 100644 index 000000000000..539a59c11c07 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol @@ -0,0 +1,3 @@ +contract C layout at uint(keccak256(bytes.concat("ABCD"))) {} +// ---- +// TypeError 1139: (21-58): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol new file mode 100644 index 000000000000..d2ac0e931d0d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol @@ -0,0 +1,6 @@ +contract A {} +contract B is A {} +contract C is B layout at 42 {} +contract D is C {} +// ---- +// TypeError 8894: (79-80): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol new file mode 100644 index 000000000000..ee480730434c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol @@ -0,0 +1,9 @@ +==== Source: A ==== +function f() pure {} + +==== Source: B ==== +import "A" as MyModule; + +contract C layout at MyModule {} +// ---- +// TypeError 6396: (B:46-54): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol new file mode 100644 index 000000000000..035e43d24ae4 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol @@ -0,0 +1,4 @@ +contract A {} +contract C layout at A(address(0x1234)) {} +// ---- +// TypeError 6396: (35-53): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol new file mode 100644 index 000000000000..4d48e410f881 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol @@ -0,0 +1,3 @@ +contract A layout at uint {} +// ---- +// TypeError 6396: (21-25): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_statement_without_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_statement_without_at.sol new file mode 100644 index 000000000000..b60654629fa4 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_statement_without_at.sol @@ -0,0 +1,4 @@ +contract C layout { } +// ---- +// ParserError 1994: (18-19): Expected 'at' but got '{' +// ParserError 6933: (20-21): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol new file mode 100644 index 000000000000..13e094631c23 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol @@ -0,0 +1,5 @@ +contract A { } +contract B { } +contract C is A, B layout at 0x1234 { } +contract D layout at 0xABCD is A, B { } +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/library.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/library.sol new file mode 100644 index 000000000000..2848a7c7ef1d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/library.sol @@ -0,0 +1,3 @@ +library L layout at 42 { } +// ---- +// ParserError 2314: (10-16): Expected '{' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol new file mode 100644 index 000000000000..0f682d779b0b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol @@ -0,0 +1,3 @@ +contract at layout at uint(42) { } +// ---- +// TypeError 6396: (22-30): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol new file mode 100644 index 000000000000..a5876ab6e632 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol @@ -0,0 +1,4 @@ +contract A layout at 42_0e10 {} +contract B layout at 0x1234_ABCD {} +contract C layout at 1234_000 {} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol new file mode 100644 index 000000000000..0558e28db9b6 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol @@ -0,0 +1,11 @@ +contract A layout at this {} +contract B layout at super {} +contract C layout at msg {} +contract D layout at tx {} +contract E layout at block {} +// ---- +// TypeError 1139: (21-25): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (50-55): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (80-83): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (108-110): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (135-140): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol new file mode 100644 index 000000000000..a9b5abef18b3 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol @@ -0,0 +1,3 @@ +contract C layout at 5 minutes { } +contract D layout at 2 gwei { } +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/natspec.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/natspec.sol new file mode 100644 index 000000000000..d1712a1ff10a --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/natspec.sol @@ -0,0 +1,10 @@ +contract C layout at + /** + @notice function f should return the value of the base slot for the contract's storage layout + @dev the value returned by f should be in the range of uint256 + */ + f() +{ } +// ==== +// stopAfter: parsing +// ---- \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol new file mode 100644 index 000000000000..9e3111f880c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol @@ -0,0 +1,3 @@ +contract A layout at -1 {} +// ---- +// TypeError 6753: (21-23): The base slot of the storage layout evaluates to -1, which is outside the range of type uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol new file mode 100644 index 000000000000..c87a98eaa919 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol @@ -0,0 +1,5 @@ +contract A layout at addmod(1, 2, 3) {} +contract B layout at mulmod(3, 2, 1) {} +// ---- +// TypeError 6396: (21-36): The base slot of the storage layout must evaluate to a rational number. +// TypeError 6396: (61-76): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol new file mode 100644 index 000000000000..e21521e39a97 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol @@ -0,0 +1,3 @@ +contract A layout at 42.0 {} +contract B layout at 2.5e10 {} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/repeated_layout_definition.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/repeated_layout_definition.sol new file mode 100644 index 000000000000..7176940306fa --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/repeated_layout_definition.sol @@ -0,0 +1,5 @@ +contract C layout at 0x1234 layout at 0xABC layout at 0x4321 layout at 0xCBA { } +// ---- +// ParserError 8714: (28-34): More than one storage layout definition. +// ParserError 8714: (44-50): More than one storage layout definition. +// ParserError 8714: (61-67): More than one storage layout definition. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol new file mode 100644 index 000000000000..58fb725d7590 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol @@ -0,0 +1,4 @@ +contract A {} +contract B is A layout at 64 {} +contract C is A layout at 42 {} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol new file mode 100644 index 000000000000..024f5a95f941 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol @@ -0,0 +1,4 @@ +contract A layout at 0x1234 {} +contract B layout at 1024 {} +contract C layout at 0 {} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol new file mode 100644 index 000000000000..92c0b1147ea4 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol @@ -0,0 +1,7 @@ +contract A { + uint public x = 10; +} + +contract C is A layout at A.x {} +// ---- +// TypeError 1139: (66-69): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol new file mode 100644 index 000000000000..70e3e441956e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol @@ -0,0 +1,7 @@ +contract A { + uint public x = 10; +} + +contract C is A layout at this.x() {} +// ---- +// TypeError 1139: (66-74): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_layout_specifier.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_layout_specifier.sol new file mode 100644 index 000000000000..0f7279fcd267 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_layout_specifier.sol @@ -0,0 +1,5 @@ +contract C { + uint x layout at 0xF; +} +// ---- +// ParserError 2314: (24-30): Expected ';' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol new file mode 100644 index 000000000000..3b8292fe8cbd --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol @@ -0,0 +1,3 @@ +contract C layout at "MyLayoutBase" {} +// ---- +// TypeError 6396: (21-35): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol new file mode 100644 index 000000000000..bb1bcc0e13ba --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol @@ -0,0 +1,11 @@ +contract A { + struct SA { + uint x; + uint y; + bytes32 b; + } +} + +contract C is A layout at A.SA { } +// ---- +// TypeError 1139: (115-119): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_with_layout_specifier.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_with_layout_specifier.sol new file mode 100644 index 000000000000..fa05d1276375 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_with_layout_specifier.sol @@ -0,0 +1,3 @@ +struct S layout at 23 { } +// ---- +// ParserError 2314: (9-15): Expected '{' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol new file mode 100644 index 000000000000..f426104cc2cb --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol @@ -0,0 +1,5 @@ +contract A layout at true ? 42 : 94 {} +contract B layout at 255 + (true ? 1 : 0) {} +// ---- +// TypeError 6396: (21-35): The base slot of the storage layout must evaluate to a rational number. +// TypeError 6396: (60-80): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol new file mode 100644 index 000000000000..eb4693e488d1 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol @@ -0,0 +1,3 @@ +contract C layout at (1, 2, 3) {} +// ---- +// TypeError 6396: (21-30): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol new file mode 100644 index 000000000000..dd8ee6f9cc27 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol @@ -0,0 +1,3 @@ +contract at layout at type(uint).max { } +// ---- +// TypeError 6396: (22-36): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol new file mode 100644 index 000000000000..14259fd3d65d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol @@ -0,0 +1,10 @@ +type MyUint is uint; + +using {add as +} for MyUint global; +function add(MyUint a, MyUint b) pure returns (MyUint) { + return MyUint.wrap(2); +} + +contract C layout at MyUint.wrap(1) + MyUint.wrap(2) {} +// ---- +// TypeError 1139: (166-197): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol new file mode 100644 index 000000000000..98036416880a --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol @@ -0,0 +1,5 @@ +type MyUint is uint128; +MyUint constant x = MyUint.wrap(42); +contract C layout at x {} +// ---- +// TypeError 6396: (82-83): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol new file mode 100644 index 000000000000..b45ee88dd98d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol @@ -0,0 +1,5 @@ +type MyUint is uint128; +MyUint constant x = MyUint.wrap(42); +contract C layout at MyUint.unwrap(x) {} +// ---- +// TypeError 6396: (82-98): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol new file mode 100644 index 000000000000..172fb58ab12c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol @@ -0,0 +1,4 @@ +type MyUint is uint128; +contract C layout at MyUint.wrap(42) {} +// ---- +// TypeError 6396: (45-60): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol new file mode 100644 index 000000000000..bb56de728944 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol @@ -0,0 +1,5 @@ +contract A layout at [1, 2, 3][0] {} +contract B layout at 255 + [1, 2, 3][0] {} +// ---- +// TypeError 6396: (21-33): The base slot of the storage layout must evaluate to a rational number. +// TypeError 6396: (58-76): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol new file mode 100644 index 000000000000..1f08fa0ec9ee --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol @@ -0,0 +1,4 @@ +bytes32 constant b = "Solidity"; +contract C layout at uint8(b[1]) {} +// ---- +// TypeError 6396: (54-65): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol new file mode 100644 index 000000000000..5d1f777fd3c0 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol @@ -0,0 +1,8 @@ +contract A layout at 2**256 - 2**64 {} +contract C layout at 2**256 - 2**65 { + uint[2**63] x; + uint[2**63] y; +} +// ---- +// Warning 3495: (11-35): This contract is very close to the end of storage. This limits its future upgradability. +// Warning 3495: (50-74): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/empty_struct.sol b/test/libsolidity/syntaxTests/structs/empty_struct.sol similarity index 100% rename from test/libsolidity/syntaxTests/empty_struct.sol rename to test/libsolidity/syntaxTests/structs/empty_struct.sol diff --git a/test/libsolidity/syntaxTests/unimplemented_super_function.sol b/test/libsolidity/syntaxTests/super/unimplemented_super_function.sol similarity index 100% rename from test/libsolidity/syntaxTests/unimplemented_super_function.sol rename to test/libsolidity/syntaxTests/super/unimplemented_super_function.sol diff --git a/test/libsolidity/syntaxTests/unimplemented_super_function_derived.sol b/test/libsolidity/syntaxTests/super/unimplemented_super_function_derived.sol similarity index 100% rename from test/libsolidity/syntaxTests/unimplemented_super_function_derived.sol rename to test/libsolidity/syntaxTests/super/unimplemented_super_function_derived.sol diff --git a/test/libsolidity/syntaxTests/types/address/address_members.sol b/test/libsolidity/syntaxTests/types/address/address_members.sol index 144361b9409a..9299b65d523c 100644 --- a/test/libsolidity/syntaxTests/types/address/address_members.sol +++ b/test/libsolidity/syntaxTests/types/address/address_members.sol @@ -5,4 +5,6 @@ contract C { function i() public view returns (uint) { return f().code.length; } function j() public view returns (uint) { return h().length; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol b/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol index 754ff2c67488..449b628d4491 100644 --- a/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol +++ b/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol @@ -3,5 +3,7 @@ contract C { selfdestruct(a); } } +// ==== +// bytecodeFormat: legacy // ---- // Warning 5159: (64-76): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. diff --git a/test/libsolidity/syntaxTests/types/address/codehash.sol b/test/libsolidity/syntaxTests/types/address/codehash.sol index cf7eaabec976..00956d97e848 100644 --- a/test/libsolidity/syntaxTests/types/address/codehash.sol +++ b/test/libsolidity/syntaxTests/types/address/codehash.sol @@ -5,4 +5,5 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/types/address/eof/address_members.sol b/test/libsolidity/syntaxTests/types/address/eof/address_members.sol new file mode 100644 index 000000000000..a1b21de2cea0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/eof/address_members.sol @@ -0,0 +1,9 @@ +contract C { + function f() public view returns (address) { return address(this); } + function g() public view returns (uint) { return f().balance; } + function h() public pure returns (bytes memory) { return msg.data; } + function j() public pure returns (uint) { return h().length; } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libsolidity/syntaxTests/types/function_types/function_definition_expression.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_definition_expression.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_definition_expression.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_definition_expression.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_parameter_return_types_fail.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_parameter_return_types_fail.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_parameter_return_types_success.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_parameter_return_types_success.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_state_mutability_fail.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_state_mutability_fail.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_state_mutability_success.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_state_mutability_success.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/function_selector_pure.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/function_selector_pure.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/function_selector_pure.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/function_selector_pure.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/local_variable_selector_not_pure.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/local_variable_selector_not_pure.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/local_variable_selector_not_pure.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/local_variable_selector_not_pure.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_contract_name.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_contract_name.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_contract_name.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_contract_name.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_not_pure.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_not_pure.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_not_pure.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_not_pure.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_super.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_super.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_super.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_super.sol diff --git a/test/libsolidity/syntaxTests/types/mapping/abstract_contructor_param.sol b/test/libsolidity/syntaxTests/types/mapping/abstract_constructor_param.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/mapping/abstract_contructor_param.sol rename to test/libsolidity/syntaxTests/types/mapping/abstract_constructor_param.sol diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recursive_data_location_memory.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol rename to test/libsolidity/syntaxTests/types/mapping/mapping_struct_recursive_data_location_memory.sol diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol index a93555fd7120..f76fa84308a9 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol @@ -12,5 +12,7 @@ contract C { a; b; c; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (66-84): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_paramter_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_parameter_err.sol similarity index 100% rename from test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_paramter_err.sol rename to test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_parameter_err.sol diff --git a/test/libsolidity/syntaxTests/viewPureChecker/address_constantinople.sol b/test/libsolidity/syntaxTests/viewPureChecker/address_constantinople.sol index 4387ca60a75b..e8ee980bf5ac 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/address_constantinople.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/address_constantinople.sol @@ -8,4 +8,5 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol index cc8ac5e8341b..9097a166c118 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol @@ -27,4 +27,6 @@ contract C { assembly { pop(extcodesize(0)) } } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly_constantinople.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly_constantinople.sol index ed0b20d53793..16f57b2e8091 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly_constantinople.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/assembly_constantinople.sol @@ -5,4 +5,5 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol index 4d1710a3a160..8f275321382a 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol @@ -18,5 +18,7 @@ contract C { } receive() payable external {} } +// ==== +// bytecodeFormat: legacy // ---- // Warning 5159: (122-134): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/call_options_without_call.sol b/test/libsolidity/syntaxTests/viewPureChecker/call_options_without_call.sol new file mode 100644 index 000000000000..ea4d20297bb9 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/call_options_without_call.sol @@ -0,0 +1,9 @@ +contract C { + function f() external payable {} + function g(address a) external pure { + a.call{value: 42}; + } + function h() external view { + this.f{value: 42}; + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/assembly.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/assembly.sol new file mode 100644 index 000000000000..fad9b7c1fa27 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/assembly.sol @@ -0,0 +1,29 @@ +contract C { + struct S { uint x; } + S s; + function e() pure public { + assembly { mstore(keccak256(0, 20), mul(s.slot, 2)) } + } + function f() pure public { + uint x; + assembly { x := 7 } + } + function g() view public { + assembly { for {} 1 { pop(sload(0)) } { } pop(calldataload(0)) } + } + function h() view public { + assembly { function g() { pop(blockhash(20)) } } + } + function i() public { + assembly { pop(extcall(0, 1, 2, 3)) } + } + function k() public view { + assembly { pop(balance(0)) } + } + function l() public pure { + assembly { pop(calldataload(0)) } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol new file mode 100644 index 000000000000..91ea709fe2a6 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol @@ -0,0 +1,22 @@ +contract C { + function f() public { + payable(this).transfer(1); + require(payable(this).send(2)); + (bool success,) = address(this).delegatecall(""); + require(success); + (success,) = address(this).call(""); + require(success); + } + function g() pure public { + bytes32 x = keccak256("abc"); + bytes32 y = sha256("abc"); + address z = ecrecover(bytes32(uint256(1)), uint8(2), bytes32(uint256(3)), bytes32(uint256(4))); + require(true); + assert(true); + x; y; z; + } + receive() payable external {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed.sol new file mode 100644 index 000000000000..81d0f4e565b5 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed.sol @@ -0,0 +1,86 @@ +contract C { + function f() public { + assembly { + stop() + pop(add(0, 1)) + pop(sub(0, 1)) + pop(mul(0, 1)) + pop(div(0, 1)) + pop(sdiv(0, 1)) + pop(mod(0, 1)) + pop(smod(0, 1)) + pop(exp(0, 1)) + pop(not(0)) + pop(lt(0, 1)) + pop(gt(0, 1)) + pop(slt(0, 1)) + pop(sgt(0, 1)) + pop(eq(0, 1)) + pop(iszero(0)) + pop(and(0, 1)) + pop(or(0, 1)) + pop(xor(0, 1)) + pop(byte(0, 1)) + pop(shl(0, 1)) + pop(shr(0, 1)) + pop(sar(0, 1)) + pop(addmod(0, 1, 2)) + pop(mulmod(0, 1, 2)) + pop(signextend(0, 1)) + pop(keccak256(0, 1)) + pop(0) + pop(mload(0)) + mstore(0, 1) + mstore8(0, 1) + pop(sload(0)) + sstore(0, 1) + pop(address()) + pop(balance(0)) + pop(selfbalance()) + pop(caller()) + pop(callvalue()) + pop(calldataload(0)) + pop(calldatasize()) + calldatacopy(0, 1, 2) + pop(returndatasize()) + returndatacopy(0, 1, 2) + pop(extcall(0, 1, 2, 3)) + pop(extdelegatecall(0, 1, 2)) + pop(extstaticcall(0, 1, 2)) + return(0, 1) + revert(0, 1) + invalid() + log0(0, 1) + log1(0, 1, 2) + log2(0, 1, 2, 3) + log3(0, 1, 2, 3, 4) + log4(0, 1, 2, 3, 4, 5) + pop(chainid()) + pop(basefee()) + pop(origin()) + pop(gasprice()) + pop(blockhash(0)) + pop(coinbase()) + pop(timestamp()) + pop(number()) + pop(prevrandao()) + + mcopy(1, 2, 3) + pop(blobhash(0)) + pop(blobbasefee()) + pop(tload(0)) + tstore(0, 0) + + // NOTE: msize() is allowed only with optimizer disabled + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Warning 2394: (1970-1976): Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. +// Warning 5740: (89-1400): Unreachable code. +// Warning 5740: (1413-1425): Unreachable code. +// Warning 5740: (1438-1447): Unreachable code. +// Warning 5740: (1460-1982): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_pure.sol new file mode 100644 index 000000000000..f3da4722ff7d --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_pure.sol @@ -0,0 +1,85 @@ +contract C { + function f() public pure { + assembly { + stop() + pop(add(0, 1)) + pop(sub(0, 1)) + pop(mul(0, 1)) + pop(div(0, 1)) + pop(sdiv(0, 1)) + pop(mod(0, 1)) + pop(smod(0, 1)) + pop(exp(0, 1)) + pop(not(0)) + pop(lt(0, 1)) + pop(gt(0, 1)) + pop(slt(0, 1)) + pop(sgt(0, 1)) + pop(eq(0, 1)) + pop(iszero(0)) + pop(and(0, 1)) + pop(or(0, 1)) + pop(xor(0, 1)) + pop(byte(0, 1)) + pop(shl(0, 1)) + pop(shr(0, 1)) + pop(sar(0, 1)) + pop(addmod(0, 1, 2)) + pop(mulmod(0, 1, 2)) + pop(signextend(0, 1)) + pop(keccak256(0, 1)) + pop(0) + pop(mload(0)) + mstore(0, 1) + mstore8(0, 1) + //pop(sload(0)) + //sstore(0, 1) + //pop(address()) + //pop(balance(0)) + //pop(selfbalance()) + //pop(caller()) + //pop(callvalue()) + pop(calldataload(0)) + pop(calldatasize()) + calldatacopy(0, 1, 2) + pop(returndatasize()) + returndatacopy(0, 1, 2) + //pop(extcall(0, 1, 2, 3)) + //pop(extdelegatecall(0, 1, 2)) + //pop(extstaticcall(0, 1, 2)) + return(0, 1) + revert(0, 1) + invalid() + //log0(0, 1) + //log1(0, 1, 2) + //log2(0, 1, 2, 3) + //log3(0, 1, 2, 3, 4) + //log4(0, 1, 2, 3, 4, 5) + //pop(chainid()) + //pop(basefee()) + //pop(origin()) + //pop(gasprice()) + //pop(blockhash(0)) + //pop(coinbase()) + //pop(timestamp()) + //pop(number()) + //pop(prevrandao()) + //pop(gaslimit()) + mcopy(1, 2, 3) + //pop(blobhash(0)) + //pop(blobbasefee()) + //pop(tload(0)) + //tstore(0, 1) + + // NOTE: msize() is allowed only with optimizer disabled + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Warning 5740: (94-1425): Unreachable code. +// Warning 5740: (1438-1450): Unreachable code. +// Warning 5740: (1463-1472): Unreachable code. +// Warning 5740: (1939-1953): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_view.sol new file mode 100644 index 000000000000..d1a5be03601e --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_view.sol @@ -0,0 +1,85 @@ +contract C { + function f() public view { + assembly { + stop() + pop(add(0, 1)) + pop(sub(0, 1)) + pop(mul(0, 1)) + pop(div(0, 1)) + pop(sdiv(0, 1)) + pop(mod(0, 1)) + pop(smod(0, 1)) + pop(exp(0, 1)) + pop(not(0)) + pop(lt(0, 1)) + pop(gt(0, 1)) + pop(slt(0, 1)) + pop(sgt(0, 1)) + pop(eq(0, 1)) + pop(iszero(0)) + pop(and(0, 1)) + pop(or(0, 1)) + pop(xor(0, 1)) + pop(byte(0, 1)) + pop(shl(0, 1)) + pop(shr(0, 1)) + pop(sar(0, 1)) + pop(addmod(0, 1, 2)) + pop(mulmod(0, 1, 2)) + pop(signextend(0, 1)) + pop(keccak256(0, 1)) + pop(0) + pop(mload(0)) + mstore(0, 1) + mstore8(0, 1) + pop(sload(0)) + //sstore(0, 1) + pop(address()) + pop(balance(0)) + pop(selfbalance()) + pop(caller()) + pop(callvalue()) + pop(calldataload(0)) + pop(calldatasize()) + calldatacopy(0, 1, 2) + pop(returndatasize()) + returndatacopy(0, 1, 2) + //pop(extcall(0, 1, 2, 3)) + //pop(extdelegatecall(0, 1, 2)) + pop(extstaticcall(0, 1, 2)) + return(0, 1) + revert(0, 1) + invalid() + //log0(0, 1) + //log1(0, 1, 2) + //log2(0, 1, 2, 3) + //log3(0, 1, 2, 3, 4) + //log4(0, 1, 2, 3, 4, 5) + pop(chainid()) + pop(basefee()) + pop(origin()) + pop(gasprice()) + pop(blockhash(0)) + pop(coinbase()) + pop(timestamp()) + pop(number()) + pop(prevrandao()) + pop(gaslimit()) + mcopy(1, 2, 3) + pop(blobhash(0)) + pop(blobbasefee()) + pop(tload(0)) + //tstore(0, 1) + + // NOTE: msize() is allowed only with optimizer disabled + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Warning 5740: (94-1411): Unreachable code. +// Warning 5740: (1424-1436): Unreachable code. +// Warning 5740: (1449-1458): Unreachable code. +// Warning 5740: (1626-2005): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed.sol new file mode 100644 index 000000000000..e65ea26bd97e --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed.sol @@ -0,0 +1,28 @@ +// TODO: eofcreate, returncontract and auxdataloadn are for now disallowed in inline assembly. They need proper design on language level +contract C { + function f() public { + assembly { + linkersymbol("x") + memoryguard(0) + verbatim_1i_1o(hex"600202", 0) + + pop(eofcreate("a", 0, 0, 0, 0)) + returncontract("a", 0, 0, 0) + pop(auxdataloadn(0)) + + pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// SyntaxError 6553: (184-449): The msize instruction cannot be used when the Yul optimizer is activated because it can change its semantics. Either disable the Yul optimizer or do not use the instruction. +// DeclarationError 4619: (207-219): Function "linkersymbol" not found. +// DeclarationError 4619: (237-248): Function "memoryguard" not found. +// DeclarationError 4619: (264-278): Function "verbatim_1i_1o" not found. +// DeclarationError 4619: (312-321): Function "eofcreate" not found. +// TypeError 3950: (312-338): Expected expression to evaluate to one value, but got 0 values instead. +// DeclarationError 4619: (352-366): Function "returncontract" not found. +// DeclarationError 4619: (397-409): Function "auxdataloadn" not found. +// TypeError 3950: (397-412): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_pure.sol new file mode 100644 index 000000000000..19342ec194c4 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_pure.sol @@ -0,0 +1,71 @@ +contract C { + function f() public pure { + assembly { + pop(sload(0)) + sstore(0, 1) + pop(address()) + pop(balance(0)) + pop(caller()) + pop(callvalue()) + pop(extcall(0, 1, 2, 3)) + pop(extstaticcall(0, 1, 2)) + pop(extdelegatecall(0, 1, 2)) + log0(0, 1) + log1(0, 1, 2) + log2(0, 1, 2, 3) + log3(0, 1, 2, 3, 4) + log4(0, 1, 2, 3, 4, 5) + pop(origin()) + pop(gasprice()) + pop(blockhash(0)) + pop(coinbase()) + pop(timestamp()) + pop(number()) + pop(gaslimit()) + pop(blobhash(0)) + pop(blobbasefee()) + pop(tload(0)) + tstore(0, 0) + pop(selfbalance()) + pop(chainid()) + pop(basefee()) + pop(prevrandao()) + + // This one is disallowed too but the error suppresses other errors. + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Warning 2394: (781-787): Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. +// TypeError 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (101-113): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (130-139): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (157-167): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (185-193): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (211-222): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (240-259): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (277-299): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (317-341): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (355-365): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (378-391): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (404-420): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (433-452): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (465-487): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (504-512): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (530-540): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (558-570): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (588-598): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (616-627): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (645-653): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (671-681): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (699-710): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (728-741): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (759-767): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (781-793): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (810-823): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (841-850): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (868-877): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (895-907): 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/eof/inline_assembly_instructions_disallowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_view.sol new file mode 100644 index 000000000000..f8e9bc3ef136 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_view.sol @@ -0,0 +1,28 @@ +contract C { + function f() public view { + assembly { + sstore(0, 1) + pop(extcall(0, 1, 2, 3)) + pop(extdelegatecall(0, 1, 2)) + log0(0, 1) + log1(0, 1, 2) + log2(0, 1, 2, 3) + log3(0, 1, 2, 3, 4) + log4(0, 1, 2, 3, 4, 5) + + // This one is disallowed too but the error suppresses other errors. + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 8961: (75-87): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (104-123): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (141-165): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (179-189): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (202-215): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (228-244): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (257-276): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (289-311): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/gas_value_without_call.sol b/test/libsolidity/syntaxTests/viewPureChecker/gas_value_without_call.sol index 41120bf08111..f0bfba70ce31 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/gas_value_without_call.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/gas_value_without_call.sol @@ -11,4 +11,6 @@ contract C { this.f{gas: 42}; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol b/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol index 65030cb30729..77956ffac02a 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol @@ -7,6 +7,8 @@ contract C { this.h{gas: 42}(); } } +// ==== +// bytecodeFormat: legacy // ---- // 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/inline_assembly_instructions_allowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol index 886d6de0ce2f..680a8f85f2f7 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol @@ -84,6 +84,7 @@ contract C { } // ==== // EVMVersion: >=paris +// bytecodeFormat: legacy // ---- // Warning 1699: (1754-1766): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. // Warning 5740: (89-1716): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol index 16c75d6f7291..5268f7a98e0b 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol @@ -83,6 +83,7 @@ contract C { } // ==== // EVMVersion: >=london +// bytecodeFormat: legacy // ---- // Warning 5740: (94-1755): Unreachable code. // Warning 5740: (1768-1780): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol index 0bb92c1fd2fa..e2fa70102dfa 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol @@ -84,6 +84,7 @@ contract C { } // ==== // EVMVersion: >=paris +// bytecodeFormat: legacy // ---- // Warning 5740: (94-1733): Unreachable code. // Warning 5740: (1746-1758): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed.sol index 992a51ad2a28..ff557e6865f7 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed.sol @@ -15,6 +15,8 @@ contract C { } } } +// ==== +// bytecodeFormat: legacy // ---- // SyntaxError 6553: (47-362): The msize instruction cannot be used when the Yul optimizer is activated because it can change its semantics. Either disable the Yul optimizer or do not use the instruction. // DeclarationError 4619: (70-78): Function "datasize" not found. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol index 665a17eebf63..91be09f58f22 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol @@ -34,6 +34,8 @@ contract C { } } } +// ==== +// bytecodeFormat: legacy // ---- // Warning 1699: (498-510): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. // Warning 5740: (526-853): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol index f0320d8b0835..ded86c88a9a3 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol @@ -7,5 +7,6 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // TypeError 2527: (79-107): 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/inline_assembly_instructions_disallowed_pure_constantinople.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol index 30210efc32fa..47826724e8e6 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol @@ -8,6 +8,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // TypeError 2527: (79-93): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". // TypeError 8961: (111-130): Function cannot be declared as pure because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol index b2f241ff08c5..e2bf4c5d1f4b 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol @@ -22,6 +22,7 @@ contract C { } // ==== // EVMVersion: >=london +// bytecodeFormat: legacy // ---- // Warning 1699: (308-320): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. // Warning 5740: (336-468): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/staticcall_gas_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/staticcall_gas_view.sol index f49327a92114..832f60f97b56 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/staticcall_gas_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/staticcall_gas_view.sol @@ -8,4 +8,5 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/util/ContractABIUtils.h b/test/libsolidity/util/ContractABIUtils.h index 3f0b1b04e283..ec41956ae32e 100644 --- a/test/libsolidity/util/ContractABIUtils.h +++ b/test/libsolidity/util/ContractABIUtils.h @@ -72,7 +72,7 @@ class ContractABIUtils /// Calculates the encoding size of given _parameters based /// on the size of their types. - static size_t encodingSize(ParameterList const& _paremeters); + static size_t encodingSize(ParameterList const& _parameters); private: /// Parses and translates a single type and returns a list of diff --git a/test/libsolidity/util/SoltestTypes.h b/test/libsolidity/util/SoltestTypes.h index 791cea011610..4db9bc43b257 100644 --- a/test/libsolidity/util/SoltestTypes.h +++ b/test/libsolidity/util/SoltestTypes.h @@ -32,7 +32,7 @@ namespace solidity::frontend::test T(Invalid, "invalid", 0) \ T(EOS, "EOS", 0) \ T(Whitespace, "_", 0) \ - /* punctuations */ \ + /* punctuation */ \ T(LParen, "(", 0) \ T(RParen, ")", 0) \ T(LBrack, "[", 0) \ diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 6562e1743588..a9f4c59a74ac 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -21,6 +21,8 @@ #include +#include + #include #include @@ -30,76 +32,69 @@ #include #include +#include + #include #include #include +#include #include #include using namespace solidity; +using namespace solidity::frontend; using namespace solidity::yul; using namespace solidity::langutil; +using namespace solidity::util; +using namespace solidity::test; -namespace -{ -Dialect const& defaultDialect() -{ - return yul::EVMDialect::strictAssemblyForEVM( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); -} -} - -std::pair, std::shared_ptr> yul::test::parse(std::string const& _source) -{ - YulStack stack( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, - solidity::test::CommonOptions::get().optimize ? - solidity::frontend::OptimiserSettings::standard() : - solidity::frontend::OptimiserSettings::minimal(), - DebugInfoSelection::All() - ); - if (!stack.parseAndAnalyze("", _source) || Error::hasErrorsWarningsOrInfos(stack.errors())) - BOOST_FAIL("Invalid source."); - return std::make_pair(stack.parserResult()->code(), stack.parserResult()->analysisInfo); -} - -std::pair, std::shared_ptr> yul::test::parse( +YulStack yul::test::parseYul( std::string const& _source, - Dialect const& _dialect, - ErrorList& _errors + std::string _sourceUnitName, + std::optional _optimiserSettings ) { - ErrorReporter errorReporter(_errors); - CharStream stream(_source, ""); - std::shared_ptr scanner = std::make_shared(stream); - std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _dialect).parse(scanner, false); - if (!parserResult) - return {}; - if (!parserResult->hasCode() || errorReporter.hasErrors()) - return {}; - std::shared_ptr analysisInfo = std::make_shared(); - AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->qualifiedDataNames()); - // TODO this should be done recursively. - if (!analyzer.analyze(parserResult->code()->root()) || errorReporter.hasErrors()) - return {}; - return {std::move(parserResult), std::move(analysisInfo)}; + YulStack yulStack( + CommonOptions::get().evmVersion(), + CommonOptions::get().eofVersion(), + YulStack::Language::StrictAssembly, + _optimiserSettings.has_value() ? + *_optimiserSettings : + (CommonOptions::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal()), + DebugInfoSelection::AllExceptExperimental() + ); + bool successful = yulStack.parseAndAnalyze(_sourceUnitName, _source); + if (!successful) + soltestAssert(yulStack.hasErrors()); + else + { + soltestAssert(!yulStack.hasErrors()); + soltestAssert(yulStack.parserResult()); + soltestAssert(yulStack.parserResult()->code()); + soltestAssert(yulStack.parserResult()->analysisInfo); + } + return yulStack; } yul::Block yul::test::disambiguate(std::string const& _source) { - auto result = parse(_source); - return std::get(Disambiguator(defaultDialect(), *result.second, {})(result.first->root())); + YulStack yulStack = parseYul(_source); + soltestAssert(!yulStack.hasErrorsWarningsOrInfos()); + return std::get(Disambiguator( + yulStack.dialect(), + *yulStack.parserResult()->analysisInfo, + {} + )(yulStack.parserResult()->code()->root())); } std::string yul::test::format(std::string const& _source) { - return yul::AsmPrinter()(parse(_source).first->root()); + YulStack yulStack = parseYul(_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Subobjects not supported."); + soltestAssert(!yulStack.hasErrorsWarningsOrInfos()); + return AsmPrinter::format(*yulStack.parserResult()->code()); } namespace @@ -134,3 +129,18 @@ yul::Dialect const& yul::test::dialect(std::string const& _name, langutil::EVMVe return validDialects.at(_name)(_evmVersion, _eofVersion); } + +void yul::test::printYulErrors( + YulStack const& _yulStack, + std::ostream& _stream, + std::string const& _linePrefix, + bool const _formatted +) +{ + AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) + << _linePrefix + << "Error parsing source." + << std::endl; + SourceReferenceFormatter formatter{_stream, _yulStack, true, false}; + formatter.printErrorInformation(_yulStack.errors()); +} diff --git a/test/libyul/Common.h b/test/libyul/Common.h index 2255272b6b5e..de402c29a9da 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -21,11 +21,14 @@ #pragma once +#include + #include #include #include #include +#include namespace solidity::langutil { @@ -37,23 +40,31 @@ namespace solidity::yul { struct AsmAnalysisInfo; struct Block; -struct Object; -struct Dialect; +class Object; +class Dialect; class AST; +class YulStack; } namespace solidity::yul::test { -std::pair, std::shared_ptr> -parse(std::string const& _source); - -std::pair, std::shared_ptr> -parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors); +yul::YulStack parseYul( + std::string const& _source, + std::string _sourceUnitName = "", + std::optional _optimiserSettings = std::nullopt +); Block disambiguate(std::string const& _source); std::string format(std::string const& _source); solidity::yul::Dialect const& dialect(std::string const& _name, langutil::EVMVersion _evmVersion, std::optional _eofVersion); +void printYulErrors( + yul::YulStack const& _yulStack, + std::ostream& _stream, + std::string const& _linePrefix, + bool const _formatted +); + } diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 6c86ac21f32f..a030af487eb1 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -20,10 +20,12 @@ #include +#include + #include -#include #include +#include #include @@ -34,15 +36,11 @@ namespace { std::string check(std::string const& _input) { - Object obj; - auto parsingResult = yul::test::parse(_input); - obj.setCode(parsingResult.first, parsingResult.second); - BOOST_REQUIRE(obj.hasCode()); - auto functions = CompilabilityChecker( - EVMDialect::strictAssemblyForEVM( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ), obj, true).stackDeficit; + YulStack yulStack = parseYul(_input); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + soltestAssert(!yulStack.hasErrorsWarningsOrInfos()); + + auto functions = CompilabilityChecker(*yulStack.parserResult(), true).stackDeficit; std::string out; for (auto const& function: functions) out += function.first.str() + ": " + std::to_string(function.second) + " "; diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index b7264bc0e96d..c0ab37956e4c 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -24,8 +24,8 @@ #include #include #include +#include -#include #include #ifdef ISOLTEST @@ -41,15 +41,11 @@ using namespace solidity::frontend; using namespace solidity::frontend::test; ControlFlowGraphTest::ControlFlowGraphTest(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now m_expectation = m_reader.simpleExpectations(); } @@ -64,8 +60,9 @@ static std::string variableSlotToString(VariableSlot const& _slot) class ControlFlowGraphPrinter { public: - ControlFlowGraphPrinter(std::ostream& _stream): - m_stream(_stream) + ControlFlowGraphPrinter(std::ostream& _stream, Dialect const& _dialect): + m_stream(_stream), + m_dialect(_dialect) { } void operator()(CFG::BasicBlock const& _block, bool _isMainEntry = true) @@ -133,7 +130,7 @@ class ControlFlowGraphPrinter m_stream << _call.function.get().name.str() << ": "; }, [&](CFG::BuiltinCall const& _call) { - m_stream << _call.functionCall.get().functionName.name.str() << ": "; + m_stream << _call.builtin.get().name << ": "; }, [&](CFG::Assignment const& _assignment) { m_stream << "Assignment("; @@ -141,7 +138,7 @@ class ControlFlowGraphPrinter m_stream << "): "; } }, operation.operation); - m_stream << stackToString(operation.input) << " => " << stackToString(operation.output) << "\\l\\\n"; + m_stream << stackToString(operation.input, m_dialect) << " => " << stackToString(operation.output, m_dialect) << "\\l\\\n"; } m_stream << "\"];\n"; std::visit(util::GenericVisitor{ @@ -163,7 +160,7 @@ class ControlFlowGraphPrinter { m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; m_stream << "Block" << getBlockId(_block) << "Exit [label=\"{ "; - m_stream << stackSlotToString(_conditionalJump.condition); + m_stream << stackSlotToString(_conditionalJump.condition, m_dialect); m_stream << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; m_stream << "Block" << getBlockId(_block); m_stream << "Exit:0 -> Block" << getBlockId(*_conditionalJump.zero) << ";\n"; @@ -192,6 +189,7 @@ class ControlFlowGraphPrinter return id; } std::ostream& m_stream; + Dialect const& m_dialect; std::map m_blockIds; size_t m_blockCount = 0; std::list m_blocksToPrint; @@ -199,20 +197,24 @@ class ControlFlowGraphPrinter TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build( + *yulStack.parserResult()->analysisInfo, + yulStack.dialect(), + yulStack.parserResult()->code()->root() + ); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - ControlFlowGraphPrinter printer{output}; + ControlFlowGraphPrinter printer{output, yulStack.dialect()}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/ControlFlowGraphTest.h b/test/libyul/ControlFlowGraphTest.h index 44cea06d3f7c..f6c8ddfce5db 100644 --- a/test/libyul/ControlFlowGraphTest.h +++ b/test/libyul/ControlFlowGraphTest.h @@ -20,14 +20,10 @@ #include -namespace solidity::yul +namespace solidity::yul::test { -struct Dialect; -namespace test -{ - -class ControlFlowGraphTest: public solidity::frontend::test::TestCase +class ControlFlowGraphTest: public frontend::test::EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) @@ -36,8 +32,6 @@ class ControlFlowGraphTest: public solidity::frontend::test::TestCase } explicit ControlFlowGraphTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; -private: - Dialect const* m_dialect = nullptr; }; -} + } diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 50c69b179dd1..2249ba110cb1 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -25,12 +25,15 @@ #include #include #include -#include +#include using namespace solidity; +using namespace solidity::test; using namespace solidity::yul; using namespace solidity::yul::test; using namespace solidity::frontend::test; +using namespace solidity::util; +using namespace solidity::langutil; namespace { @@ -56,19 +59,21 @@ ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(std::string const& _filen TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - Object obj; - auto parsingResult = yul::test::parse(m_source); - obj.setCode(parsingResult.first, parsingResult.second); - if (!obj.hasCode()) - BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) + { + printYulErrors(yulStack, _stream, _linePrefix, _formatted); + return TestResult::FatalError; + } - // TODO: Add EOF support ControlFlowSideEffectsCollector sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), - obj.code()->root() + yulStack.dialect(), + yulStack.parserResult()->code()->root() ); m_obtainedResult.clear(); - forEach(obj.code()->root(), [&](FunctionDefinition const& _fun) { + forEach(yulStack.parserResult()->code()->root(), [&](FunctionDefinition const& _fun) { std::string effectStr = toString(sideEffects.functionSideEffects().at(&_fun)); m_obtainedResult += _fun.name.str() + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; }); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 23c24ce305fd..96699b109c52 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -27,11 +27,10 @@ #include -#include - -#include +#include using namespace solidity; +using namespace solidity::test; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -52,36 +51,31 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin solidity::frontend::OptimiserSettings settings = solidity::frontend::OptimiserSettings::none(); settings.runYulOptimiser = false; settings.optimizeStackAllocation = m_stackOpt; - YulStack stack( - EVMVersion{}, - std::nullopt, + // Restrict to a single EVM/EOF version combination (the default one) as code generation + // can be different from version to version. + YulStack yulStack( + CommonOptions::get().evmVersion(), + CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, settings, - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); - if (!stack.parseAndAnalyze("", m_source)) + yulStack.parseAndAnalyze("", m_source); + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; - SourceReferenceFormatter{_stream, stack, true, false} - .printErrorInformation(stack.errors()); + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } - // TODO: Add EOF support - evmasm::Assembly assembly{solidity::test::CommonOptions::get().evmVersion(), false, std::nullopt, {}}; + evmasm::Assembly assembly{CommonOptions::get().evmVersion(), false, CommonOptions::get().eofVersion(), {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( - *stack.parserResult(), + *yulStack.parserResult(), adapter, - // TODO: Make sure that why we cannot pass here solidity::test::CommonOptions::get().evmVersion() and assembly.eofVersion() - EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}, std::nullopt), - m_stackOpt, - std::nullopt + m_stackOpt ); - std::ostringstream output; - output << assembly; - m_obtainedResult = output.str(); + m_obtainedResult = toString(assembly); return checkResult(_stream, _linePrefix, _formatted); } diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 7a153de7d362..cb24ed764c32 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -20,20 +20,21 @@ #include #include -#include - #include #include #include #include +#include #include #include +#include #include using namespace solidity; +using namespace solidity::test; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -74,7 +75,7 @@ std::string toString(SideEffects const& _sideEffects) } FunctionSideEffects::FunctionSideEffects(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); m_expectation = m_reader.simpleExpectations(); @@ -82,21 +83,29 @@ FunctionSideEffects::FunctionSideEffects(std::string const& _filename): TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - Object obj; - auto parsingResult = yul::test::parse(m_source); - obj.setCode(parsingResult.first, parsingResult.second); - if (!obj.hasCode()) - BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); - - // TODO: Add EOF support - std::map functionSideEffects = SideEffectsPropagator::sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), - CallGraphGenerator::callGraph(obj.code()->root()) + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) + { + printYulErrors(yulStack, _stream, _linePrefix, _formatted); + return TestResult::FatalError; + } + + std::map functionSideEffects = SideEffectsPropagator::sideEffects( + yulStack.dialect(), + CallGraphGenerator::callGraph(yulStack.parserResult()->code()->root()) ); std::map functionSideEffectsStr; for (auto const& fun: functionSideEffects) - functionSideEffectsStr[fun.first.str()] = toString(fun.second); + { + auto const& functionNameStr = std::visit(GenericVisitor{ + [](YulName const& _name) { return _name.str(); }, + [&](BuiltinHandle const& _builtin) { return yulStack.dialect().builtin(_builtin).name; } + }, fun.first); + functionSideEffectsStr[functionNameStr] = toString(fun.second); + } m_obtainedResult.clear(); for (auto const& fun: functionSideEffectsStr) diff --git a/test/libyul/FunctionSideEffects.h b/test/libyul/FunctionSideEffects.h index ac0653733f03..9a7b77c14968 100644 --- a/test/libyul/FunctionSideEffects.h +++ b/test/libyul/FunctionSideEffects.h @@ -18,7 +18,6 @@ #pragma once -#include #include #include @@ -29,7 +28,7 @@ namespace solidity::yul::test { -class FunctionSideEffects: public solidity::frontend::test::TestCase +class FunctionSideEffects: public solidity::frontend::test::EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index badeb21fe7f9..6e75442f0621 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -20,9 +20,12 @@ #include +#include + #include #include +#include #include #include #include @@ -30,8 +33,6 @@ #include #include -#include - #include using namespace solidity::langutil; @@ -44,27 +45,28 @@ class KnowledgeBaseTest protected: KnowledgeBase constructKnowledgeBase(std::string const& _source) { - ErrorList errorList; - std::shared_ptr analysisInfo; - std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_dialect, errorList); - BOOST_REQUIRE(m_object && errorList.empty() && m_object->hasCode()); + YulStack yulStack = parseYul(_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + soltestAssert(!yulStack.hasErrors()); + m_object = yulStack.parserResult(); auto astRoot = std::get(yul::ASTCopier{}(m_object->code()->root())); - NameDispenser dispenser(m_dialect, astRoot); + NameDispenser dispenser(*m_object->dialect(), astRoot); std::set reserved; - OptimiserStepContext context{m_dialect, dispenser, reserved, 0}; + OptimiserStepContext context{*m_object->dialect(), dispenser, reserved, 0}; CommonSubexpressionEliminator::run(context, astRoot); m_ssaValues(astRoot); for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; - m_object->setCode(std::make_shared(std::move(astRoot))); - return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }); + m_object->setCode(std::make_shared(*m_object->dialect(), std::move(astRoot))); + return KnowledgeBase( + [this](YulName _var) { return util::valueOrNullptr(m_values, _var); }, + *m_object->dialect() + ); } - // TODO: Add EOF support - EVMDialect m_dialect{EVMVersion{}, std::nullopt, true}; std::shared_ptr m_object; SSAValueTracker m_ssaValues; std::map m_values; diff --git a/test/libyul/Metrics.cpp b/test/libyul/Metrics.cpp index 5c7b5fc34de0..9e74cd150e49 100644 --- a/test/libyul/Metrics.cpp +++ b/test/libyul/Metrics.cpp @@ -20,11 +20,14 @@ #include +#include + #include #include #include #include +#include #include @@ -38,9 +41,10 @@ namespace size_t codeSize(std::string const& _source, CodeWeights const _weights = {}) { - std::shared_ptr ast = parse(_source).first; - BOOST_REQUIRE(ast); - return CodeSize::codeSize(ast->root(), _weights); + YulStack yulStack = parseYul(_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + soltestAssert(!yulStack.hasErrors()); + return CodeSize::codeSize(yulStack.parserResult()->code()->root(), _weights); } } diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 5d6dd1b23dea..b7e475c91b1b 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -21,8 +21,7 @@ #include #include - -#include +#include #include @@ -31,11 +30,10 @@ #include #include -#include #include -#include +#include using namespace solidity; using namespace solidity::util; @@ -46,7 +44,7 @@ using namespace solidity::frontend; using namespace solidity::frontend::test; ObjectCompilerTest::ObjectCompilerTest(std::string const& _filename): - TestCase(_filename) + solidity::frontend::test::EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); m_optimisationPreset = m_reader.enumSetting( @@ -59,43 +57,54 @@ ObjectCompilerTest::ObjectCompilerTest(std::string const& _filename): }, "minimal" ); + + constexpr std::array allowedOutputs = {"Assembly", "Bytecode", "Opcodes", "SourceMappings"}; + boost::split(m_outputSetting, m_reader.stringSetting("outputs", "Assembly,Bytecode,Opcodes,SourceMappings"), boost::is_any_of(",")); + for (auto const& output: m_outputSetting) + if (std::find(allowedOutputs.begin(), allowedOutputs.end(), output) == allowedOutputs.end()) + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid output type: \"" + output + "\""}); + m_expectation = m_reader.simpleExpectations(); } TestCase::TestResult ObjectCompilerTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - YulStack stack( - EVMVersion(), - std::nullopt, - YulStack::Language::StrictAssembly, - OptimiserSettings::preset(m_optimisationPreset), - DebugInfoSelection::All() - ); - if (!stack.parseAndAnalyze("source", m_source)) + YulStack yulStack = parseYul(m_source, "source", OptimiserSettings::preset(m_optimisationPreset)); + MachineAssemblyObject obj; + if (!yulStack.hasErrors()) + { + yulStack.optimize(); + obj = yulStack.assemble(YulStack::Machine::EVM); + } + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; - SourceReferenceFormatter{_stream, stack, true, false} - .printErrorInformation(stack.errors()); + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } - stack.optimize(); - MachineAssemblyObject obj = stack.assemble(YulStack::Machine::EVM); - solAssert(obj.bytecode, ""); - solAssert(obj.sourceMappings, ""); + solAssert(obj.bytecode); + solAssert(obj.sourceMappings); - m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(stack.debugInfoSelection()); + if (std::find(m_outputSetting.begin(), m_outputSetting.end(), "Assembly") != m_outputSetting.end()) + m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(yulStack.debugInfoSelection()); if (obj.bytecode->bytecode.empty()) m_obtainedResult += "-- empty bytecode --\n"; else - m_obtainedResult += - "Bytecode: " + - util::toHex(obj.bytecode->bytecode) + - "\nOpcodes: " + - boost::trim_copy(evmasm::disassemble(obj.bytecode->bytecode, solidity::test::CommonOptions::get().evmVersion())) + - "\nSourceMappings:" + - (obj.sourceMappings->empty() ? "" : " " + *obj.sourceMappings) + - "\n"; + { + if (std::find(m_outputSetting.begin(), m_outputSetting.end(), "Bytecode") != m_outputSetting.end()) + m_obtainedResult += "Bytecode: " + util::toHex(obj.bytecode->bytecode); + if (std::find(m_outputSetting.begin(), m_outputSetting.end(), "Opcodes") != m_outputSetting.end()) + { + m_obtainedResult += (!m_obtainedResult.empty() && m_obtainedResult.back() != '\n') ? "\n" : ""; + m_obtainedResult += "Opcodes: " + + boost::trim_copy(evmasm::disassemble(obj.bytecode->bytecode, solidity::test::CommonOptions::get().evmVersion())); + } + if (std::find(m_outputSetting.begin(), m_outputSetting.end(), "SourceMappings") != m_outputSetting.end()) + { + m_obtainedResult += (!m_obtainedResult.empty() && m_obtainedResult.back() != '\n') ? "\n" : ""; + m_obtainedResult += "SourceMappings:" + (obj.sourceMappings->empty() ? "" : " " + *obj.sourceMappings) + "\n"; + } + } return checkResult(_stream, _linePrefix, _formatted); } diff --git a/test/libyul/ObjectCompilerTest.h b/test/libyul/ObjectCompilerTest.h index fe899870022e..7a7941a69f95 100644 --- a/test/libyul/ObjectCompilerTest.h +++ b/test/libyul/ObjectCompilerTest.h @@ -38,7 +38,7 @@ struct Block; namespace solidity::yul::test { -class ObjectCompilerTest: public solidity::frontend::test::TestCase +class ObjectCompilerTest: public solidity::frontend::test::EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) @@ -51,10 +51,10 @@ class ObjectCompilerTest: public solidity::frontend::test::TestCase TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: - bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); void disambiguate(); frontend::OptimisationPreset m_optimisationPreset; + std::vector m_outputSetting; }; } diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index 7ed321cd48e6..446348fa0ba3 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -53,42 +54,14 @@ namespace solidity::yul::test namespace { -std::pair parse(std::string const& _source) -{ - YulStack asmStack( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() - ); - bool success = asmStack.parseAndAnalyze("source", _source); - return {success, asmStack.errors()}; -} - std::optional parseAndReturnFirstError(std::string const& _source, bool _allowWarningsAndInfos = true) { - bool success; - ErrorList errors; - tie(success, errors) = parse(_source); - if (!success) - { - BOOST_REQUIRE_EQUAL(errors.size(), 1); - return *errors.front(); - } - else - { - // If success is true, there might still be an error in the assembly stage. - if (_allowWarningsAndInfos && !Error::containsErrors(errors)) - return {}; - else if (!errors.empty()) - { - if (!_allowWarningsAndInfos) - BOOST_CHECK_EQUAL(errors.size(), 1); - return *errors.front(); - } - } - return {}; + YulStack yulStack = parseYul(_source, "source", OptimiserSettings::none()); + if (!yulStack.hasErrorsWarningsOrInfos() || (!yulStack.hasErrors() && _allowWarningsAndInfos)) + return {}; + + BOOST_REQUIRE_EQUAL(yulStack.errors().size(), 1); + return *yulStack.errors().front(); } bool successParse(std::string const& _source, bool _allowWarningsAndInfos = true) @@ -112,8 +85,8 @@ std::tuple, ErrorList> tryGetSourceLocationMapping( ErrorList errors; ErrorReporter reporter(errors); - // TODO: Add EOF support - Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); ObjectParser objectParser{reporter, dialect}; CharStream stream(std::move(source), ""); auto object = objectParser.parse(std::make_shared(stream), false); @@ -178,7 +151,7 @@ BOOST_AUTO_TEST_CASE(to_string) solidity::test::CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); BOOST_REQUIRE(asmStack.parseAndAnalyze("source", code)); BOOST_CHECK_EQUAL(asmStack.print(), expectation); diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 930a34cf1a04..d9ea91cbd351 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -133,13 +133,21 @@ BOOST_AUTO_TEST_SUITE(YulParser) BOOST_AUTO_TEST_CASE(builtins_analysis) { - struct SimpleDialect: public Dialect + struct SimpleDialect: Dialect { - BuiltinFunction const* builtin(YulName _name) const override + std::optional findBuiltin(std::string_view _name) const override { - return _name == "builtin"_yulname ? &f : nullptr; + if (_name == "builtin") + return BuiltinHandle{std::numeric_limits::max()}; + return std::nullopt; } - BuiltinFunction f{"builtin"_yulname, 2, 3, {}, {}, false, {}}; + + BuiltinFunction const& builtin(BuiltinHandle const& handle) const override + { + BOOST_REQUIRE(handle.id == std::numeric_limits::max()); + return f; + } + BuiltinFunction f{"builtin", 2, 3, {}, {}, false, {}}; }; SimpleDialect dialect; @@ -162,8 +170,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_empty_block) auto const sourceText = "/// @src 0:234:543\n" "{}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -181,8 +189,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -205,8 +213,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -228,8 +236,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) "/// @src 0:343:434\n" "switch y case 0 {} default {}\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -253,8 +261,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) " let z := add(3, 4)\n" "}\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -286,8 +294,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_inherit_into_outer_scope) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); @@ -318,8 +326,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) "/// @src 1:1:10\n" "a := true\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // should still parse BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); @@ -340,8 +348,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) "let b := true\n" "\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); // should still parse BOOST_REQUIRE(errorList.size() == 1); @@ -361,8 +369,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_1) "/// @src 0:234:2026\n" ":= true\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); @@ -385,8 +393,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_2) 2) } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); @@ -420,8 +428,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_3) mstore(1, 2) // FunctionCall } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); @@ -457,8 +465,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_comments_after_valid) let a := true } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); @@ -477,8 +485,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_suffix) /// @src 0:420:680foo {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -495,8 +503,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) /// abc@src 0:111:222 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); @@ -510,8 +518,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) /// @src -1:-1:-1 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); @@ -525,8 +533,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) /// @src a:b:c {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -543,8 +551,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) /// @src 111111111111111111111:222222222222222222222:333333333333333333333 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -565,8 +573,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) let x := true } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); @@ -584,8 +592,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_no_whitespace) /// @src 0:111:222@src 1:333:444 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -602,8 +610,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_s /// @src 0:111:222 @src 1:333:444 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); @@ -614,8 +622,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) ErrorList errorList; ErrorReporter reporter(errorList); auto const sourceText = "/// @src 0:111:222 \n{}"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -632,8 +640,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) let x := true } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); @@ -655,8 +663,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets) let y := /** @src 1:96:165 "contract D {..." */ 128 } )~~~"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); @@ -681,8 +689,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_empty_snippet) /// @src 0:111:222 "" {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -696,8 +704,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_befo /// @src 0:111:222"abc" def {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -714,8 +722,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_afte /// @src 0:111:222 "abc"def {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -729,8 +737,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whites /// @src 0:111:222 "abc"@src 1:333:444 "abc" {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); @@ -744,8 +752,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_untermina /// @src 0:111:222 " abc @src 1:333:444 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -763,8 +771,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) /// {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -781,8 +789,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) /// @src 0:111:222 hex"abc"@src 1:333:444 "abc" {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // the second source location is not parsed as such, as the hex string isn't interpreted as snippet but @@ -798,8 +806,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) /// @src 0:111:222 "\n\\x\x\w\uö\xy\z\y\fq" {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -814,8 +822,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces /// @src 1 : 222 : 333 '\x33\u1234\t\n' {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); @@ -830,8 +838,8 @@ BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_ar /// @src 1:222:333 {{}} )", invalid); - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); @@ -849,8 +857,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) /// " @src 0:333:444 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 333, 444); @@ -868,8 +876,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locati let y := /** @src 1:96:165 "function f() internal { \"\/** @src 0:6:7 *\/\"; }" */ 128 } )~~~"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); @@ -898,8 +906,8 @@ BOOST_AUTO_TEST_CASE(astid) mstore(1, 2) } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(7)); @@ -921,8 +929,8 @@ BOOST_AUTO_TEST_CASE(astid_reset) mstore(1, 2) } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(7)); @@ -940,8 +948,8 @@ BOOST_AUTO_TEST_CASE(astid_multi) /// @src -1:-1:-1 @ast-id 7 @src 1:1:1 @ast-id 8 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(8)); @@ -955,8 +963,8 @@ BOOST_AUTO_TEST_CASE(astid_invalid) /// @src -1:-1:-1 @ast-id abc @src 1:1:1 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -973,8 +981,8 @@ BOOST_AUTO_TEST_CASE(astid_too_large) /// @ast-id 9223372036854775808 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -990,8 +998,8 @@ BOOST_AUTO_TEST_CASE(astid_way_too_large) /// @ast-id 999999999999999999999999999999999999999 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -1007,8 +1015,8 @@ BOOST_AUTO_TEST_CASE(astid_not_fully_numeric) /// @ast-id 9x {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -1030,8 +1038,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line) "\n" " let x := 123\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 1); diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index c0d1e87270ef..c23a2ca5faf9 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -25,8 +25,7 @@ #include #include - -#include +#include #ifdef ISOLTEST #include @@ -48,32 +47,28 @@ SSAControlFlowGraphTest::SSAControlFlowGraphTest(std::string const& _filename): { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now m_expectation = m_reader.simpleExpectations(); } TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } - auto info = AsmAnalyzer::analyzeStrictAssertCorrect(*m_dialect, *object); std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( - info, - *m_dialect, - object->code()->root() + *yulStack.parserResult()->analysisInfo, + yulStack.dialect(), + yulStack.parserResult()->code()->root() ); - - m_obtainedResult = controlFlow->toDot(); + ControlFlowLiveness liveness(*controlFlow); + m_obtainedResult = controlFlow->toDot(&liveness); auto result = checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/SSAControlFlowGraphTest.h b/test/libyul/SSAControlFlowGraphTest.h index f976be03c339..51dd3c86d1a0 100644 --- a/test/libyul/SSAControlFlowGraphTest.h +++ b/test/libyul/SSAControlFlowGraphTest.h @@ -1,18 +1,18 @@ /* -This file is part of solidity. + This file is part of solidity. -solidity is free software: you can redistribute it and/or modify + 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. + 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. + 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 . + You should have received a copy of the GNU General Public License + along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 @@ -22,11 +22,7 @@ along with solidity. If not, see . #include -namespace solidity::yul -{ -struct Dialect; - -namespace test +namespace solidity::yul::test { class SSAControlFlowGraphTest: public solidity::frontend::test::TestCase @@ -35,8 +31,6 @@ class SSAControlFlowGraphTest: public solidity::frontend::test::TestCase static std::unique_ptr create(Config const& _config); explicit SSAControlFlowGraphTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; -private: - Dialect const* m_dialect = nullptr; }; -} + } diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index f50d2d23b028..eb34eabb1776 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -24,10 +24,10 @@ #include #include #include +#include #include -#include +#include -#include #include #include @@ -45,15 +45,11 @@ using namespace solidity::frontend; using namespace solidity::frontend::test; StackLayoutGeneratorTest::StackLayoutGeneratorTest(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now m_expectation = m_reader.simpleExpectations(); } @@ -68,8 +64,8 @@ static std::string variableSlotToString(VariableSlot const& _slot) class StackLayoutPrinter { public: - StackLayoutPrinter(std::ostream& _stream, StackLayout const& _stackLayout): - m_stream(_stream), m_stackLayout(_stackLayout) + StackLayoutPrinter(std::ostream& _stream, StackLayout const& _stackLayout, Dialect const& _dialect): + m_stream(_stream), m_stackLayout(_stackLayout), m_dialect(_dialect) { } void operator()(CFG::BasicBlock const& _block, bool _isMainEntry = true) @@ -103,7 +99,7 @@ class StackLayoutPrinter m_stream << "\\l\\\n"; Stack functionEntryStack = {FunctionReturnLabelSlot{_info.function}}; functionEntryStack += _info.parameters | ranges::views::reverse; - m_stream << stackToString(functionEntryStack) << "\"];\n"; + m_stream << stackToString(functionEntryStack, m_dialect) << "\"];\n"; m_stream << "FunctionEntry_" << _info.function.name.str() << " -> Block" << getBlockId(*_info.entry) << ";\n"; (*this)(*_info.entry, false); } @@ -134,17 +130,17 @@ class StackLayoutPrinter }, entry->exit); auto const& blockInfo = m_stackLayout.blockInfos.at(&_block); - m_stream << stackToString(blockInfo.entryLayout) << "\\l\\\n"; + m_stream << stackToString(blockInfo.entryLayout, m_dialect) << "\\l\\\n"; for (auto const& operation: _block.operations) { auto entryLayout = m_stackLayout.operationEntryLayout.at(&operation); - m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation)) << "\\l\\\n"; + m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation), m_dialect) << "\\l\\\n"; std::visit(util::GenericVisitor{ [&](CFG::FunctionCall const& _call) { m_stream << _call.function.get().name.str(); }, [&](CFG::BuiltinCall const& _call) { - m_stream << _call.functionCall.get().functionName.name.str(); + m_stream << _call.builtin.get().name; }, [&](CFG::Assignment const& _assignment) { @@ -158,9 +154,9 @@ class StackLayoutPrinter for (size_t i = 0; i < operation.input.size(); ++i) entryLayout.pop_back(); entryLayout += operation.output; - m_stream << stackToString(entryLayout) << "\\l\\\n"; + m_stream << stackToString(entryLayout, m_dialect) << "\\l\\\n"; } - m_stream << stackToString(blockInfo.exitLayout) << "\\l\\\n"; + m_stream << stackToString(blockInfo.exitLayout, m_dialect) << "\\l\\\n"; m_stream << "\"];\n"; std::visit(util::GenericVisitor{ [&](CFG::BasicBlock::MainExit const&) @@ -181,7 +177,7 @@ class StackLayoutPrinter { m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; m_stream << "Block" << getBlockId(_block) << "Exit [label=\"{ "; - m_stream << stackSlotToString(_conditionalJump.condition); + m_stream << stackSlotToString(_conditionalJump.condition, m_dialect); m_stream << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; m_stream << "Block" << getBlockId(_block); m_stream << "Exit:0 -> Block" << getBlockId(*_conditionalJump.zero) << ";\n"; @@ -211,6 +207,7 @@ class StackLayoutPrinter } std::ostream& m_stream; StackLayout const& m_stackLayout; + Dialect const& m_dialect; std::map m_blockIds; size_t m_blockCount = 0; std::list m_blocksToPrint; @@ -218,21 +215,30 @@ class StackLayoutPrinter TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); - StackLayout stackLayout = StackLayoutGenerator::run(*cfg); + std::unique_ptr cfg = ControlFlowGraphBuilder::build( + *yulStack.parserResult()->analysisInfo, + yulStack.dialect(), + yulStack.parserResult()->code()->root() + ); + + auto const* evmDialect = dynamic_cast(&yulStack.dialect()); + solAssert(evmDialect, "StackLayoutGenerator can only be run on EVM dialects."); + + StackLayout stackLayout = StackLayoutGenerator::run(*cfg, *evmDialect); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - StackLayoutPrinter printer{output, stackLayout}; + StackLayoutPrinter printer{output, stackLayout, yulStack.dialect()}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/StackLayoutGeneratorTest.h b/test/libyul/StackLayoutGeneratorTest.h index 9f570045f78e..c7259a02a963 100644 --- a/test/libyul/StackLayoutGeneratorTest.h +++ b/test/libyul/StackLayoutGeneratorTest.h @@ -20,14 +20,10 @@ #include -namespace solidity::yul +namespace solidity::yul::test { -struct Dialect; -namespace test -{ - -class StackLayoutGeneratorTest: public solidity::frontend::test::TestCase +class StackLayoutGeneratorTest: public frontend::test::EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) @@ -36,8 +32,6 @@ class StackLayoutGeneratorTest: public solidity::frontend::test::TestCase } explicit StackLayoutGeneratorTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; -private: - Dialect const* m_dialect = nullptr; }; -} + } diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index 40fdcc5b15f4..58ea124fb1df 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -17,10 +17,16 @@ #include +#include + +#include +#include + #include #include -#include +#include +using namespace solidity::test; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -131,12 +137,23 @@ bool StackShufflingTest::parse(std::string const& _source) StackShufflingTest::StackShufflingTest(std::string const& _filename): TestCase(_filename) { + processSettings(); m_source = m_reader.source(); m_expectation = m_reader.simpleExpectations(); } +void StackShufflingTest::processSettings() +{ + std::string depthString = m_reader.stringSetting("maximumStackDepth", "16"); + std::optional depth = toUnsignedInt(depthString); + if (!depth.has_value()) + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid maximum stack depth: \"" + depthString + "\""}); + m_maximumStackDepth = *depth; +} + TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { + auto const& dialect = CommonOptions::get().evmDialect(); if (!parse(m_source)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; @@ -144,19 +161,22 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string } std::ostringstream output; + size_t operations = 0; createStackLayout( m_sourceStack, m_targetStack, [&](unsigned _swapDepth) // swap { - output << stackToString(m_sourceStack) << std::endl; + ++operations; + output << stackToString(m_sourceStack, dialect) << std::endl; output << "SWAP" << _swapDepth << std::endl; }, [&](StackSlot const& _slot) // dupOrPush { - output << stackToString(m_sourceStack) << std::endl; + ++operations; + output << stackToString(m_sourceStack, dialect) << std::endl; if (canBeFreelyGenerated(_slot)) - output << "PUSH " << stackSlotToString(_slot) << std::endl; + output << "PUSH " << stackSlotToString(_slot, dialect) << std::endl; else { if (auto depth = util::findOffset(m_sourceStack | ranges::views::reverse, _slot)) @@ -166,12 +186,15 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string } }, [&](){ // pop - output << stackToString(m_sourceStack) << std::endl; + ++operations; + output << stackToString(m_sourceStack, dialect) << std::endl; output << "POP" << std::endl; - } + }, + m_maximumStackDepth ); - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, dialect) << std::endl; + output << operations << " operations" << std::endl; m_obtainedResult = output.str(); return checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/StackShufflingTest.h b/test/libyul/StackShufflingTest.h index 2e2dd12ad325..5485ed081805 100644 --- a/test/libyul/StackShufflingTest.h +++ b/test/libyul/StackShufflingTest.h @@ -37,8 +37,10 @@ class StackShufflingTest: public TestCase explicit StackShufflingTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: + void processSettings(); bool parse(std::string const& _source); + size_t m_maximumStackDepth{}; Stack m_sourceStack; Stack m_targetStack; std::map m_functions; diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index aa37e85afdd8..88046c02f8a1 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -16,39 +16,38 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include -#include - -#include -#include +#include #include -#include #include #include #include +#include + using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; +using namespace solidity::test; using namespace solidity::yul::test; +using namespace solidity::frontend; using namespace solidity::frontend::test; void SyntaxTest::parseAndAnalyze() { - if (m_sources.sources.size() != 1) - BOOST_THROW_EXCEPTION(std::runtime_error{"Expected only one source for yul test."}); + solUnimplementedAssert(m_sources.sources.size() == 1, "Multi-source Yul tests are not supported."); + auto const& [sourceUnitName, source] = *m_sources.sources.begin(); - std::string const& name = m_sources.sources.begin()->first; - std::string const& source = m_sources.sources.begin()->second; - - ErrorList errorList{}; - soltestAssert(m_dialect, ""); - // Silently ignoring the results. - yul::test::parse(source, *m_dialect, errorList); - for (auto const& error: errorList) + YulStack yulStack = parseYul(source); + if (!yulStack.hasErrors()) + { + // Assemble the object so that we can test CodeGenerationErrors too. + yulStack.optimize(); + yulStack.assemble(YulStack::Machine::EVM); + } + for (auto const& error: yulStack.errors()) { int locationStart = -1; int locationEnd = -1; @@ -63,21 +62,16 @@ void SyntaxTest::parseAndAnalyze() error->type(), error->errorId(), errorMessage(*error), - name, + sourceUnitName, locationStart, locationEnd }); } - } SyntaxTest::SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion): CommonSyntaxTest(_filename, _evmVersion) { std::string dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now } diff --git a/test/libyul/SyntaxTest.h b/test/libyul/SyntaxTest.h index 27e59ee61439..9aab3298e1c5 100644 --- a/test/libyul/SyntaxTest.h +++ b/test/libyul/SyntaxTest.h @@ -19,7 +19,6 @@ #pragma once #include -#include namespace solidity::yul::test { @@ -37,9 +36,6 @@ class SyntaxTest: public solidity::test::CommonSyntaxTest ~SyntaxTest() override {} protected: void parseAndAnalyze() override; - -private: - Dialect const* m_dialect = nullptr; }; } diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 343a17b4a4a1..d97211b9761d 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -18,20 +18,18 @@ #include +#include + #include #include -#include #include #include #include #include #include -#include - -#include #include #include @@ -39,6 +37,7 @@ #include using namespace solidity; +using namespace solidity::test; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -56,40 +55,23 @@ YulInterpreterTest::YulInterpreterTest(std::string const& _filename): TestCase::TestResult YulInterpreterTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - if (!parse(_stream, _linePrefix, _formatted)) + YulStack yulStack = parseYul(m_source, "", solidity::frontend::OptimiserSettings::none()); + + if (yulStack.hasErrors()) + { + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; + } - m_obtainedResult = interpret(); + m_obtainedResult = interpret(yulStack.parserResult()); return checkResult(_stream, _linePrefix, _formatted); } -bool YulInterpreterTest::parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) +std::string YulInterpreterTest::interpret(std::shared_ptr const& _object) { - YulStack stack( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() - ); - if (stack.parseAndAnalyze("", m_source)) - { - m_ast = stack.parserResult()->code(); - m_analysisInfo = stack.parserResult()->analysisInfo; - return true; - } - else - { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; - SourceReferenceFormatter{_stream, stack, true, false} - .printErrorInformation(stack.errors()); - return false; - } -} + solAssert(_object && _object->hasCode()); -std::string YulInterpreterTest::interpret() -{ InterpreterState state; state.maxTraceSize = 32; state.maxSteps = 512; @@ -98,8 +80,8 @@ std::string YulInterpreterTest::interpret() { Interpreter::run( state, - EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), std::nullopt), - m_ast->root(), + *_object->dialect(), + _object->code()->root(), /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false ); diff --git a/test/libyul/YulInterpreterTest.h b/test/libyul/YulInterpreterTest.h index d591591332ce..b4a21b69a277 100644 --- a/test/libyul/YulInterpreterTest.h +++ b/test/libyul/YulInterpreterTest.h @@ -22,8 +22,7 @@ namespace solidity::yul { -struct AsmAnalysisInfo; -class AST; +class Object; } namespace solidity::yul::test @@ -42,11 +41,8 @@ class YulInterpreterTest: public solidity::frontend::test::EVMVersionRestrictedT TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: - bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); - std::string interpret(); + std::string interpret(std::shared_ptr const& _object); - std::shared_ptr m_ast; - std::shared_ptr m_analysisInfo; bool m_simulateExternalCallsToSelf = false; }; diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 308afef5f904..1048fb468854 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -56,25 +57,18 @@ YulOptimizerTest::YulOptimizerTest(std::string const& _filename): m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now m_expectation = m_reader.simpleExpectations(); } TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - std::tie(m_object, m_analysisInfo) = parse(_stream, _linePrefix, _formatted, m_source); + m_object = parse(_stream, _linePrefix, _formatted, m_source); if (!m_object) return TestResult::FatalError; - soltestAssert(m_dialect, "Dialect not set."); - - m_object->analysisInfo = m_analysisInfo; - YulOptimizerTestCommon tester(m_object, *m_dialect); + YulOptimizerTestCommon tester(m_object); tester.setStep(m_optimizerStep); if (!tester.runStep()) @@ -84,13 +78,14 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co } auto optimizedObject = tester.optimizedObject(); std::string printedOptimizedObject; + soltestAssert(optimizedObject->dialect()); if (optimizedObject->subObjects.empty()) - printedOptimizedObject = AsmPrinter{}(optimizedObject->code()->root()); + printedOptimizedObject = AsmPrinter::format(*optimizedObject->code()); else printedOptimizedObject = optimizedObject->toString(); // Re-parse new code for compilability - if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printedOptimizedObject))) + if (!parse(_stream, _linePrefix, _formatted, printedOptimizedObject)) { util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) << _linePrefix << "Result after the optimiser:" << std::endl; @@ -103,25 +98,19 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co return checkResult(_stream, _linePrefix, _formatted); } -std::pair, std::shared_ptr> YulOptimizerTest::parse( +std::shared_ptr YulOptimizerTest::parse( std::ostream& _stream, std::string const& _linePrefix, bool const _formatted, std::string const& _source ) { - ErrorList errors; - soltestAssert(m_dialect, ""); - std::shared_ptr object; - std::shared_ptr analysisInfo; - std::tie(object, analysisInfo) = yul::test::parse(_source, *m_dialect, errors); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(_source); + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; - CharStream charStream(_source, ""); - SourceReferenceFormatter{_stream, SingletonCharStreamProvider(charStream), true, false} - .printErrorInformation(errors); - return {}; + printYulErrors(yulStack, _stream, _linePrefix, _formatted); + return nullptr; } - return {std::move(object), std::move(analysisInfo)}; + + return yulStack.parserResult(); } diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 832b5dfb8f7c..02fd6a0b2700 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -29,8 +29,8 @@ using ErrorList = std::vector>; namespace solidity::yul { struct AsmAnalysisInfo; -struct Object; -struct Dialect; +class Object; +class Dialect; } namespace solidity::yul::test @@ -48,16 +48,16 @@ class YulOptimizerTest: public solidity::frontend::test::EVMVersionRestrictedTes TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: - std::pair, std::shared_ptr> parse( - std::ostream& _stream, std::string const& _linePrefix, bool const _formatted, std::string const& _source + std::shared_ptr parse( + std::ostream& _stream, + std::string const& _linePrefix, + bool const _formatted, + std::string const& _source ); std::string m_optimizerStep; - Dialect const* m_dialect = nullptr; - std::shared_ptr m_object; - std::shared_ptr m_analysisInfo; }; } diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 0f94f309dce4..19b2176c10f5 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include #include @@ -73,11 +75,12 @@ using namespace solidity::yul; using namespace solidity::yul::test; using namespace solidity::frontend; -YulOptimizerTestCommon::YulOptimizerTestCommon( - std::shared_ptr _obj, - Dialect const& _dialect -): m_dialect(&_dialect), m_object(_obj), m_optimizedObject(std::make_shared(*_obj)) +YulOptimizerTestCommon::YulOptimizerTestCommon(std::shared_ptr _obj): + m_object(_obj), + m_optimizedObject(std::make_shared(*_obj)) { + soltestAssert(m_object && m_optimizedObject); + if ( std::any_of( m_object->subObjects.begin(), @@ -85,7 +88,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( [](auto const& subObject) { return dynamic_cast(subObject.get()) == nullptr;} ) ) - solUnimplementedAssert(false, "The current implementation of YulOptimizerTests ignores subobjects that are not Data."); + solUnimplemented("The current implementation of YulOptimizerTests ignores subobjects that are not Data."); m_namedSteps = { {"disambiguator", [&]() { return disambiguate(); }}, @@ -108,8 +111,8 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( {"constantOptimiser", [&]() { auto block = std::get(ASTCopier{}(m_object->code()->root())); updateContext(block); - GasMeter meter(dynamic_cast(*m_dialect), false, 200); - ConstantOptimiser{dynamic_cast(*m_dialect), meter}(block); + GasMeter meter(dynamic_cast(*m_object->dialect()), false, 200); + ConstantOptimiser{dynamic_cast(*m_object->dialect()), meter}(block); return block; }}, {"varDeclInitializer", [&]() { @@ -410,16 +413,15 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( size_t maxIterations = 16; { Object object(*m_optimizedObject); - object.setCode(std::make_shared(std::get(ASTCopier{}(block)))); - block = std::get<1>(StackCompressor::run(*m_dialect, object, true, maxIterations)); + object.setCode(std::make_shared(*m_object->dialect(), std::get(ASTCopier{}(block)))); + block = std::get<1>(StackCompressor::run(object, true, maxIterations)); } BlockFlattener::run(*m_context, block); return block; }}, {"fullSuite", [&]() { - GasMeter meter(dynamic_cast(*m_dialect), false, 200); + GasMeter meter(dynamic_cast(*m_object->dialect()), false, 200); OptimiserSuite::run( - *m_dialect, &meter, *m_optimizedObject, true, @@ -433,9 +435,8 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( auto block = disambiguate(); updateContext(block); Object object(*m_optimizedObject); - object.setCode(std::make_shared(std::get(ASTCopier{}(block)))); + object.setCode(std::make_shared(*m_object->dialect(), std::get(ASTCopier{}(block)))); auto const unreachables = CompilabilityChecker{ - *m_dialect, object, true }.unreachableVariables; @@ -495,12 +496,10 @@ void YulOptimizerTestCommon::setStep(std::string const& _optimizerStep) bool YulOptimizerTestCommon::runStep() { - yulAssert(m_dialect, "Dialect not set."); - if (m_namedSteps.count(m_optimizerStep)) { auto block = m_namedSteps[m_optimizerStep](); - m_optimizedObject->setCode(std::make_shared(std::move(block))); + m_optimizedObject->setCode(std::make_shared(*m_object->dialect(), std::move(block))); } else return false; @@ -544,15 +543,15 @@ Block const* YulOptimizerTestCommon::run() Block YulOptimizerTestCommon::disambiguate() { - auto block = std::get(Disambiguator(*m_dialect, *m_object->analysisInfo)(m_object->code()->root())); + auto block = std::get(Disambiguator(*m_object->dialect(), *m_object->analysisInfo)(m_object->code()->root())); return block; } void YulOptimizerTestCommon::updateContext(Block const& _block) { - m_nameDispenser = std::make_unique(*m_dialect, _block, m_reservedIdentifiers); + m_nameDispenser = std::make_unique(*m_object->dialect(), _block, m_reservedIdentifiers); m_context = std::make_unique(OptimiserStepContext{ - *m_dialect, + *m_object->dialect(), *m_nameDispenser, m_reservedIdentifiers, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 41806fcd6a5a..df5c84039b0f 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -29,8 +29,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; -struct Object; -struct Dialect; +class Object; class AST; } @@ -39,10 +38,7 @@ namespace solidity::yul::test class YulOptimizerTestCommon { public: - explicit YulOptimizerTestCommon( - std::shared_ptr _obj, - Dialect const& _dialect - ); + explicit YulOptimizerTestCommon(std::shared_ptr _obj); /// Sets optimiser step to be run to @param /// _optimiserStep. void setStep(std::string const& _optimizerStep); @@ -65,7 +61,6 @@ class YulOptimizerTestCommon std::string m_optimizerStep; - Dialect const* m_dialect = nullptr; std::set m_reservedIdentifiers; std::unique_ptr m_nameDispenser; std::unique_ptr m_context; diff --git a/test/libyul/evmCodeTransform/after_terminating_function.yul b/test/libyul/evmCodeTransform/after_terminating_function.yul index ee32b4431579..7baa751c3c0f 100644 --- a/test/libyul/evmCodeTransform/after_terminating_function.yul +++ b/test/libyul/evmCodeTransform/after_terminating_function.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":17:18 */ // 0x02 diff --git a/test/libyul/evmCodeTransform/early_push_on_deep_swap.yul b/test/libyul/evmCodeTransform/early_push_on_deep_swap.yul index 5e119cc73f8f..3d9d55e7822b 100644 --- a/test/libyul/evmCodeTransform/early_push_on_deep_swap.yul +++ b/test/libyul/evmCodeTransform/early_push_on_deep_swap.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":1027:1092 */ // 0x0100000000000000000000000000000000000000000000000000000000000001 diff --git a/test/libyul/evmCodeTransform/eof_dup256.yul b/test/libyul/evmCodeTransform/eof_dup256.yul new file mode 100644 index 000000000000..a345c7b6d63d --- /dev/null +++ b/test/libyul/evmCodeTransform/eof_dup256.yul @@ -0,0 +1,2595 @@ +object "main" { + code { + let v0 := calldataload(0) + let v1 := calldataload(1) + let v2 := calldataload(2) + let v3 := calldataload(3) + let v4 := calldataload(4) + let v5 := calldataload(5) + let v6 := calldataload(6) + let v7 := calldataload(7) + let v8 := calldataload(8) + let v9 := calldataload(9) + let v10 := calldataload(10) + let v11 := calldataload(11) + let v12 := calldataload(12) + let v13 := calldataload(13) + let v14 := calldataload(14) + let v15 := calldataload(15) + let v16 := calldataload(16) + let v17 := calldataload(17) + let v18 := calldataload(18) + let v19 := calldataload(19) + let v20 := calldataload(20) + let v21 := calldataload(21) + let v22 := calldataload(22) + let v23 := calldataload(23) + let v24 := calldataload(24) + let v25 := calldataload(25) + let v26 := calldataload(26) + let v27 := calldataload(27) + let v28 := calldataload(28) + let v29 := calldataload(29) + let v30 := calldataload(30) + let v31 := calldataload(31) + let v32 := calldataload(32) + let v33 := calldataload(33) + let v34 := calldataload(34) + let v35 := calldataload(35) + let v36 := calldataload(36) + let v37 := calldataload(37) + let v38 := calldataload(38) + let v39 := calldataload(39) + let v40 := calldataload(40) + let v41 := calldataload(41) + let v42 := calldataload(42) + let v43 := calldataload(43) + let v44 := calldataload(44) + let v45 := calldataload(45) + let v46 := calldataload(46) + let v47 := calldataload(47) + let v48 := calldataload(48) + let v49 := calldataload(49) + let v50 := calldataload(50) + let v51 := calldataload(51) + let v52 := calldataload(52) + let v53 := calldataload(53) + let v54 := calldataload(54) + let v55 := calldataload(55) + let v56 := calldataload(56) + let v57 := calldataload(57) + let v58 := calldataload(58) + let v59 := calldataload(59) + let v60 := calldataload(60) + let v61 := calldataload(61) + let v62 := calldataload(62) + let v63 := calldataload(63) + let v64 := calldataload(64) + let v65 := calldataload(65) + let v66 := calldataload(66) + let v67 := calldataload(67) + let v68 := calldataload(68) + let v69 := calldataload(69) + let v70 := calldataload(70) + let v71 := calldataload(71) + let v72 := calldataload(72) + let v73 := calldataload(73) + let v74 := calldataload(74) + let v75 := calldataload(75) + let v76 := calldataload(76) + let v77 := calldataload(77) + let v78 := calldataload(78) + let v79 := calldataload(79) + let v80 := calldataload(80) + let v81 := calldataload(81) + let v82 := calldataload(82) + let v83 := calldataload(83) + let v84 := calldataload(84) + let v85 := calldataload(85) + let v86 := calldataload(86) + let v87 := calldataload(87) + let v88 := calldataload(88) + let v89 := calldataload(89) + let v90 := calldataload(90) + let v91 := calldataload(91) + let v92 := calldataload(92) + let v93 := calldataload(93) + let v94 := calldataload(94) + let v95 := calldataload(95) + let v96 := calldataload(96) + let v97 := calldataload(97) + let v98 := calldataload(98) + let v99 := calldataload(99) + let v100 := calldataload(100) + let v101 := calldataload(101) + let v102 := calldataload(102) + let v103 := calldataload(103) + let v104 := calldataload(104) + let v105 := calldataload(105) + let v106 := calldataload(106) + let v107 := calldataload(107) + let v108 := calldataload(108) + let v109 := calldataload(109) + let v110 := calldataload(110) + let v111 := calldataload(111) + let v112 := calldataload(112) + let v113 := calldataload(113) + let v114 := calldataload(114) + let v115 := calldataload(115) + let v116 := calldataload(116) + let v117 := calldataload(117) + let v118 := calldataload(118) + let v119 := calldataload(119) + let v120 := calldataload(120) + let v121 := calldataload(121) + let v122 := calldataload(122) + let v123 := calldataload(123) + let v124 := calldataload(124) + let v125 := calldataload(125) + let v126 := calldataload(126) + let v127 := calldataload(127) + let v128 := calldataload(128) + let v129 := calldataload(129) + let v130 := calldataload(130) + let v131 := calldataload(131) + let v132 := calldataload(132) + let v133 := calldataload(133) + let v134 := calldataload(134) + let v135 := calldataload(135) + let v136 := calldataload(136) + let v137 := calldataload(137) + let v138 := calldataload(138) + let v139 := calldataload(139) + let v140 := calldataload(140) + let v141 := calldataload(141) + let v142 := calldataload(142) + let v143 := calldataload(143) + let v144 := calldataload(144) + let v145 := calldataload(145) + let v146 := calldataload(146) + let v147 := calldataload(147) + let v148 := calldataload(148) + let v149 := calldataload(149) + let v150 := calldataload(150) + let v151 := calldataload(151) + let v152 := calldataload(152) + let v153 := calldataload(153) + let v154 := calldataload(154) + let v155 := calldataload(155) + let v156 := calldataload(156) + let v157 := calldataload(157) + let v158 := calldataload(158) + let v159 := calldataload(159) + let v160 := calldataload(160) + let v161 := calldataload(161) + let v162 := calldataload(162) + let v163 := calldataload(163) + let v164 := calldataload(164) + let v165 := calldataload(165) + let v166 := calldataload(166) + let v167 := calldataload(167) + let v168 := calldataload(168) + let v169 := calldataload(169) + let v170 := calldataload(170) + let v171 := calldataload(171) + let v172 := calldataload(172) + let v173 := calldataload(173) + let v174 := calldataload(174) + let v175 := calldataload(175) + let v176 := calldataload(176) + let v177 := calldataload(177) + let v178 := calldataload(178) + let v179 := calldataload(179) + let v180 := calldataload(180) + let v181 := calldataload(181) + let v182 := calldataload(182) + let v183 := calldataload(183) + let v184 := calldataload(184) + let v185 := calldataload(185) + let v186 := calldataload(186) + let v187 := calldataload(187) + let v188 := calldataload(188) + let v189 := calldataload(189) + let v190 := calldataload(190) + let v191 := calldataload(191) + let v192 := calldataload(192) + let v193 := calldataload(193) + let v194 := calldataload(194) + let v195 := calldataload(195) + let v196 := calldataload(196) + let v197 := calldataload(197) + let v198 := calldataload(198) + let v199 := calldataload(199) + let v200 := calldataload(200) + let v201 := calldataload(201) + let v202 := calldataload(202) + let v203 := calldataload(203) + let v204 := calldataload(204) + let v205 := calldataload(205) + let v206 := calldataload(206) + let v207 := calldataload(207) + let v208 := calldataload(208) + let v209 := calldataload(209) + let v210 := calldataload(210) + let v211 := calldataload(211) + let v212 := calldataload(212) + let v213 := calldataload(213) + let v214 := calldataload(214) + let v215 := calldataload(215) + let v216 := calldataload(216) + let v217 := calldataload(217) + let v218 := calldataload(218) + let v219 := calldataload(219) + let v220 := calldataload(220) + let v221 := calldataload(221) + let v222 := calldataload(222) + let v223 := calldataload(223) + let v224 := calldataload(224) + let v225 := calldataload(225) + let v226 := calldataload(226) + let v227 := calldataload(227) + let v228 := calldataload(228) + let v229 := calldataload(229) + let v230 := calldataload(230) + let v231 := calldataload(231) + let v232 := calldataload(232) + let v233 := calldataload(233) + let v234 := calldataload(234) + let v235 := calldataload(235) + let v236 := calldataload(236) + let v237 := calldataload(237) + let v238 := calldataload(238) + let v239 := calldataload(239) + let v240 := calldataload(240) + let v241 := calldataload(241) + let v242 := calldataload(242) + let v243 := calldataload(243) + let v244 := calldataload(244) + let v245 := calldataload(245) + let v246 := calldataload(246) + let v247 := calldataload(247) + let v248 := calldataload(248) + let v249 := calldataload(249) + let v250 := calldataload(250) + let v251 := calldataload(251) + let v252 := calldataload(252) + let v253 := calldataload(253) + let v254 := calldataload(254) + let v255 := calldataload(255) + // The conditional jump splits basic blocks and prevents us from moving the resulting dupn{256} further up. + // At the time of writing, the current code transform would do that and turn it into a less-deep dup otherwise. + if calldataload(256) { revert(0,0) } + sstore(256, v0) + sstore(255, v255) + sstore(254, v254) + sstore(253, v253) + sstore(252, v252) + sstore(251, v251) + sstore(250, v250) + sstore(249, v249) + sstore(248, v248) + sstore(247, v247) + sstore(246, v246) + sstore(245, v245) + sstore(244, v244) + sstore(243, v243) + sstore(242, v242) + sstore(241, v241) + sstore(240, v240) + sstore(239, v239) + sstore(238, v238) + sstore(237, v237) + sstore(236, v236) + sstore(235, v235) + sstore(234, v234) + sstore(233, v233) + sstore(232, v232) + sstore(231, v231) + sstore(230, v230) + sstore(229, v229) + sstore(228, v228) + sstore(227, v227) + sstore(226, v226) + sstore(225, v225) + sstore(224, v224) + sstore(223, v223) + sstore(222, v222) + sstore(221, v221) + sstore(220, v220) + sstore(219, v219) + sstore(218, v218) + sstore(217, v217) + sstore(216, v216) + sstore(215, v215) + sstore(214, v214) + sstore(213, v213) + sstore(212, v212) + sstore(211, v211) + sstore(210, v210) + sstore(209, v209) + sstore(208, v208) + sstore(207, v207) + sstore(206, v206) + sstore(205, v205) + sstore(204, v204) + sstore(203, v203) + sstore(202, v202) + sstore(201, v201) + sstore(200, v200) + sstore(199, v199) + sstore(198, v198) + sstore(197, v197) + sstore(196, v196) + sstore(195, v195) + sstore(194, v194) + sstore(193, v193) + sstore(192, v192) + sstore(191, v191) + sstore(190, v190) + sstore(189, v189) + sstore(188, v188) + sstore(187, v187) + sstore(186, v186) + sstore(185, v185) + sstore(184, v184) + sstore(183, v183) + sstore(182, v182) + sstore(181, v181) + sstore(180, v180) + sstore(179, v179) + sstore(178, v178) + sstore(177, v177) + sstore(176, v176) + sstore(175, v175) + sstore(174, v174) + sstore(173, v173) + sstore(172, v172) + sstore(171, v171) + sstore(170, v170) + sstore(169, v169) + sstore(168, v168) + sstore(167, v167) + sstore(166, v166) + sstore(165, v165) + sstore(164, v164) + sstore(163, v163) + sstore(162, v162) + sstore(161, v161) + sstore(160, v160) + sstore(159, v159) + sstore(158, v158) + sstore(157, v157) + sstore(156, v156) + sstore(155, v155) + sstore(154, v154) + sstore(153, v153) + sstore(152, v152) + sstore(151, v151) + sstore(150, v150) + sstore(149, v149) + sstore(148, v148) + sstore(147, v147) + sstore(146, v146) + sstore(145, v145) + sstore(144, v144) + sstore(143, v143) + sstore(142, v142) + sstore(141, v141) + sstore(140, v140) + sstore(139, v139) + sstore(138, v138) + sstore(137, v137) + sstore(136, v136) + sstore(135, v135) + sstore(134, v134) + sstore(133, v133) + sstore(132, v132) + sstore(131, v131) + sstore(130, v130) + sstore(129, v129) + sstore(128, v128) + sstore(127, v127) + sstore(126, v126) + sstore(125, v125) + sstore(124, v124) + sstore(123, v123) + sstore(122, v122) + sstore(121, v121) + sstore(120, v120) + sstore(119, v119) + sstore(118, v118) + sstore(117, v117) + sstore(116, v116) + sstore(115, v115) + sstore(114, v114) + sstore(113, v113) + sstore(112, v112) + sstore(111, v111) + sstore(110, v110) + sstore(109, v109) + sstore(108, v108) + sstore(107, v107) + sstore(106, v106) + sstore(105, v105) + sstore(104, v104) + sstore(103, v103) + sstore(102, v102) + sstore(101, v101) + sstore(100, v100) + sstore(99, v99) + sstore(98, v98) + sstore(97, v97) + sstore(96, v96) + sstore(95, v95) + sstore(94, v94) + sstore(93, v93) + sstore(92, v92) + sstore(91, v91) + sstore(90, v90) + sstore(89, v89) + sstore(88, v88) + sstore(87, v87) + sstore(86, v86) + sstore(85, v85) + sstore(84, v84) + sstore(83, v83) + sstore(82, v82) + sstore(81, v81) + sstore(80, v80) + sstore(79, v79) + sstore(78, v78) + sstore(77, v77) + sstore(76, v76) + sstore(75, v75) + sstore(74, v74) + sstore(73, v73) + sstore(72, v72) + sstore(71, v71) + sstore(70, v70) + sstore(69, v69) + sstore(68, v68) + sstore(67, v67) + sstore(66, v66) + sstore(65, v65) + sstore(64, v64) + sstore(63, v63) + sstore(62, v62) + sstore(61, v61) + sstore(60, v60) + sstore(59, v59) + sstore(58, v58) + sstore(57, v57) + sstore(56, v56) + sstore(55, v55) + sstore(54, v54) + sstore(53, v53) + sstore(52, v52) + sstore(51, v51) + sstore(50, v50) + sstore(49, v49) + sstore(48, v48) + sstore(47, v47) + sstore(46, v46) + sstore(45, v45) + sstore(44, v44) + sstore(43, v43) + sstore(42, v42) + sstore(41, v41) + sstore(40, v40) + sstore(39, v39) + sstore(38, v38) + sstore(37, v37) + sstore(36, v36) + sstore(35, v35) + sstore(34, v34) + sstore(33, v33) + sstore(32, v32) + sstore(31, v31) + sstore(30, v30) + sstore(29, v29) + sstore(28, v28) + sstore(27, v27) + sstore(26, v26) + sstore(25, v25) + sstore(24, v24) + sstore(23, v23) + sstore(22, v22) + sstore(21, v21) + sstore(20, v20) + sstore(19, v19) + sstore(18, v18) + sstore(17, v17) + sstore(16, v16) + sstore(15, v15) + sstore(14, v14) + sstore(13, v13) + sstore(12, v12) + sstore(11, v11) + sstore(10, v10) + sstore(9, v9) + sstore(8, v8) + sstore(7, v7) + sstore(6, v6) + sstore(5, v5) + sstore(4, v4) + sstore(3, v3) + sstore(2, v2) + sstore(1, v1) + sstore(0, v0) + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// stackOptimization: true +// ---- +// /* "":58:59 */ +// 0x00 +// /* "":45:60 */ +// calldataload +// /* "":92:93 */ +// 0x01 +// /* "":79:94 */ +// calldataload +// /* "":126:127 */ +// 0x02 +// /* "":113:128 */ +// calldataload +// /* "":160:161 */ +// 0x03 +// /* "":147:162 */ +// calldataload +// /* "":194:195 */ +// 0x04 +// /* "":181:196 */ +// calldataload +// /* "":228:229 */ +// 0x05 +// /* "":215:230 */ +// calldataload +// /* "":262:263 */ +// 0x06 +// /* "":249:264 */ +// calldataload +// /* "":296:297 */ +// 0x07 +// /* "":283:298 */ +// calldataload +// /* "":330:331 */ +// 0x08 +// /* "":317:332 */ +// calldataload +// /* "":364:365 */ +// 0x09 +// /* "":351:366 */ +// calldataload +// /* "":399:401 */ +// 0x0a +// /* "":386:402 */ +// calldataload +// /* "":435:437 */ +// 0x0b +// /* "":422:438 */ +// calldataload +// /* "":471:473 */ +// 0x0c +// /* "":458:474 */ +// calldataload +// /* "":507:509 */ +// 0x0d +// /* "":494:510 */ +// calldataload +// /* "":543:545 */ +// 0x0e +// /* "":530:546 */ +// calldataload +// /* "":579:581 */ +// 0x0f +// /* "":566:582 */ +// calldataload +// /* "":615:617 */ +// 0x10 +// /* "":602:618 */ +// calldataload +// /* "":651:653 */ +// 0x11 +// /* "":638:654 */ +// calldataload +// /* "":687:689 */ +// 0x12 +// /* "":674:690 */ +// calldataload +// /* "":723:725 */ +// 0x13 +// /* "":710:726 */ +// calldataload +// /* "":759:761 */ +// 0x14 +// /* "":746:762 */ +// calldataload +// /* "":795:797 */ +// 0x15 +// /* "":782:798 */ +// calldataload +// /* "":831:833 */ +// 0x16 +// /* "":818:834 */ +// calldataload +// /* "":867:869 */ +// 0x17 +// /* "":854:870 */ +// calldataload +// /* "":903:905 */ +// 0x18 +// /* "":890:906 */ +// calldataload +// /* "":939:941 */ +// 0x19 +// /* "":926:942 */ +// calldataload +// /* "":975:977 */ +// 0x1a +// /* "":962:978 */ +// calldataload +// /* "":1011:1013 */ +// 0x1b +// /* "":998:1014 */ +// calldataload +// /* "":1047:1049 */ +// 0x1c +// /* "":1034:1050 */ +// calldataload +// /* "":1083:1085 */ +// 0x1d +// /* "":1070:1086 */ +// calldataload +// /* "":1119:1121 */ +// 0x1e +// /* "":1106:1122 */ +// calldataload +// /* "":1155:1157 */ +// 0x1f +// /* "":1142:1158 */ +// calldataload +// /* "":1191:1193 */ +// 0x20 +// /* "":1178:1194 */ +// calldataload +// /* "":1227:1229 */ +// 0x21 +// /* "":1214:1230 */ +// calldataload +// /* "":1263:1265 */ +// 0x22 +// /* "":1250:1266 */ +// calldataload +// /* "":1299:1301 */ +// 0x23 +// /* "":1286:1302 */ +// calldataload +// /* "":1335:1337 */ +// 0x24 +// /* "":1322:1338 */ +// calldataload +// /* "":1371:1373 */ +// 0x25 +// /* "":1358:1374 */ +// calldataload +// /* "":1407:1409 */ +// 0x26 +// /* "":1394:1410 */ +// calldataload +// /* "":1443:1445 */ +// 0x27 +// /* "":1430:1446 */ +// calldataload +// /* "":1479:1481 */ +// 0x28 +// /* "":1466:1482 */ +// calldataload +// /* "":1515:1517 */ +// 0x29 +// /* "":1502:1518 */ +// calldataload +// /* "":1551:1553 */ +// 0x2a +// /* "":1538:1554 */ +// calldataload +// /* "":1587:1589 */ +// 0x2b +// /* "":1574:1590 */ +// calldataload +// /* "":1623:1625 */ +// 0x2c +// /* "":1610:1626 */ +// calldataload +// /* "":1659:1661 */ +// 0x2d +// /* "":1646:1662 */ +// calldataload +// /* "":1695:1697 */ +// 0x2e +// /* "":1682:1698 */ +// calldataload +// /* "":1731:1733 */ +// 0x2f +// /* "":1718:1734 */ +// calldataload +// /* "":1767:1769 */ +// 0x30 +// /* "":1754:1770 */ +// calldataload +// /* "":1803:1805 */ +// 0x31 +// /* "":1790:1806 */ +// calldataload +// /* "":1839:1841 */ +// 0x32 +// /* "":1826:1842 */ +// calldataload +// /* "":1875:1877 */ +// 0x33 +// /* "":1862:1878 */ +// calldataload +// /* "":1911:1913 */ +// 0x34 +// /* "":1898:1914 */ +// calldataload +// /* "":1947:1949 */ +// 0x35 +// /* "":1934:1950 */ +// calldataload +// /* "":1983:1985 */ +// 0x36 +// /* "":1970:1986 */ +// calldataload +// /* "":2019:2021 */ +// 0x37 +// /* "":2006:2022 */ +// calldataload +// /* "":2055:2057 */ +// 0x38 +// /* "":2042:2058 */ +// calldataload +// /* "":2091:2093 */ +// 0x39 +// /* "":2078:2094 */ +// calldataload +// /* "":2127:2129 */ +// 0x3a +// /* "":2114:2130 */ +// calldataload +// /* "":2163:2165 */ +// 0x3b +// /* "":2150:2166 */ +// calldataload +// /* "":2199:2201 */ +// 0x3c +// /* "":2186:2202 */ +// calldataload +// /* "":2235:2237 */ +// 0x3d +// /* "":2222:2238 */ +// calldataload +// /* "":2271:2273 */ +// 0x3e +// /* "":2258:2274 */ +// calldataload +// /* "":2307:2309 */ +// 0x3f +// /* "":2294:2310 */ +// calldataload +// /* "":2343:2345 */ +// 0x40 +// /* "":2330:2346 */ +// calldataload +// /* "":2379:2381 */ +// 0x41 +// /* "":2366:2382 */ +// calldataload +// /* "":2415:2417 */ +// 0x42 +// /* "":2402:2418 */ +// calldataload +// /* "":2451:2453 */ +// 0x43 +// /* "":2438:2454 */ +// calldataload +// /* "":2487:2489 */ +// 0x44 +// /* "":2474:2490 */ +// calldataload +// /* "":2523:2525 */ +// 0x45 +// /* "":2510:2526 */ +// calldataload +// /* "":2559:2561 */ +// 0x46 +// /* "":2546:2562 */ +// calldataload +// /* "":2595:2597 */ +// 0x47 +// /* "":2582:2598 */ +// calldataload +// /* "":2631:2633 */ +// 0x48 +// /* "":2618:2634 */ +// calldataload +// /* "":2667:2669 */ +// 0x49 +// /* "":2654:2670 */ +// calldataload +// /* "":2703:2705 */ +// 0x4a +// /* "":2690:2706 */ +// calldataload +// /* "":2739:2741 */ +// 0x4b +// /* "":2726:2742 */ +// calldataload +// /* "":2775:2777 */ +// 0x4c +// /* "":2762:2778 */ +// calldataload +// /* "":2811:2813 */ +// 0x4d +// /* "":2798:2814 */ +// calldataload +// /* "":2847:2849 */ +// 0x4e +// /* "":2834:2850 */ +// calldataload +// /* "":2883:2885 */ +// 0x4f +// /* "":2870:2886 */ +// calldataload +// /* "":2919:2921 */ +// 0x50 +// /* "":2906:2922 */ +// calldataload +// /* "":2955:2957 */ +// 0x51 +// /* "":2942:2958 */ +// calldataload +// /* "":2991:2993 */ +// 0x52 +// /* "":2978:2994 */ +// calldataload +// /* "":3027:3029 */ +// 0x53 +// /* "":3014:3030 */ +// calldataload +// /* "":3063:3065 */ +// 0x54 +// /* "":3050:3066 */ +// calldataload +// /* "":3099:3101 */ +// 0x55 +// /* "":3086:3102 */ +// calldataload +// /* "":3135:3137 */ +// 0x56 +// /* "":3122:3138 */ +// calldataload +// /* "":3171:3173 */ +// 0x57 +// /* "":3158:3174 */ +// calldataload +// /* "":3207:3209 */ +// 0x58 +// /* "":3194:3210 */ +// calldataload +// /* "":3243:3245 */ +// 0x59 +// /* "":3230:3246 */ +// calldataload +// /* "":3279:3281 */ +// 0x5a +// /* "":3266:3282 */ +// calldataload +// /* "":3315:3317 */ +// 0x5b +// /* "":3302:3318 */ +// calldataload +// /* "":3351:3353 */ +// 0x5c +// /* "":3338:3354 */ +// calldataload +// /* "":3387:3389 */ +// 0x5d +// /* "":3374:3390 */ +// calldataload +// /* "":3423:3425 */ +// 0x5e +// /* "":3410:3426 */ +// calldataload +// /* "":3459:3461 */ +// 0x5f +// /* "":3446:3462 */ +// calldataload +// /* "":3495:3497 */ +// 0x60 +// /* "":3482:3498 */ +// calldataload +// /* "":3531:3533 */ +// 0x61 +// /* "":3518:3534 */ +// calldataload +// /* "":3567:3569 */ +// 0x62 +// /* "":3554:3570 */ +// calldataload +// /* "":3603:3605 */ +// 0x63 +// /* "":3590:3606 */ +// calldataload +// /* "":3640:3643 */ +// 0x64 +// /* "":3627:3644 */ +// calldataload +// /* "":3678:3681 */ +// 0x65 +// /* "":3665:3682 */ +// calldataload +// /* "":3716:3719 */ +// 0x66 +// /* "":3703:3720 */ +// calldataload +// /* "":3754:3757 */ +// 0x67 +// /* "":3741:3758 */ +// calldataload +// /* "":3792:3795 */ +// 0x68 +// /* "":3779:3796 */ +// calldataload +// /* "":3830:3833 */ +// 0x69 +// /* "":3817:3834 */ +// calldataload +// /* "":3868:3871 */ +// 0x6a +// /* "":3855:3872 */ +// calldataload +// /* "":3906:3909 */ +// 0x6b +// /* "":3893:3910 */ +// calldataload +// /* "":3944:3947 */ +// 0x6c +// /* "":3931:3948 */ +// calldataload +// /* "":3982:3985 */ +// 0x6d +// /* "":3969:3986 */ +// calldataload +// /* "":4020:4023 */ +// 0x6e +// /* "":4007:4024 */ +// calldataload +// /* "":4058:4061 */ +// 0x6f +// /* "":4045:4062 */ +// calldataload +// /* "":4096:4099 */ +// 0x70 +// /* "":4083:4100 */ +// calldataload +// /* "":4134:4137 */ +// 0x71 +// /* "":4121:4138 */ +// calldataload +// /* "":4172:4175 */ +// 0x72 +// /* "":4159:4176 */ +// calldataload +// /* "":4210:4213 */ +// 0x73 +// /* "":4197:4214 */ +// calldataload +// /* "":4248:4251 */ +// 0x74 +// /* "":4235:4252 */ +// calldataload +// /* "":4286:4289 */ +// 0x75 +// /* "":4273:4290 */ +// calldataload +// /* "":4324:4327 */ +// 0x76 +// /* "":4311:4328 */ +// calldataload +// /* "":4362:4365 */ +// 0x77 +// /* "":4349:4366 */ +// calldataload +// /* "":4400:4403 */ +// 0x78 +// /* "":4387:4404 */ +// calldataload +// /* "":4438:4441 */ +// 0x79 +// /* "":4425:4442 */ +// calldataload +// /* "":4476:4479 */ +// 0x7a +// /* "":4463:4480 */ +// calldataload +// /* "":4514:4517 */ +// 0x7b +// /* "":4501:4518 */ +// calldataload +// /* "":4552:4555 */ +// 0x7c +// /* "":4539:4556 */ +// calldataload +// /* "":4590:4593 */ +// 0x7d +// /* "":4577:4594 */ +// calldataload +// /* "":4628:4631 */ +// 0x7e +// /* "":4615:4632 */ +// calldataload +// /* "":4666:4669 */ +// 0x7f +// /* "":4653:4670 */ +// calldataload +// /* "":4704:4707 */ +// 0x80 +// /* "":4691:4708 */ +// calldataload +// /* "":4742:4745 */ +// 0x81 +// /* "":4729:4746 */ +// calldataload +// /* "":4780:4783 */ +// 0x82 +// /* "":4767:4784 */ +// calldataload +// /* "":4818:4821 */ +// 0x83 +// /* "":4805:4822 */ +// calldataload +// /* "":4856:4859 */ +// 0x84 +// /* "":4843:4860 */ +// calldataload +// /* "":4894:4897 */ +// 0x85 +// /* "":4881:4898 */ +// calldataload +// /* "":4932:4935 */ +// 0x86 +// /* "":4919:4936 */ +// calldataload +// /* "":4970:4973 */ +// 0x87 +// /* "":4957:4974 */ +// calldataload +// /* "":5008:5011 */ +// 0x88 +// /* "":4995:5012 */ +// calldataload +// /* "":5046:5049 */ +// 0x89 +// /* "":5033:5050 */ +// calldataload +// /* "":5084:5087 */ +// 0x8a +// /* "":5071:5088 */ +// calldataload +// /* "":5122:5125 */ +// 0x8b +// /* "":5109:5126 */ +// calldataload +// /* "":5160:5163 */ +// 0x8c +// /* "":5147:5164 */ +// calldataload +// /* "":5198:5201 */ +// 0x8d +// /* "":5185:5202 */ +// calldataload +// /* "":5236:5239 */ +// 0x8e +// /* "":5223:5240 */ +// calldataload +// /* "":5274:5277 */ +// 0x8f +// /* "":5261:5278 */ +// calldataload +// /* "":5312:5315 */ +// 0x90 +// /* "":5299:5316 */ +// calldataload +// /* "":5350:5353 */ +// 0x91 +// /* "":5337:5354 */ +// calldataload +// /* "":5388:5391 */ +// 0x92 +// /* "":5375:5392 */ +// calldataload +// /* "":5426:5429 */ +// 0x93 +// /* "":5413:5430 */ +// calldataload +// /* "":5464:5467 */ +// 0x94 +// /* "":5451:5468 */ +// calldataload +// /* "":5502:5505 */ +// 0x95 +// /* "":5489:5506 */ +// calldataload +// /* "":5540:5543 */ +// 0x96 +// /* "":5527:5544 */ +// calldataload +// /* "":5578:5581 */ +// 0x97 +// /* "":5565:5582 */ +// calldataload +// /* "":5616:5619 */ +// 0x98 +// /* "":5603:5620 */ +// calldataload +// /* "":5654:5657 */ +// 0x99 +// /* "":5641:5658 */ +// calldataload +// /* "":5692:5695 */ +// 0x9a +// /* "":5679:5696 */ +// calldataload +// /* "":5730:5733 */ +// 0x9b +// /* "":5717:5734 */ +// calldataload +// /* "":5768:5771 */ +// 0x9c +// /* "":5755:5772 */ +// calldataload +// /* "":5806:5809 */ +// 0x9d +// /* "":5793:5810 */ +// calldataload +// /* "":5844:5847 */ +// 0x9e +// /* "":5831:5848 */ +// calldataload +// /* "":5882:5885 */ +// 0x9f +// /* "":5869:5886 */ +// calldataload +// /* "":5920:5923 */ +// 0xa0 +// /* "":5907:5924 */ +// calldataload +// /* "":5958:5961 */ +// 0xa1 +// /* "":5945:5962 */ +// calldataload +// /* "":5996:5999 */ +// 0xa2 +// /* "":5983:6000 */ +// calldataload +// /* "":6034:6037 */ +// 0xa3 +// /* "":6021:6038 */ +// calldataload +// /* "":6072:6075 */ +// 0xa4 +// /* "":6059:6076 */ +// calldataload +// /* "":6110:6113 */ +// 0xa5 +// /* "":6097:6114 */ +// calldataload +// /* "":6148:6151 */ +// 0xa6 +// /* "":6135:6152 */ +// calldataload +// /* "":6186:6189 */ +// 0xa7 +// /* "":6173:6190 */ +// calldataload +// /* "":6224:6227 */ +// 0xa8 +// /* "":6211:6228 */ +// calldataload +// /* "":6262:6265 */ +// 0xa9 +// /* "":6249:6266 */ +// calldataload +// /* "":6300:6303 */ +// 0xaa +// /* "":6287:6304 */ +// calldataload +// /* "":6338:6341 */ +// 0xab +// /* "":6325:6342 */ +// calldataload +// /* "":6376:6379 */ +// 0xac +// /* "":6363:6380 */ +// calldataload +// /* "":6414:6417 */ +// 0xad +// /* "":6401:6418 */ +// calldataload +// /* "":6452:6455 */ +// 0xae +// /* "":6439:6456 */ +// calldataload +// /* "":6490:6493 */ +// 0xaf +// /* "":6477:6494 */ +// calldataload +// /* "":6528:6531 */ +// 0xb0 +// /* "":6515:6532 */ +// calldataload +// /* "":6566:6569 */ +// 0xb1 +// /* "":6553:6570 */ +// calldataload +// /* "":6604:6607 */ +// 0xb2 +// /* "":6591:6608 */ +// calldataload +// /* "":6642:6645 */ +// 0xb3 +// /* "":6629:6646 */ +// calldataload +// /* "":6680:6683 */ +// 0xb4 +// /* "":6667:6684 */ +// calldataload +// /* "":6718:6721 */ +// 0xb5 +// /* "":6705:6722 */ +// calldataload +// /* "":6756:6759 */ +// 0xb6 +// /* "":6743:6760 */ +// calldataload +// /* "":6794:6797 */ +// 0xb7 +// /* "":6781:6798 */ +// calldataload +// /* "":6832:6835 */ +// 0xb8 +// /* "":6819:6836 */ +// calldataload +// /* "":6870:6873 */ +// 0xb9 +// /* "":6857:6874 */ +// calldataload +// /* "":6908:6911 */ +// 0xba +// /* "":6895:6912 */ +// calldataload +// /* "":6946:6949 */ +// 0xbb +// /* "":6933:6950 */ +// calldataload +// /* "":6984:6987 */ +// 0xbc +// /* "":6971:6988 */ +// calldataload +// /* "":7022:7025 */ +// 0xbd +// /* "":7009:7026 */ +// calldataload +// /* "":7060:7063 */ +// 0xbe +// /* "":7047:7064 */ +// calldataload +// /* "":7098:7101 */ +// 0xbf +// /* "":7085:7102 */ +// calldataload +// /* "":7136:7139 */ +// 0xc0 +// /* "":7123:7140 */ +// calldataload +// /* "":7174:7177 */ +// 0xc1 +// /* "":7161:7178 */ +// calldataload +// /* "":7212:7215 */ +// 0xc2 +// /* "":7199:7216 */ +// calldataload +// /* "":7250:7253 */ +// 0xc3 +// /* "":7237:7254 */ +// calldataload +// /* "":7288:7291 */ +// 0xc4 +// /* "":7275:7292 */ +// calldataload +// /* "":7326:7329 */ +// 0xc5 +// /* "":7313:7330 */ +// calldataload +// /* "":7364:7367 */ +// 0xc6 +// /* "":7351:7368 */ +// calldataload +// /* "":7402:7405 */ +// 0xc7 +// /* "":7389:7406 */ +// calldataload +// /* "":7440:7443 */ +// 0xc8 +// /* "":7427:7444 */ +// calldataload +// /* "":7478:7481 */ +// 0xc9 +// /* "":7465:7482 */ +// calldataload +// /* "":7516:7519 */ +// 0xca +// /* "":7503:7520 */ +// calldataload +// /* "":7554:7557 */ +// 0xcb +// /* "":7541:7558 */ +// calldataload +// /* "":7592:7595 */ +// 0xcc +// /* "":7579:7596 */ +// calldataload +// /* "":7630:7633 */ +// 0xcd +// /* "":7617:7634 */ +// calldataload +// /* "":7668:7671 */ +// 0xce +// /* "":7655:7672 */ +// calldataload +// /* "":7706:7709 */ +// 0xcf +// /* "":7693:7710 */ +// calldataload +// /* "":7744:7747 */ +// 0xd0 +// /* "":7731:7748 */ +// calldataload +// /* "":7782:7785 */ +// 0xd1 +// /* "":7769:7786 */ +// calldataload +// /* "":7820:7823 */ +// 0xd2 +// /* "":7807:7824 */ +// calldataload +// /* "":7858:7861 */ +// 0xd3 +// /* "":7845:7862 */ +// calldataload +// /* "":7896:7899 */ +// 0xd4 +// /* "":7883:7900 */ +// calldataload +// /* "":7934:7937 */ +// 0xd5 +// /* "":7921:7938 */ +// calldataload +// /* "":7972:7975 */ +// 0xd6 +// /* "":7959:7976 */ +// calldataload +// /* "":8010:8013 */ +// 0xd7 +// /* "":7997:8014 */ +// calldataload +// /* "":8048:8051 */ +// 0xd8 +// /* "":8035:8052 */ +// calldataload +// /* "":8086:8089 */ +// 0xd9 +// /* "":8073:8090 */ +// calldataload +// /* "":8124:8127 */ +// 0xda +// /* "":8111:8128 */ +// calldataload +// /* "":8162:8165 */ +// 0xdb +// /* "":8149:8166 */ +// calldataload +// /* "":8200:8203 */ +// 0xdc +// /* "":8187:8204 */ +// calldataload +// /* "":8238:8241 */ +// 0xdd +// /* "":8225:8242 */ +// calldataload +// /* "":8276:8279 */ +// 0xde +// /* "":8263:8280 */ +// calldataload +// /* "":8314:8317 */ +// 0xdf +// /* "":8301:8318 */ +// calldataload +// /* "":8352:8355 */ +// 0xe0 +// /* "":8339:8356 */ +// calldataload +// /* "":8390:8393 */ +// 0xe1 +// /* "":8377:8394 */ +// calldataload +// /* "":8428:8431 */ +// 0xe2 +// /* "":8415:8432 */ +// calldataload +// /* "":8466:8469 */ +// 0xe3 +// /* "":8453:8470 */ +// calldataload +// /* "":8504:8507 */ +// 0xe4 +// /* "":8491:8508 */ +// calldataload +// /* "":8542:8545 */ +// 0xe5 +// /* "":8529:8546 */ +// calldataload +// /* "":8580:8583 */ +// 0xe6 +// /* "":8567:8584 */ +// calldataload +// /* "":8618:8621 */ +// 0xe7 +// /* "":8605:8622 */ +// calldataload +// /* "":8656:8659 */ +// 0xe8 +// /* "":8643:8660 */ +// calldataload +// /* "":8694:8697 */ +// 0xe9 +// /* "":8681:8698 */ +// calldataload +// /* "":8732:8735 */ +// 0xea +// /* "":8719:8736 */ +// calldataload +// /* "":8770:8773 */ +// 0xeb +// /* "":8757:8774 */ +// calldataload +// /* "":8808:8811 */ +// 0xec +// /* "":8795:8812 */ +// calldataload +// /* "":8846:8849 */ +// 0xed +// /* "":8833:8850 */ +// calldataload +// /* "":8884:8887 */ +// 0xee +// /* "":8871:8888 */ +// calldataload +// /* "":8922:8925 */ +// 0xef +// /* "":8909:8926 */ +// calldataload +// /* "":8960:8963 */ +// 0xf0 +// /* "":8947:8964 */ +// calldataload +// /* "":8998:9001 */ +// 0xf1 +// /* "":8985:9002 */ +// calldataload +// /* "":9036:9039 */ +// 0xf2 +// /* "":9023:9040 */ +// calldataload +// /* "":9074:9077 */ +// 0xf3 +// /* "":9061:9078 */ +// calldataload +// /* "":9112:9115 */ +// 0xf4 +// /* "":9099:9116 */ +// calldataload +// /* "":9150:9153 */ +// 0xf5 +// /* "":9137:9154 */ +// calldataload +// /* "":9188:9191 */ +// 0xf6 +// /* "":9175:9192 */ +// calldataload +// /* "":9226:9229 */ +// 0xf7 +// /* "":9213:9230 */ +// calldataload +// /* "":9264:9267 */ +// 0xf8 +// /* "":9251:9268 */ +// calldataload +// /* "":9302:9305 */ +// 0xf9 +// /* "":9289:9306 */ +// calldataload +// /* "":9340:9343 */ +// 0xfa +// /* "":9327:9344 */ +// calldataload +// /* "":9378:9381 */ +// 0xfb +// /* "":9365:9382 */ +// calldataload +// /* "":9416:9419 */ +// 0xfc +// /* "":9403:9420 */ +// calldataload +// /* "":9454:9457 */ +// 0xfd +// /* "":9441:9458 */ +// calldataload +// /* "":9492:9495 */ +// 0xfe +// /* "":9479:9496 */ +// calldataload +// /* "":9530:9533 */ +// 0xff +// /* "":9517:9534 */ +// calldataload +// /* "":9795:9798 */ +// 0x0100 +// /* "":9782:9799 */ +// calldataload +// /* "":9779:9815 */ +// rjumpi{tag_1} +// /* "":25:16281 */ +// tag_2: +// /* "":9824:9839 */ +// dupn{256} +// /* "":9831:9834 */ +// 0x0100 +// /* "":9824:9839 */ +// sstore +// /* "":9855:9858 */ +// 0xff +// /* "":9848:9865 */ +// sstore +// /* "":9881:9884 */ +// 0xfe +// /* "":9874:9891 */ +// sstore +// /* "":9907:9910 */ +// 0xfd +// /* "":9900:9917 */ +// sstore +// /* "":9933:9936 */ +// 0xfc +// /* "":9926:9943 */ +// sstore +// /* "":9959:9962 */ +// 0xfb +// /* "":9952:9969 */ +// sstore +// /* "":9985:9988 */ +// 0xfa +// /* "":9978:9995 */ +// sstore +// /* "":10011:10014 */ +// 0xf9 +// /* "":10004:10021 */ +// sstore +// /* "":10037:10040 */ +// 0xf8 +// /* "":10030:10047 */ +// sstore +// /* "":10063:10066 */ +// 0xf7 +// /* "":10056:10073 */ +// sstore +// /* "":10089:10092 */ +// 0xf6 +// /* "":10082:10099 */ +// sstore +// /* "":10115:10118 */ +// 0xf5 +// /* "":10108:10125 */ +// sstore +// /* "":10141:10144 */ +// 0xf4 +// /* "":10134:10151 */ +// sstore +// /* "":10167:10170 */ +// 0xf3 +// /* "":10160:10177 */ +// sstore +// /* "":10193:10196 */ +// 0xf2 +// /* "":10186:10203 */ +// sstore +// /* "":10219:10222 */ +// 0xf1 +// /* "":10212:10229 */ +// sstore +// /* "":10245:10248 */ +// 0xf0 +// /* "":10238:10255 */ +// sstore +// /* "":10271:10274 */ +// 0xef +// /* "":10264:10281 */ +// sstore +// /* "":10297:10300 */ +// 0xee +// /* "":10290:10307 */ +// sstore +// /* "":10323:10326 */ +// 0xed +// /* "":10316:10333 */ +// sstore +// /* "":10349:10352 */ +// 0xec +// /* "":10342:10359 */ +// sstore +// /* "":10375:10378 */ +// 0xeb +// /* "":10368:10385 */ +// sstore +// /* "":10401:10404 */ +// 0xea +// /* "":10394:10411 */ +// sstore +// /* "":10427:10430 */ +// 0xe9 +// /* "":10420:10437 */ +// sstore +// /* "":10453:10456 */ +// 0xe8 +// /* "":10446:10463 */ +// sstore +// /* "":10479:10482 */ +// 0xe7 +// /* "":10472:10489 */ +// sstore +// /* "":10505:10508 */ +// 0xe6 +// /* "":10498:10515 */ +// sstore +// /* "":10531:10534 */ +// 0xe5 +// /* "":10524:10541 */ +// sstore +// /* "":10557:10560 */ +// 0xe4 +// /* "":10550:10567 */ +// sstore +// /* "":10583:10586 */ +// 0xe3 +// /* "":10576:10593 */ +// sstore +// /* "":10609:10612 */ +// 0xe2 +// /* "":10602:10619 */ +// sstore +// /* "":10635:10638 */ +// 0xe1 +// /* "":10628:10645 */ +// sstore +// /* "":10661:10664 */ +// 0xe0 +// /* "":10654:10671 */ +// sstore +// /* "":10687:10690 */ +// 0xdf +// /* "":10680:10697 */ +// sstore +// /* "":10713:10716 */ +// 0xde +// /* "":10706:10723 */ +// sstore +// /* "":10739:10742 */ +// 0xdd +// /* "":10732:10749 */ +// sstore +// /* "":10765:10768 */ +// 0xdc +// /* "":10758:10775 */ +// sstore +// /* "":10791:10794 */ +// 0xdb +// /* "":10784:10801 */ +// sstore +// /* "":10817:10820 */ +// 0xda +// /* "":10810:10827 */ +// sstore +// /* "":10843:10846 */ +// 0xd9 +// /* "":10836:10853 */ +// sstore +// /* "":10869:10872 */ +// 0xd8 +// /* "":10862:10879 */ +// sstore +// /* "":10895:10898 */ +// 0xd7 +// /* "":10888:10905 */ +// sstore +// /* "":10921:10924 */ +// 0xd6 +// /* "":10914:10931 */ +// sstore +// /* "":10947:10950 */ +// 0xd5 +// /* "":10940:10957 */ +// sstore +// /* "":10973:10976 */ +// 0xd4 +// /* "":10966:10983 */ +// sstore +// /* "":10999:11002 */ +// 0xd3 +// /* "":10992:11009 */ +// sstore +// /* "":11025:11028 */ +// 0xd2 +// /* "":11018:11035 */ +// sstore +// /* "":11051:11054 */ +// 0xd1 +// /* "":11044:11061 */ +// sstore +// /* "":11077:11080 */ +// 0xd0 +// /* "":11070:11087 */ +// sstore +// /* "":11103:11106 */ +// 0xcf +// /* "":11096:11113 */ +// sstore +// /* "":11129:11132 */ +// 0xce +// /* "":11122:11139 */ +// sstore +// /* "":11155:11158 */ +// 0xcd +// /* "":11148:11165 */ +// sstore +// /* "":11181:11184 */ +// 0xcc +// /* "":11174:11191 */ +// sstore +// /* "":11207:11210 */ +// 0xcb +// /* "":11200:11217 */ +// sstore +// /* "":11233:11236 */ +// 0xca +// /* "":11226:11243 */ +// sstore +// /* "":11259:11262 */ +// 0xc9 +// /* "":11252:11269 */ +// sstore +// /* "":11285:11288 */ +// 0xc8 +// /* "":11278:11295 */ +// sstore +// /* "":11311:11314 */ +// 0xc7 +// /* "":11304:11321 */ +// sstore +// /* "":11337:11340 */ +// 0xc6 +// /* "":11330:11347 */ +// sstore +// /* "":11363:11366 */ +// 0xc5 +// /* "":11356:11373 */ +// sstore +// /* "":11389:11392 */ +// 0xc4 +// /* "":11382:11399 */ +// sstore +// /* "":11415:11418 */ +// 0xc3 +// /* "":11408:11425 */ +// sstore +// /* "":11441:11444 */ +// 0xc2 +// /* "":11434:11451 */ +// sstore +// /* "":11467:11470 */ +// 0xc1 +// /* "":11460:11477 */ +// sstore +// /* "":11493:11496 */ +// 0xc0 +// /* "":11486:11503 */ +// sstore +// /* "":11519:11522 */ +// 0xbf +// /* "":11512:11529 */ +// sstore +// /* "":11545:11548 */ +// 0xbe +// /* "":11538:11555 */ +// sstore +// /* "":11571:11574 */ +// 0xbd +// /* "":11564:11581 */ +// sstore +// /* "":11597:11600 */ +// 0xbc +// /* "":11590:11607 */ +// sstore +// /* "":11623:11626 */ +// 0xbb +// /* "":11616:11633 */ +// sstore +// /* "":11649:11652 */ +// 0xba +// /* "":11642:11659 */ +// sstore +// /* "":11675:11678 */ +// 0xb9 +// /* "":11668:11685 */ +// sstore +// /* "":11701:11704 */ +// 0xb8 +// /* "":11694:11711 */ +// sstore +// /* "":11727:11730 */ +// 0xb7 +// /* "":11720:11737 */ +// sstore +// /* "":11753:11756 */ +// 0xb6 +// /* "":11746:11763 */ +// sstore +// /* "":11779:11782 */ +// 0xb5 +// /* "":11772:11789 */ +// sstore +// /* "":11805:11808 */ +// 0xb4 +// /* "":11798:11815 */ +// sstore +// /* "":11831:11834 */ +// 0xb3 +// /* "":11824:11841 */ +// sstore +// /* "":11857:11860 */ +// 0xb2 +// /* "":11850:11867 */ +// sstore +// /* "":11883:11886 */ +// 0xb1 +// /* "":11876:11893 */ +// sstore +// /* "":11909:11912 */ +// 0xb0 +// /* "":11902:11919 */ +// sstore +// /* "":11935:11938 */ +// 0xaf +// /* "":11928:11945 */ +// sstore +// /* "":11961:11964 */ +// 0xae +// /* "":11954:11971 */ +// sstore +// /* "":11987:11990 */ +// 0xad +// /* "":11980:11997 */ +// sstore +// /* "":12013:12016 */ +// 0xac +// /* "":12006:12023 */ +// sstore +// /* "":12039:12042 */ +// 0xab +// /* "":12032:12049 */ +// sstore +// /* "":12065:12068 */ +// 0xaa +// /* "":12058:12075 */ +// sstore +// /* "":12091:12094 */ +// 0xa9 +// /* "":12084:12101 */ +// sstore +// /* "":12117:12120 */ +// 0xa8 +// /* "":12110:12127 */ +// sstore +// /* "":12143:12146 */ +// 0xa7 +// /* "":12136:12153 */ +// sstore +// /* "":12169:12172 */ +// 0xa6 +// /* "":12162:12179 */ +// sstore +// /* "":12195:12198 */ +// 0xa5 +// /* "":12188:12205 */ +// sstore +// /* "":12221:12224 */ +// 0xa4 +// /* "":12214:12231 */ +// sstore +// /* "":12247:12250 */ +// 0xa3 +// /* "":12240:12257 */ +// sstore +// /* "":12273:12276 */ +// 0xa2 +// /* "":12266:12283 */ +// sstore +// /* "":12299:12302 */ +// 0xa1 +// /* "":12292:12309 */ +// sstore +// /* "":12325:12328 */ +// 0xa0 +// /* "":12318:12335 */ +// sstore +// /* "":12351:12354 */ +// 0x9f +// /* "":12344:12361 */ +// sstore +// /* "":12377:12380 */ +// 0x9e +// /* "":12370:12387 */ +// sstore +// /* "":12403:12406 */ +// 0x9d +// /* "":12396:12413 */ +// sstore +// /* "":12429:12432 */ +// 0x9c +// /* "":12422:12439 */ +// sstore +// /* "":12455:12458 */ +// 0x9b +// /* "":12448:12465 */ +// sstore +// /* "":12481:12484 */ +// 0x9a +// /* "":12474:12491 */ +// sstore +// /* "":12507:12510 */ +// 0x99 +// /* "":12500:12517 */ +// sstore +// /* "":12533:12536 */ +// 0x98 +// /* "":12526:12543 */ +// sstore +// /* "":12559:12562 */ +// 0x97 +// /* "":12552:12569 */ +// sstore +// /* "":12585:12588 */ +// 0x96 +// /* "":12578:12595 */ +// sstore +// /* "":12611:12614 */ +// 0x95 +// /* "":12604:12621 */ +// sstore +// /* "":12637:12640 */ +// 0x94 +// /* "":12630:12647 */ +// sstore +// /* "":12663:12666 */ +// 0x93 +// /* "":12656:12673 */ +// sstore +// /* "":12689:12692 */ +// 0x92 +// /* "":12682:12699 */ +// sstore +// /* "":12715:12718 */ +// 0x91 +// /* "":12708:12725 */ +// sstore +// /* "":12741:12744 */ +// 0x90 +// /* "":12734:12751 */ +// sstore +// /* "":12767:12770 */ +// 0x8f +// /* "":12760:12777 */ +// sstore +// /* "":12793:12796 */ +// 0x8e +// /* "":12786:12803 */ +// sstore +// /* "":12819:12822 */ +// 0x8d +// /* "":12812:12829 */ +// sstore +// /* "":12845:12848 */ +// 0x8c +// /* "":12838:12855 */ +// sstore +// /* "":12871:12874 */ +// 0x8b +// /* "":12864:12881 */ +// sstore +// /* "":12897:12900 */ +// 0x8a +// /* "":12890:12907 */ +// sstore +// /* "":12923:12926 */ +// 0x89 +// /* "":12916:12933 */ +// sstore +// /* "":12949:12952 */ +// 0x88 +// /* "":12942:12959 */ +// sstore +// /* "":12975:12978 */ +// 0x87 +// /* "":12968:12985 */ +// sstore +// /* "":13001:13004 */ +// 0x86 +// /* "":12994:13011 */ +// sstore +// /* "":13027:13030 */ +// 0x85 +// /* "":13020:13037 */ +// sstore +// /* "":13053:13056 */ +// 0x84 +// /* "":13046:13063 */ +// sstore +// /* "":13079:13082 */ +// 0x83 +// /* "":13072:13089 */ +// sstore +// /* "":13105:13108 */ +// 0x82 +// /* "":13098:13115 */ +// sstore +// /* "":13131:13134 */ +// 0x81 +// /* "":13124:13141 */ +// sstore +// /* "":13157:13160 */ +// 0x80 +// /* "":13150:13167 */ +// sstore +// /* "":13183:13186 */ +// 0x7f +// /* "":13176:13193 */ +// sstore +// /* "":13209:13212 */ +// 0x7e +// /* "":13202:13219 */ +// sstore +// /* "":13235:13238 */ +// 0x7d +// /* "":13228:13245 */ +// sstore +// /* "":13261:13264 */ +// 0x7c +// /* "":13254:13271 */ +// sstore +// /* "":13287:13290 */ +// 0x7b +// /* "":13280:13297 */ +// sstore +// /* "":13313:13316 */ +// 0x7a +// /* "":13306:13323 */ +// sstore +// /* "":13339:13342 */ +// 0x79 +// /* "":13332:13349 */ +// sstore +// /* "":13365:13368 */ +// 0x78 +// /* "":13358:13375 */ +// sstore +// /* "":13391:13394 */ +// 0x77 +// /* "":13384:13401 */ +// sstore +// /* "":13417:13420 */ +// 0x76 +// /* "":13410:13427 */ +// sstore +// /* "":13443:13446 */ +// 0x75 +// /* "":13436:13453 */ +// sstore +// /* "":13469:13472 */ +// 0x74 +// /* "":13462:13479 */ +// sstore +// /* "":13495:13498 */ +// 0x73 +// /* "":13488:13505 */ +// sstore +// /* "":13521:13524 */ +// 0x72 +// /* "":13514:13531 */ +// sstore +// /* "":13547:13550 */ +// 0x71 +// /* "":13540:13557 */ +// sstore +// /* "":13573:13576 */ +// 0x70 +// /* "":13566:13583 */ +// sstore +// /* "":13599:13602 */ +// 0x6f +// /* "":13592:13609 */ +// sstore +// /* "":13625:13628 */ +// 0x6e +// /* "":13618:13635 */ +// sstore +// /* "":13651:13654 */ +// 0x6d +// /* "":13644:13661 */ +// sstore +// /* "":13677:13680 */ +// 0x6c +// /* "":13670:13687 */ +// sstore +// /* "":13703:13706 */ +// 0x6b +// /* "":13696:13713 */ +// sstore +// /* "":13729:13732 */ +// 0x6a +// /* "":13722:13739 */ +// sstore +// /* "":13755:13758 */ +// 0x69 +// /* "":13748:13765 */ +// sstore +// /* "":13781:13784 */ +// 0x68 +// /* "":13774:13791 */ +// sstore +// /* "":13807:13810 */ +// 0x67 +// /* "":13800:13817 */ +// sstore +// /* "":13833:13836 */ +// 0x66 +// /* "":13826:13843 */ +// sstore +// /* "":13859:13862 */ +// 0x65 +// /* "":13852:13869 */ +// sstore +// /* "":13885:13888 */ +// 0x64 +// /* "":13878:13895 */ +// sstore +// /* "":13911:13913 */ +// 0x63 +// /* "":13904:13919 */ +// sstore +// /* "":13935:13937 */ +// 0x62 +// /* "":13928:13943 */ +// sstore +// /* "":13959:13961 */ +// 0x61 +// /* "":13952:13967 */ +// sstore +// /* "":13983:13985 */ +// 0x60 +// /* "":13976:13991 */ +// sstore +// /* "":14007:14009 */ +// 0x5f +// /* "":14000:14015 */ +// sstore +// /* "":14031:14033 */ +// 0x5e +// /* "":14024:14039 */ +// sstore +// /* "":14055:14057 */ +// 0x5d +// /* "":14048:14063 */ +// sstore +// /* "":14079:14081 */ +// 0x5c +// /* "":14072:14087 */ +// sstore +// /* "":14103:14105 */ +// 0x5b +// /* "":14096:14111 */ +// sstore +// /* "":14127:14129 */ +// 0x5a +// /* "":14120:14135 */ +// sstore +// /* "":14151:14153 */ +// 0x59 +// /* "":14144:14159 */ +// sstore +// /* "":14175:14177 */ +// 0x58 +// /* "":14168:14183 */ +// sstore +// /* "":14199:14201 */ +// 0x57 +// /* "":14192:14207 */ +// sstore +// /* "":14223:14225 */ +// 0x56 +// /* "":14216:14231 */ +// sstore +// /* "":14247:14249 */ +// 0x55 +// /* "":14240:14255 */ +// sstore +// /* "":14271:14273 */ +// 0x54 +// /* "":14264:14279 */ +// sstore +// /* "":14295:14297 */ +// 0x53 +// /* "":14288:14303 */ +// sstore +// /* "":14319:14321 */ +// 0x52 +// /* "":14312:14327 */ +// sstore +// /* "":14343:14345 */ +// 0x51 +// /* "":14336:14351 */ +// sstore +// /* "":14367:14369 */ +// 0x50 +// /* "":14360:14375 */ +// sstore +// /* "":14391:14393 */ +// 0x4f +// /* "":14384:14399 */ +// sstore +// /* "":14415:14417 */ +// 0x4e +// /* "":14408:14423 */ +// sstore +// /* "":14439:14441 */ +// 0x4d +// /* "":14432:14447 */ +// sstore +// /* "":14463:14465 */ +// 0x4c +// /* "":14456:14471 */ +// sstore +// /* "":14487:14489 */ +// 0x4b +// /* "":14480:14495 */ +// sstore +// /* "":14511:14513 */ +// 0x4a +// /* "":14504:14519 */ +// sstore +// /* "":14535:14537 */ +// 0x49 +// /* "":14528:14543 */ +// sstore +// /* "":14559:14561 */ +// 0x48 +// /* "":14552:14567 */ +// sstore +// /* "":14583:14585 */ +// 0x47 +// /* "":14576:14591 */ +// sstore +// /* "":14607:14609 */ +// 0x46 +// /* "":14600:14615 */ +// sstore +// /* "":14631:14633 */ +// 0x45 +// /* "":14624:14639 */ +// sstore +// /* "":14655:14657 */ +// 0x44 +// /* "":14648:14663 */ +// sstore +// /* "":14679:14681 */ +// 0x43 +// /* "":14672:14687 */ +// sstore +// /* "":14703:14705 */ +// 0x42 +// /* "":14696:14711 */ +// sstore +// /* "":14727:14729 */ +// 0x41 +// /* "":14720:14735 */ +// sstore +// /* "":14751:14753 */ +// 0x40 +// /* "":14744:14759 */ +// sstore +// /* "":14775:14777 */ +// 0x3f +// /* "":14768:14783 */ +// sstore +// /* "":14799:14801 */ +// 0x3e +// /* "":14792:14807 */ +// sstore +// /* "":14823:14825 */ +// 0x3d +// /* "":14816:14831 */ +// sstore +// /* "":14847:14849 */ +// 0x3c +// /* "":14840:14855 */ +// sstore +// /* "":14871:14873 */ +// 0x3b +// /* "":14864:14879 */ +// sstore +// /* "":14895:14897 */ +// 0x3a +// /* "":14888:14903 */ +// sstore +// /* "":14919:14921 */ +// 0x39 +// /* "":14912:14927 */ +// sstore +// /* "":14943:14945 */ +// 0x38 +// /* "":14936:14951 */ +// sstore +// /* "":14967:14969 */ +// 0x37 +// /* "":14960:14975 */ +// sstore +// /* "":14991:14993 */ +// 0x36 +// /* "":14984:14999 */ +// sstore +// /* "":15015:15017 */ +// 0x35 +// /* "":15008:15023 */ +// sstore +// /* "":15039:15041 */ +// 0x34 +// /* "":15032:15047 */ +// sstore +// /* "":15063:15065 */ +// 0x33 +// /* "":15056:15071 */ +// sstore +// /* "":15087:15089 */ +// 0x32 +// /* "":15080:15095 */ +// sstore +// /* "":15111:15113 */ +// 0x31 +// /* "":15104:15119 */ +// sstore +// /* "":15135:15137 */ +// 0x30 +// /* "":15128:15143 */ +// sstore +// /* "":15159:15161 */ +// 0x2f +// /* "":15152:15167 */ +// sstore +// /* "":15183:15185 */ +// 0x2e +// /* "":15176:15191 */ +// sstore +// /* "":15207:15209 */ +// 0x2d +// /* "":15200:15215 */ +// sstore +// /* "":15231:15233 */ +// 0x2c +// /* "":15224:15239 */ +// sstore +// /* "":15255:15257 */ +// 0x2b +// /* "":15248:15263 */ +// sstore +// /* "":15279:15281 */ +// 0x2a +// /* "":15272:15287 */ +// sstore +// /* "":15303:15305 */ +// 0x29 +// /* "":15296:15311 */ +// sstore +// /* "":15327:15329 */ +// 0x28 +// /* "":15320:15335 */ +// sstore +// /* "":15351:15353 */ +// 0x27 +// /* "":15344:15359 */ +// sstore +// /* "":15375:15377 */ +// 0x26 +// /* "":15368:15383 */ +// sstore +// /* "":15399:15401 */ +// 0x25 +// /* "":15392:15407 */ +// sstore +// /* "":15423:15425 */ +// 0x24 +// /* "":15416:15431 */ +// sstore +// /* "":15447:15449 */ +// 0x23 +// /* "":15440:15455 */ +// sstore +// /* "":15471:15473 */ +// 0x22 +// /* "":15464:15479 */ +// sstore +// /* "":15495:15497 */ +// 0x21 +// /* "":15488:15503 */ +// sstore +// /* "":15519:15521 */ +// 0x20 +// /* "":15512:15527 */ +// sstore +// /* "":15543:15545 */ +// 0x1f +// /* "":15536:15551 */ +// sstore +// /* "":15567:15569 */ +// 0x1e +// /* "":15560:15575 */ +// sstore +// /* "":15591:15593 */ +// 0x1d +// /* "":15584:15599 */ +// sstore +// /* "":15615:15617 */ +// 0x1c +// /* "":15608:15623 */ +// sstore +// /* "":15639:15641 */ +// 0x1b +// /* "":15632:15647 */ +// sstore +// /* "":15663:15665 */ +// 0x1a +// /* "":15656:15671 */ +// sstore +// /* "":15687:15689 */ +// 0x19 +// /* "":15680:15695 */ +// sstore +// /* "":15711:15713 */ +// 0x18 +// /* "":15704:15719 */ +// sstore +// /* "":15735:15737 */ +// 0x17 +// /* "":15728:15743 */ +// sstore +// /* "":15759:15761 */ +// 0x16 +// /* "":15752:15767 */ +// sstore +// /* "":15783:15785 */ +// 0x15 +// /* "":15776:15791 */ +// sstore +// /* "":15807:15809 */ +// 0x14 +// /* "":15800:15815 */ +// sstore +// /* "":15831:15833 */ +// 0x13 +// /* "":15824:15839 */ +// sstore +// /* "":15855:15857 */ +// 0x12 +// /* "":15848:15863 */ +// sstore +// /* "":15879:15881 */ +// 0x11 +// /* "":15872:15887 */ +// sstore +// /* "":15903:15905 */ +// 0x10 +// /* "":15896:15911 */ +// sstore +// /* "":15927:15929 */ +// 0x0f +// /* "":15920:15935 */ +// sstore +// /* "":15951:15953 */ +// 0x0e +// /* "":15944:15959 */ +// sstore +// /* "":15975:15977 */ +// 0x0d +// /* "":15968:15983 */ +// sstore +// /* "":15999:16001 */ +// 0x0c +// /* "":15992:16007 */ +// sstore +// /* "":16023:16025 */ +// 0x0b +// /* "":16016:16031 */ +// sstore +// /* "":16047:16049 */ +// 0x0a +// /* "":16040:16055 */ +// sstore +// /* "":16071:16072 */ +// 0x09 +// /* "":16064:16077 */ +// sstore +// /* "":16093:16094 */ +// 0x08 +// /* "":16086:16099 */ +// sstore +// /* "":16115:16116 */ +// 0x07 +// /* "":16108:16121 */ +// sstore +// /* "":16137:16138 */ +// 0x06 +// /* "":16130:16143 */ +// sstore +// /* "":16159:16160 */ +// 0x05 +// /* "":16152:16165 */ +// sstore +// /* "":16181:16182 */ +// 0x04 +// /* "":16174:16187 */ +// sstore +// /* "":16203:16204 */ +// 0x03 +// /* "":16196:16209 */ +// sstore +// /* "":16225:16226 */ +// 0x02 +// /* "":16218:16231 */ +// sstore +// /* "":16247:16248 */ +// 0x01 +// /* "":16240:16253 */ +// sstore +// /* "":16269:16270 */ +// 0x00 +// /* "":16262:16275 */ +// sstore +// /* "":25:16281 */ +// stop +// /* "":9800:9815 */ +// tag_1: +// /* "":9811:9812 */ +// 0x00 +// /* "":9802:9813 */ +// dup1 +// revert diff --git a/test/libyul/evmCodeTransform/eof_swap17.yul b/test/libyul/evmCodeTransform/eof_swap17.yul new file mode 100644 index 000000000000..1f9b993cca87 --- /dev/null +++ b/test/libyul/evmCodeTransform/eof_swap17.yul @@ -0,0 +1,229 @@ +object "main" { + code { + // v17 is 17 slots deep in stack - all values in between are still needed - no way to avoid a swapn{17}. + // Running this without EOF, as expected, throws stack-too-deep. + function f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14, v15, v16, v17) { + sstore(17, v17) + sstore(16, v16) + sstore(15, v15) + sstore(14, v14) + sstore(13, v13) + sstore(12, v12) + sstore(11, v11) + sstore(10, v10) + sstore(9, v09) + sstore(8, v08) + sstore(7, v07) + sstore(6, v06) + sstore(5, v05) + sstore(4, v04) + sstore(3, v03) + sstore(2, v02) + sstore(1, v01) + sstore(0, v00) + } + f( + calldataload(0), + calldataload(1), + calldataload(2), + calldataload(3), + calldataload(4), + calldataload(5), + calldataload(6), + calldataload(7), + calldataload(8), + calldataload(9), + calldataload(10), + calldataload(11), + calldataload(12), + calldataload(13), + calldataload(14), + calldataload(15), + calldataload(16), + calldataload(17) + ) + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// stackOptimization: true +// ---- +// /* "":1361:1363 */ +// 0x11 +// /* "":1348:1364 */ +// calldataload +// /* "":1331:1333 */ +// 0x10 +// /* "":1318:1334 */ +// calldataload +// /* "":1301:1303 */ +// 0x0f +// /* "":1288:1304 */ +// calldataload +// /* "":1271:1273 */ +// 0x0e +// /* "":1258:1274 */ +// calldataload +// /* "":1241:1243 */ +// 0x0d +// /* "":1228:1244 */ +// calldataload +// /* "":1211:1213 */ +// 0x0c +// /* "":1198:1214 */ +// calldataload +// /* "":1181:1183 */ +// 0x0b +// /* "":1168:1184 */ +// calldataload +// /* "":1151:1153 */ +// 0x0a +// /* "":1138:1154 */ +// calldataload +// /* "":1122:1123 */ +// 0x09 +// /* "":1109:1124 */ +// calldataload +// /* "":1093:1094 */ +// 0x08 +// /* "":1080:1095 */ +// calldataload +// /* "":1064:1065 */ +// 0x07 +// /* "":1051:1066 */ +// calldataload +// /* "":1035:1036 */ +// 0x06 +// /* "":1022:1037 */ +// calldataload +// /* "":1006:1007 */ +// 0x05 +// /* "":993:1008 */ +// calldataload +// /* "":977:978 */ +// 0x04 +// /* "":964:979 */ +// calldataload +// /* "":948:949 */ +// 0x03 +// /* "":935:950 */ +// calldataload +// /* "":919:920 */ +// 0x02 +// /* "":906:921 */ +// calldataload +// /* "":890:891 */ +// 0x01 +// /* "":877:892 */ +// calldataload +// /* "":861:862 */ +// 0x00 +// /* "":848:863 */ +// calldataload +// /* "":833:1374 */ +// callf{code_section_1} +// /* "":22:1377 */ +// stop +// +// code_section_1: assembly { +// /* "":218:824 */ +// swapn{17} +// swap16 +// swap1 +// swap16 +// swap15 +// swap2 +// swap15 +// swap14 +// swap3 +// swap14 +// swap13 +// swap4 +// swap13 +// swap12 +// swap5 +// swap12 +// swap11 +// swap6 +// swap11 +// swap10 +// swap7 +// swap10 +// swap9 +// swap8 +// swap9 +// /* "":340:342 */ +// 0x11 +// /* "":333:348 */ +// sstore +// /* "":368:370 */ +// 0x10 +// /* "":361:376 */ +// sstore +// /* "":396:398 */ +// 0x0f +// /* "":389:404 */ +// sstore +// /* "":424:426 */ +// 0x0e +// /* "":417:432 */ +// sstore +// /* "":452:454 */ +// 0x0d +// /* "":445:460 */ +// sstore +// /* "":480:482 */ +// 0x0c +// /* "":473:488 */ +// sstore +// /* "":508:510 */ +// 0x0b +// /* "":501:516 */ +// sstore +// /* "":536:538 */ +// 0x0a +// /* "":529:544 */ +// sstore +// /* "":564:565 */ +// 0x09 +// /* "":557:571 */ +// sstore +// /* "":591:592 */ +// 0x08 +// /* "":584:598 */ +// sstore +// /* "":618:619 */ +// 0x07 +// /* "":611:625 */ +// sstore +// /* "":645:646 */ +// 0x06 +// /* "":638:652 */ +// sstore +// /* "":672:673 */ +// 0x05 +// /* "":665:679 */ +// sstore +// /* "":699:700 */ +// 0x04 +// /* "":692:706 */ +// sstore +// /* "":726:727 */ +// 0x03 +// /* "":719:733 */ +// sstore +// /* "":753:754 */ +// 0x02 +// /* "":746:760 */ +// sstore +// /* "":780:781 */ +// 0x01 +// /* "":773:787 */ +// sstore +// /* "":807:808 */ +// 0x00 +// /* "":800:814 */ +// sstore +// /* "":218:824 */ +// retf +// } diff --git a/test/libyul/evmCodeTransform/eof_swap256.yul b/test/libyul/evmCodeTransform/eof_swap256.yul new file mode 100644 index 000000000000..f718937be02e --- /dev/null +++ b/test/libyul/evmCodeTransform/eof_swap256.yul @@ -0,0 +1,2839 @@ +object "main" { + code { + // Triggers a swapn{256}. Generating one more variable results in a stack-too-deep. + // Note that this relies on not running the optimizer here. With optimizer this code + // can become entirely swap-free. + let v0 := calldataload(0) + let v1 := calldataload(1) + let v2 := calldataload(2) + let v3 := calldataload(3) + let v4 := calldataload(4) + let v5 := calldataload(5) + let v6 := calldataload(6) + let v7 := calldataload(7) + let v8 := calldataload(8) + let v9 := calldataload(9) + let v10 := calldataload(10) + let v11 := calldataload(11) + let v12 := calldataload(12) + let v13 := calldataload(13) + let v14 := calldataload(14) + let v15 := calldataload(15) + let v16 := calldataload(16) + let v17 := calldataload(17) + let v18 := calldataload(18) + let v19 := calldataload(19) + let v20 := calldataload(20) + let v21 := calldataload(21) + let v22 := calldataload(22) + let v23 := calldataload(23) + let v24 := calldataload(24) + let v25 := calldataload(25) + let v26 := calldataload(26) + let v27 := calldataload(27) + let v28 := calldataload(28) + let v29 := calldataload(29) + let v30 := calldataload(30) + let v31 := calldataload(31) + let v32 := calldataload(32) + let v33 := calldataload(33) + let v34 := calldataload(34) + let v35 := calldataload(35) + let v36 := calldataload(36) + let v37 := calldataload(37) + let v38 := calldataload(38) + let v39 := calldataload(39) + let v40 := calldataload(40) + let v41 := calldataload(41) + let v42 := calldataload(42) + let v43 := calldataload(43) + let v44 := calldataload(44) + let v45 := calldataload(45) + let v46 := calldataload(46) + let v47 := calldataload(47) + let v48 := calldataload(48) + let v49 := calldataload(49) + let v50 := calldataload(50) + let v51 := calldataload(51) + let v52 := calldataload(52) + let v53 := calldataload(53) + let v54 := calldataload(54) + let v55 := calldataload(55) + let v56 := calldataload(56) + let v57 := calldataload(57) + let v58 := calldataload(58) + let v59 := calldataload(59) + let v60 := calldataload(60) + let v61 := calldataload(61) + let v62 := calldataload(62) + let v63 := calldataload(63) + let v64 := calldataload(64) + let v65 := calldataload(65) + let v66 := calldataload(66) + let v67 := calldataload(67) + let v68 := calldataload(68) + let v69 := calldataload(69) + let v70 := calldataload(70) + let v71 := calldataload(71) + let v72 := calldataload(72) + let v73 := calldataload(73) + let v74 := calldataload(74) + let v75 := calldataload(75) + let v76 := calldataload(76) + let v77 := calldataload(77) + let v78 := calldataload(78) + let v79 := calldataload(79) + let v80 := calldataload(80) + let v81 := calldataload(81) + let v82 := calldataload(82) + let v83 := calldataload(83) + let v84 := calldataload(84) + let v85 := calldataload(85) + let v86 := calldataload(86) + let v87 := calldataload(87) + let v88 := calldataload(88) + let v89 := calldataload(89) + let v90 := calldataload(90) + let v91 := calldataload(91) + let v92 := calldataload(92) + let v93 := calldataload(93) + let v94 := calldataload(94) + let v95 := calldataload(95) + let v96 := calldataload(96) + let v97 := calldataload(97) + let v98 := calldataload(98) + let v99 := calldataload(99) + let v100 := calldataload(100) + let v101 := calldataload(101) + let v102 := calldataload(102) + let v103 := calldataload(103) + let v104 := calldataload(104) + let v105 := calldataload(105) + let v106 := calldataload(106) + let v107 := calldataload(107) + let v108 := calldataload(108) + let v109 := calldataload(109) + let v110 := calldataload(110) + let v111 := calldataload(111) + let v112 := calldataload(112) + let v113 := calldataload(113) + let v114 := calldataload(114) + let v115 := calldataload(115) + let v116 := calldataload(116) + let v117 := calldataload(117) + let v118 := calldataload(118) + let v119 := calldataload(119) + let v120 := calldataload(120) + let v121 := calldataload(121) + let v122 := calldataload(122) + let v123 := calldataload(123) + let v124 := calldataload(124) + let v125 := calldataload(125) + let v126 := calldataload(126) + let v127 := calldataload(127) + let v128 := calldataload(128) + let v129 := calldataload(129) + let v130 := calldataload(130) + let v131 := calldataload(131) + let v132 := calldataload(132) + let v133 := calldataload(133) + let v134 := calldataload(134) + let v135 := calldataload(135) + let v136 := calldataload(136) + let v137 := calldataload(137) + let v138 := calldataload(138) + let v139 := calldataload(139) + let v140 := calldataload(140) + let v141 := calldataload(141) + let v142 := calldataload(142) + let v143 := calldataload(143) + let v144 := calldataload(144) + let v145 := calldataload(145) + let v146 := calldataload(146) + let v147 := calldataload(147) + let v148 := calldataload(148) + let v149 := calldataload(149) + let v150 := calldataload(150) + let v151 := calldataload(151) + let v152 := calldataload(152) + let v153 := calldataload(153) + let v154 := calldataload(154) + let v155 := calldataload(155) + let v156 := calldataload(156) + let v157 := calldataload(157) + let v158 := calldataload(158) + let v159 := calldataload(159) + let v160 := calldataload(160) + let v161 := calldataload(161) + let v162 := calldataload(162) + let v163 := calldataload(163) + let v164 := calldataload(164) + let v165 := calldataload(165) + let v166 := calldataload(166) + let v167 := calldataload(167) + let v168 := calldataload(168) + let v169 := calldataload(169) + let v170 := calldataload(170) + let v171 := calldataload(171) + let v172 := calldataload(172) + let v173 := calldataload(173) + let v174 := calldataload(174) + let v175 := calldataload(175) + let v176 := calldataload(176) + let v177 := calldataload(177) + let v178 := calldataload(178) + let v179 := calldataload(179) + let v180 := calldataload(180) + let v181 := calldataload(181) + let v182 := calldataload(182) + let v183 := calldataload(183) + let v184 := calldataload(184) + let v185 := calldataload(185) + let v186 := calldataload(186) + let v187 := calldataload(187) + let v188 := calldataload(188) + let v189 := calldataload(189) + let v190 := calldataload(190) + let v191 := calldataload(191) + let v192 := calldataload(192) + let v193 := calldataload(193) + let v194 := calldataload(194) + let v195 := calldataload(195) + let v196 := calldataload(196) + let v197 := calldataload(197) + let v198 := calldataload(198) + let v199 := calldataload(199) + let v200 := calldataload(200) + let v201 := calldataload(201) + let v202 := calldataload(202) + let v203 := calldataload(203) + let v204 := calldataload(204) + let v205 := calldataload(205) + let v206 := calldataload(206) + let v207 := calldataload(207) + let v208 := calldataload(208) + let v209 := calldataload(209) + let v210 := calldataload(210) + let v211 := calldataload(211) + let v212 := calldataload(212) + let v213 := calldataload(213) + let v214 := calldataload(214) + let v215 := calldataload(215) + let v216 := calldataload(216) + let v217 := calldataload(217) + let v218 := calldataload(218) + let v219 := calldataload(219) + let v220 := calldataload(220) + let v221 := calldataload(221) + let v222 := calldataload(222) + let v223 := calldataload(223) + let v224 := calldataload(224) + let v225 := calldataload(225) + let v226 := calldataload(226) + let v227 := calldataload(227) + let v228 := calldataload(228) + let v229 := calldataload(229) + let v230 := calldataload(230) + let v231 := calldataload(231) + let v232 := calldataload(232) + let v233 := calldataload(233) + let v234 := calldataload(234) + let v235 := calldataload(235) + let v236 := calldataload(236) + let v237 := calldataload(237) + let v238 := calldataload(238) + let v239 := calldataload(239) + let v240 := calldataload(240) + let v241 := calldataload(241) + let v242 := calldataload(242) + let v243 := calldataload(243) + let v244 := calldataload(244) + let v245 := calldataload(245) + let v246 := calldataload(246) + let v247 := calldataload(247) + let v248 := calldataload(248) + let v249 := calldataload(249) + let v250 := calldataload(250) + let v251 := calldataload(251) + let v252 := calldataload(252) + let v253 := calldataload(253) + let v254 := calldataload(254) + let v255 := calldataload(255) + let v256 := calldataload(256) + sstore(0, v0) + sstore(1, v1) + sstore(2, v2) + sstore(3, v3) + sstore(4, v4) + sstore(5, v5) + sstore(6, v6) + sstore(7, v7) + sstore(8, v8) + sstore(9, v9) + sstore(10, v10) + sstore(11, v11) + sstore(12, v12) + sstore(13, v13) + sstore(14, v14) + sstore(15, v15) + sstore(16, v16) + sstore(17, v17) + sstore(18, v18) + sstore(19, v19) + sstore(20, v20) + sstore(21, v21) + sstore(22, v22) + sstore(23, v23) + sstore(24, v24) + sstore(25, v25) + sstore(26, v26) + sstore(27, v27) + sstore(28, v28) + sstore(29, v29) + sstore(30, v30) + sstore(31, v31) + sstore(32, v32) + sstore(33, v33) + sstore(34, v34) + sstore(35, v35) + sstore(36, v36) + sstore(37, v37) + sstore(38, v38) + sstore(39, v39) + sstore(40, v40) + sstore(41, v41) + sstore(42, v42) + sstore(43, v43) + sstore(44, v44) + sstore(45, v45) + sstore(46, v46) + sstore(47, v47) + sstore(48, v48) + sstore(49, v49) + sstore(50, v50) + sstore(51, v51) + sstore(52, v52) + sstore(53, v53) + sstore(54, v54) + sstore(55, v55) + sstore(56, v56) + sstore(57, v57) + sstore(58, v58) + sstore(59, v59) + sstore(60, v60) + sstore(61, v61) + sstore(62, v62) + sstore(63, v63) + sstore(64, v64) + sstore(65, v65) + sstore(66, v66) + sstore(67, v67) + sstore(68, v68) + sstore(69, v69) + sstore(70, v70) + sstore(71, v71) + sstore(72, v72) + sstore(73, v73) + sstore(74, v74) + sstore(75, v75) + sstore(76, v76) + sstore(77, v77) + sstore(78, v78) + sstore(79, v79) + sstore(80, v80) + sstore(81, v81) + sstore(82, v82) + sstore(83, v83) + sstore(84, v84) + sstore(85, v85) + sstore(86, v86) + sstore(87, v87) + sstore(88, v88) + sstore(89, v89) + sstore(90, v90) + sstore(91, v91) + sstore(92, v92) + sstore(93, v93) + sstore(94, v94) + sstore(95, v95) + sstore(96, v96) + sstore(97, v97) + sstore(98, v98) + sstore(99, v99) + sstore(100, v100) + sstore(101, v101) + sstore(102, v102) + sstore(103, v103) + sstore(104, v104) + sstore(105, v105) + sstore(106, v106) + sstore(107, v107) + sstore(108, v108) + sstore(109, v109) + sstore(110, v110) + sstore(111, v111) + sstore(112, v112) + sstore(113, v113) + sstore(114, v114) + sstore(115, v115) + sstore(116, v116) + sstore(117, v117) + sstore(118, v118) + sstore(119, v119) + sstore(120, v120) + sstore(121, v121) + sstore(122, v122) + sstore(123, v123) + sstore(124, v124) + sstore(125, v125) + sstore(126, v126) + sstore(127, v127) + sstore(128, v128) + sstore(129, v129) + sstore(130, v130) + sstore(131, v131) + sstore(132, v132) + sstore(133, v133) + sstore(134, v134) + sstore(135, v135) + sstore(136, v136) + sstore(137, v137) + sstore(138, v138) + sstore(139, v139) + sstore(140, v140) + sstore(141, v141) + sstore(142, v142) + sstore(143, v143) + sstore(144, v144) + sstore(145, v145) + sstore(146, v146) + sstore(147, v147) + sstore(148, v148) + sstore(149, v149) + sstore(150, v150) + sstore(151, v151) + sstore(152, v152) + sstore(153, v153) + sstore(154, v154) + sstore(155, v155) + sstore(156, v156) + sstore(157, v157) + sstore(158, v158) + sstore(159, v159) + sstore(160, v160) + sstore(161, v161) + sstore(162, v162) + sstore(163, v163) + sstore(164, v164) + sstore(165, v165) + sstore(166, v166) + sstore(167, v167) + sstore(168, v168) + sstore(169, v169) + sstore(170, v170) + sstore(171, v171) + sstore(172, v172) + sstore(173, v173) + sstore(174, v174) + sstore(175, v175) + sstore(176, v176) + sstore(177, v177) + sstore(178, v178) + sstore(179, v179) + sstore(180, v180) + sstore(181, v181) + sstore(182, v182) + sstore(183, v183) + sstore(184, v184) + sstore(185, v185) + sstore(186, v186) + sstore(187, v187) + sstore(188, v188) + sstore(189, v189) + sstore(190, v190) + sstore(191, v191) + sstore(192, v192) + sstore(193, v193) + sstore(194, v194) + sstore(195, v195) + sstore(196, v196) + sstore(197, v197) + sstore(198, v198) + sstore(199, v199) + sstore(200, v200) + sstore(201, v201) + sstore(202, v202) + sstore(203, v203) + sstore(204, v204) + sstore(205, v205) + sstore(206, v206) + sstore(207, v207) + sstore(208, v208) + sstore(209, v209) + sstore(210, v210) + sstore(211, v211) + sstore(212, v212) + sstore(213, v213) + sstore(214, v214) + sstore(215, v215) + sstore(216, v216) + sstore(217, v217) + sstore(218, v218) + sstore(219, v219) + sstore(220, v220) + sstore(221, v221) + sstore(222, v222) + sstore(223, v223) + sstore(224, v224) + sstore(225, v225) + sstore(226, v226) + sstore(227, v227) + sstore(228, v228) + sstore(229, v229) + sstore(230, v230) + sstore(231, v231) + sstore(232, v232) + sstore(233, v233) + sstore(234, v234) + sstore(235, v235) + sstore(236, v236) + sstore(237, v237) + sstore(238, v238) + sstore(239, v239) + sstore(240, v240) + sstore(241, v241) + sstore(242, v242) + sstore(243, v243) + sstore(244, v244) + sstore(245, v245) + sstore(246, v246) + sstore(247, v247) + sstore(248, v248) + sstore(249, v249) + sstore(250, v250) + sstore(251, v251) + sstore(252, v252) + sstore(253, v253) + sstore(254, v254) + sstore(255, v255) + sstore(256, v256) + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// stackOptimization: true +// ---- +// /* "":285:286 */ +// 0x00 +// /* "":272:287 */ +// calldataload +// /* "":319:320 */ +// 0x01 +// /* "":306:321 */ +// calldataload +// /* "":353:354 */ +// 0x02 +// /* "":340:355 */ +// calldataload +// /* "":387:388 */ +// 0x03 +// /* "":374:389 */ +// calldataload +// /* "":421:422 */ +// 0x04 +// /* "":408:423 */ +// calldataload +// /* "":455:456 */ +// 0x05 +// /* "":442:457 */ +// calldataload +// /* "":489:490 */ +// 0x06 +// /* "":476:491 */ +// calldataload +// /* "":523:524 */ +// 0x07 +// /* "":510:525 */ +// calldataload +// /* "":557:558 */ +// 0x08 +// /* "":544:559 */ +// calldataload +// /* "":591:592 */ +// 0x09 +// /* "":578:593 */ +// calldataload +// /* "":626:628 */ +// 0x0a +// /* "":613:629 */ +// calldataload +// /* "":662:664 */ +// 0x0b +// /* "":649:665 */ +// calldataload +// /* "":698:700 */ +// 0x0c +// /* "":685:701 */ +// calldataload +// /* "":734:736 */ +// 0x0d +// /* "":721:737 */ +// calldataload +// /* "":770:772 */ +// 0x0e +// /* "":757:773 */ +// calldataload +// /* "":806:808 */ +// 0x0f +// /* "":793:809 */ +// calldataload +// /* "":842:844 */ +// 0x10 +// /* "":829:845 */ +// calldataload +// /* "":878:880 */ +// 0x11 +// /* "":865:881 */ +// calldataload +// /* "":914:916 */ +// 0x12 +// /* "":901:917 */ +// calldataload +// /* "":950:952 */ +// 0x13 +// /* "":937:953 */ +// calldataload +// /* "":986:988 */ +// 0x14 +// /* "":973:989 */ +// calldataload +// /* "":1022:1024 */ +// 0x15 +// /* "":1009:1025 */ +// calldataload +// /* "":1058:1060 */ +// 0x16 +// /* "":1045:1061 */ +// calldataload +// /* "":1094:1096 */ +// 0x17 +// /* "":1081:1097 */ +// calldataload +// /* "":1130:1132 */ +// 0x18 +// /* "":1117:1133 */ +// calldataload +// /* "":1166:1168 */ +// 0x19 +// /* "":1153:1169 */ +// calldataload +// /* "":1202:1204 */ +// 0x1a +// /* "":1189:1205 */ +// calldataload +// /* "":1238:1240 */ +// 0x1b +// /* "":1225:1241 */ +// calldataload +// /* "":1274:1276 */ +// 0x1c +// /* "":1261:1277 */ +// calldataload +// /* "":1310:1312 */ +// 0x1d +// /* "":1297:1313 */ +// calldataload +// /* "":1346:1348 */ +// 0x1e +// /* "":1333:1349 */ +// calldataload +// /* "":1382:1384 */ +// 0x1f +// /* "":1369:1385 */ +// calldataload +// /* "":1418:1420 */ +// 0x20 +// /* "":1405:1421 */ +// calldataload +// /* "":1454:1456 */ +// 0x21 +// /* "":1441:1457 */ +// calldataload +// /* "":1490:1492 */ +// 0x22 +// /* "":1477:1493 */ +// calldataload +// /* "":1526:1528 */ +// 0x23 +// /* "":1513:1529 */ +// calldataload +// /* "":1562:1564 */ +// 0x24 +// /* "":1549:1565 */ +// calldataload +// /* "":1598:1600 */ +// 0x25 +// /* "":1585:1601 */ +// calldataload +// /* "":1634:1636 */ +// 0x26 +// /* "":1621:1637 */ +// calldataload +// /* "":1670:1672 */ +// 0x27 +// /* "":1657:1673 */ +// calldataload +// /* "":1706:1708 */ +// 0x28 +// /* "":1693:1709 */ +// calldataload +// /* "":1742:1744 */ +// 0x29 +// /* "":1729:1745 */ +// calldataload +// /* "":1778:1780 */ +// 0x2a +// /* "":1765:1781 */ +// calldataload +// /* "":1814:1816 */ +// 0x2b +// /* "":1801:1817 */ +// calldataload +// /* "":1850:1852 */ +// 0x2c +// /* "":1837:1853 */ +// calldataload +// /* "":1886:1888 */ +// 0x2d +// /* "":1873:1889 */ +// calldataload +// /* "":1922:1924 */ +// 0x2e +// /* "":1909:1925 */ +// calldataload +// /* "":1958:1960 */ +// 0x2f +// /* "":1945:1961 */ +// calldataload +// /* "":1994:1996 */ +// 0x30 +// /* "":1981:1997 */ +// calldataload +// /* "":2030:2032 */ +// 0x31 +// /* "":2017:2033 */ +// calldataload +// /* "":2066:2068 */ +// 0x32 +// /* "":2053:2069 */ +// calldataload +// /* "":2102:2104 */ +// 0x33 +// /* "":2089:2105 */ +// calldataload +// /* "":2138:2140 */ +// 0x34 +// /* "":2125:2141 */ +// calldataload +// /* "":2174:2176 */ +// 0x35 +// /* "":2161:2177 */ +// calldataload +// /* "":2210:2212 */ +// 0x36 +// /* "":2197:2213 */ +// calldataload +// /* "":2246:2248 */ +// 0x37 +// /* "":2233:2249 */ +// calldataload +// /* "":2282:2284 */ +// 0x38 +// /* "":2269:2285 */ +// calldataload +// /* "":2318:2320 */ +// 0x39 +// /* "":2305:2321 */ +// calldataload +// /* "":2354:2356 */ +// 0x3a +// /* "":2341:2357 */ +// calldataload +// /* "":2390:2392 */ +// 0x3b +// /* "":2377:2393 */ +// calldataload +// /* "":2426:2428 */ +// 0x3c +// /* "":2413:2429 */ +// calldataload +// /* "":2462:2464 */ +// 0x3d +// /* "":2449:2465 */ +// calldataload +// /* "":2498:2500 */ +// 0x3e +// /* "":2485:2501 */ +// calldataload +// /* "":2534:2536 */ +// 0x3f +// /* "":2521:2537 */ +// calldataload +// /* "":2570:2572 */ +// 0x40 +// /* "":2557:2573 */ +// calldataload +// /* "":2606:2608 */ +// 0x41 +// /* "":2593:2609 */ +// calldataload +// /* "":2642:2644 */ +// 0x42 +// /* "":2629:2645 */ +// calldataload +// /* "":2678:2680 */ +// 0x43 +// /* "":2665:2681 */ +// calldataload +// /* "":2714:2716 */ +// 0x44 +// /* "":2701:2717 */ +// calldataload +// /* "":2750:2752 */ +// 0x45 +// /* "":2737:2753 */ +// calldataload +// /* "":2786:2788 */ +// 0x46 +// /* "":2773:2789 */ +// calldataload +// /* "":2822:2824 */ +// 0x47 +// /* "":2809:2825 */ +// calldataload +// /* "":2858:2860 */ +// 0x48 +// /* "":2845:2861 */ +// calldataload +// /* "":2894:2896 */ +// 0x49 +// /* "":2881:2897 */ +// calldataload +// /* "":2930:2932 */ +// 0x4a +// /* "":2917:2933 */ +// calldataload +// /* "":2966:2968 */ +// 0x4b +// /* "":2953:2969 */ +// calldataload +// /* "":3002:3004 */ +// 0x4c +// /* "":2989:3005 */ +// calldataload +// /* "":3038:3040 */ +// 0x4d +// /* "":3025:3041 */ +// calldataload +// /* "":3074:3076 */ +// 0x4e +// /* "":3061:3077 */ +// calldataload +// /* "":3110:3112 */ +// 0x4f +// /* "":3097:3113 */ +// calldataload +// /* "":3146:3148 */ +// 0x50 +// /* "":3133:3149 */ +// calldataload +// /* "":3182:3184 */ +// 0x51 +// /* "":3169:3185 */ +// calldataload +// /* "":3218:3220 */ +// 0x52 +// /* "":3205:3221 */ +// calldataload +// /* "":3254:3256 */ +// 0x53 +// /* "":3241:3257 */ +// calldataload +// /* "":3290:3292 */ +// 0x54 +// /* "":3277:3293 */ +// calldataload +// /* "":3326:3328 */ +// 0x55 +// /* "":3313:3329 */ +// calldataload +// /* "":3362:3364 */ +// 0x56 +// /* "":3349:3365 */ +// calldataload +// /* "":3398:3400 */ +// 0x57 +// /* "":3385:3401 */ +// calldataload +// /* "":3434:3436 */ +// 0x58 +// /* "":3421:3437 */ +// calldataload +// /* "":3470:3472 */ +// 0x59 +// /* "":3457:3473 */ +// calldataload +// /* "":3506:3508 */ +// 0x5a +// /* "":3493:3509 */ +// calldataload +// /* "":3542:3544 */ +// 0x5b +// /* "":3529:3545 */ +// calldataload +// /* "":3578:3580 */ +// 0x5c +// /* "":3565:3581 */ +// calldataload +// /* "":3614:3616 */ +// 0x5d +// /* "":3601:3617 */ +// calldataload +// /* "":3650:3652 */ +// 0x5e +// /* "":3637:3653 */ +// calldataload +// /* "":3686:3688 */ +// 0x5f +// /* "":3673:3689 */ +// calldataload +// /* "":3722:3724 */ +// 0x60 +// /* "":3709:3725 */ +// calldataload +// /* "":3758:3760 */ +// 0x61 +// /* "":3745:3761 */ +// calldataload +// /* "":3794:3796 */ +// 0x62 +// /* "":3781:3797 */ +// calldataload +// /* "":3830:3832 */ +// 0x63 +// /* "":3817:3833 */ +// calldataload +// /* "":3867:3870 */ +// 0x64 +// /* "":3854:3871 */ +// calldataload +// /* "":3905:3908 */ +// 0x65 +// /* "":3892:3909 */ +// calldataload +// /* "":3943:3946 */ +// 0x66 +// /* "":3930:3947 */ +// calldataload +// /* "":3981:3984 */ +// 0x67 +// /* "":3968:3985 */ +// calldataload +// /* "":4019:4022 */ +// 0x68 +// /* "":4006:4023 */ +// calldataload +// /* "":4057:4060 */ +// 0x69 +// /* "":4044:4061 */ +// calldataload +// /* "":4095:4098 */ +// 0x6a +// /* "":4082:4099 */ +// calldataload +// /* "":4133:4136 */ +// 0x6b +// /* "":4120:4137 */ +// calldataload +// /* "":4171:4174 */ +// 0x6c +// /* "":4158:4175 */ +// calldataload +// /* "":4209:4212 */ +// 0x6d +// /* "":4196:4213 */ +// calldataload +// /* "":4247:4250 */ +// 0x6e +// /* "":4234:4251 */ +// calldataload +// /* "":4285:4288 */ +// 0x6f +// /* "":4272:4289 */ +// calldataload +// /* "":4323:4326 */ +// 0x70 +// /* "":4310:4327 */ +// calldataload +// /* "":4361:4364 */ +// 0x71 +// /* "":4348:4365 */ +// calldataload +// /* "":4399:4402 */ +// 0x72 +// /* "":4386:4403 */ +// calldataload +// /* "":4437:4440 */ +// 0x73 +// /* "":4424:4441 */ +// calldataload +// /* "":4475:4478 */ +// 0x74 +// /* "":4462:4479 */ +// calldataload +// /* "":4513:4516 */ +// 0x75 +// /* "":4500:4517 */ +// calldataload +// /* "":4551:4554 */ +// 0x76 +// /* "":4538:4555 */ +// calldataload +// /* "":4589:4592 */ +// 0x77 +// /* "":4576:4593 */ +// calldataload +// /* "":4627:4630 */ +// 0x78 +// /* "":4614:4631 */ +// calldataload +// /* "":4665:4668 */ +// 0x79 +// /* "":4652:4669 */ +// calldataload +// /* "":4703:4706 */ +// 0x7a +// /* "":4690:4707 */ +// calldataload +// /* "":4741:4744 */ +// 0x7b +// /* "":4728:4745 */ +// calldataload +// /* "":4779:4782 */ +// 0x7c +// /* "":4766:4783 */ +// calldataload +// /* "":4817:4820 */ +// 0x7d +// /* "":4804:4821 */ +// calldataload +// /* "":4855:4858 */ +// 0x7e +// /* "":4842:4859 */ +// calldataload +// /* "":4893:4896 */ +// 0x7f +// /* "":4880:4897 */ +// calldataload +// /* "":4931:4934 */ +// 0x80 +// /* "":4918:4935 */ +// calldataload +// /* "":4969:4972 */ +// 0x81 +// /* "":4956:4973 */ +// calldataload +// /* "":4994:5011 */ +// swap2 +// /* "":5007:5010 */ +// 0x82 +// /* "":4994:5011 */ +// calldataload +// /* "":5032:5049 */ +// swap4 +// /* "":5045:5048 */ +// 0x83 +// /* "":5032:5049 */ +// calldataload +// /* "":5070:5087 */ +// swap6 +// /* "":5083:5086 */ +// 0x84 +// /* "":5070:5087 */ +// calldataload +// /* "":5108:5125 */ +// swap8 +// /* "":5121:5124 */ +// 0x85 +// /* "":5108:5125 */ +// calldataload +// /* "":5146:5163 */ +// swap10 +// /* "":5159:5162 */ +// 0x86 +// /* "":5146:5163 */ +// calldataload +// /* "":5184:5201 */ +// swap12 +// /* "":5197:5200 */ +// 0x87 +// /* "":5184:5201 */ +// calldataload +// /* "":5222:5239 */ +// swap14 +// /* "":5235:5238 */ +// 0x88 +// /* "":5222:5239 */ +// calldataload +// /* "":5260:5277 */ +// swap16 +// /* "":5273:5276 */ +// 0x89 +// /* "":5260:5277 */ +// calldataload +// /* "":5298:5315 */ +// swapn{18} +// /* "":5311:5314 */ +// 0x8a +// /* "":5298:5315 */ +// calldataload +// /* "":5336:5353 */ +// swapn{20} +// /* "":5349:5352 */ +// 0x8b +// /* "":5336:5353 */ +// calldataload +// /* "":5374:5391 */ +// swapn{22} +// /* "":5387:5390 */ +// 0x8c +// /* "":5374:5391 */ +// calldataload +// /* "":5412:5429 */ +// swapn{24} +// /* "":5425:5428 */ +// 0x8d +// /* "":5412:5429 */ +// calldataload +// /* "":5450:5467 */ +// swapn{26} +// /* "":5463:5466 */ +// 0x8e +// /* "":5450:5467 */ +// calldataload +// /* "":5488:5505 */ +// swapn{28} +// /* "":5501:5504 */ +// 0x8f +// /* "":5488:5505 */ +// calldataload +// /* "":5526:5543 */ +// swapn{30} +// /* "":5539:5542 */ +// 0x90 +// /* "":5526:5543 */ +// calldataload +// /* "":5564:5581 */ +// swapn{32} +// /* "":5577:5580 */ +// 0x91 +// /* "":5564:5581 */ +// calldataload +// /* "":5602:5619 */ +// swapn{34} +// /* "":5615:5618 */ +// 0x92 +// /* "":5602:5619 */ +// calldataload +// /* "":5640:5657 */ +// swapn{36} +// /* "":5653:5656 */ +// 0x93 +// /* "":5640:5657 */ +// calldataload +// /* "":5678:5695 */ +// swapn{38} +// /* "":5691:5694 */ +// 0x94 +// /* "":5678:5695 */ +// calldataload +// /* "":5716:5733 */ +// swapn{40} +// /* "":5729:5732 */ +// 0x95 +// /* "":5716:5733 */ +// calldataload +// /* "":5754:5771 */ +// swapn{42} +// /* "":5767:5770 */ +// 0x96 +// /* "":5754:5771 */ +// calldataload +// /* "":5792:5809 */ +// swapn{44} +// /* "":5805:5808 */ +// 0x97 +// /* "":5792:5809 */ +// calldataload +// /* "":5830:5847 */ +// swapn{46} +// /* "":5843:5846 */ +// 0x98 +// /* "":5830:5847 */ +// calldataload +// /* "":5868:5885 */ +// swapn{48} +// /* "":5881:5884 */ +// 0x99 +// /* "":5868:5885 */ +// calldataload +// /* "":5906:5923 */ +// swapn{50} +// /* "":5919:5922 */ +// 0x9a +// /* "":5906:5923 */ +// calldataload +// /* "":5944:5961 */ +// swapn{52} +// /* "":5957:5960 */ +// 0x9b +// /* "":5944:5961 */ +// calldataload +// /* "":5982:5999 */ +// swapn{54} +// /* "":5995:5998 */ +// 0x9c +// /* "":5982:5999 */ +// calldataload +// /* "":6020:6037 */ +// swapn{56} +// /* "":6033:6036 */ +// 0x9d +// /* "":6020:6037 */ +// calldataload +// /* "":6058:6075 */ +// swapn{58} +// /* "":6071:6074 */ +// 0x9e +// /* "":6058:6075 */ +// calldataload +// /* "":6096:6113 */ +// swapn{60} +// /* "":6109:6112 */ +// 0x9f +// /* "":6096:6113 */ +// calldataload +// /* "":6134:6151 */ +// swapn{62} +// /* "":6147:6150 */ +// 0xa0 +// /* "":6134:6151 */ +// calldataload +// /* "":6172:6189 */ +// swapn{64} +// /* "":6185:6188 */ +// 0xa1 +// /* "":6172:6189 */ +// calldataload +// /* "":6210:6227 */ +// swapn{66} +// /* "":6223:6226 */ +// 0xa2 +// /* "":6210:6227 */ +// calldataload +// /* "":6248:6265 */ +// swapn{68} +// /* "":6261:6264 */ +// 0xa3 +// /* "":6248:6265 */ +// calldataload +// /* "":6286:6303 */ +// swapn{70} +// /* "":6299:6302 */ +// 0xa4 +// /* "":6286:6303 */ +// calldataload +// /* "":6324:6341 */ +// swapn{72} +// /* "":6337:6340 */ +// 0xa5 +// /* "":6324:6341 */ +// calldataload +// /* "":6362:6379 */ +// swapn{74} +// /* "":6375:6378 */ +// 0xa6 +// /* "":6362:6379 */ +// calldataload +// /* "":6400:6417 */ +// swapn{76} +// /* "":6413:6416 */ +// 0xa7 +// /* "":6400:6417 */ +// calldataload +// /* "":6438:6455 */ +// swapn{78} +// /* "":6451:6454 */ +// 0xa8 +// /* "":6438:6455 */ +// calldataload +// /* "":6476:6493 */ +// swapn{80} +// /* "":6489:6492 */ +// 0xa9 +// /* "":6476:6493 */ +// calldataload +// /* "":6514:6531 */ +// swapn{82} +// /* "":6527:6530 */ +// 0xaa +// /* "":6514:6531 */ +// calldataload +// /* "":6552:6569 */ +// swapn{84} +// /* "":6565:6568 */ +// 0xab +// /* "":6552:6569 */ +// calldataload +// /* "":6590:6607 */ +// swapn{86} +// /* "":6603:6606 */ +// 0xac +// /* "":6590:6607 */ +// calldataload +// /* "":6628:6645 */ +// swapn{88} +// /* "":6641:6644 */ +// 0xad +// /* "":6628:6645 */ +// calldataload +// /* "":6666:6683 */ +// swapn{90} +// /* "":6679:6682 */ +// 0xae +// /* "":6666:6683 */ +// calldataload +// /* "":6704:6721 */ +// swapn{92} +// /* "":6717:6720 */ +// 0xaf +// /* "":6704:6721 */ +// calldataload +// /* "":6742:6759 */ +// swapn{94} +// /* "":6755:6758 */ +// 0xb0 +// /* "":6742:6759 */ +// calldataload +// /* "":6780:6797 */ +// swapn{96} +// /* "":6793:6796 */ +// 0xb1 +// /* "":6780:6797 */ +// calldataload +// /* "":6818:6835 */ +// swapn{98} +// /* "":6831:6834 */ +// 0xb2 +// /* "":6818:6835 */ +// calldataload +// /* "":6856:6873 */ +// swapn{100} +// /* "":6869:6872 */ +// 0xb3 +// /* "":6856:6873 */ +// calldataload +// /* "":6894:6911 */ +// swapn{102} +// /* "":6907:6910 */ +// 0xb4 +// /* "":6894:6911 */ +// calldataload +// /* "":6932:6949 */ +// swapn{104} +// /* "":6945:6948 */ +// 0xb5 +// /* "":6932:6949 */ +// calldataload +// /* "":6970:6987 */ +// swapn{106} +// /* "":6983:6986 */ +// 0xb6 +// /* "":6970:6987 */ +// calldataload +// /* "":7008:7025 */ +// swapn{108} +// /* "":7021:7024 */ +// 0xb7 +// /* "":7008:7025 */ +// calldataload +// /* "":7046:7063 */ +// swapn{110} +// /* "":7059:7062 */ +// 0xb8 +// /* "":7046:7063 */ +// calldataload +// /* "":7084:7101 */ +// swapn{112} +// /* "":7097:7100 */ +// 0xb9 +// /* "":7084:7101 */ +// calldataload +// /* "":7122:7139 */ +// swapn{114} +// /* "":7135:7138 */ +// 0xba +// /* "":7122:7139 */ +// calldataload +// /* "":7160:7177 */ +// swapn{116} +// /* "":7173:7176 */ +// 0xbb +// /* "":7160:7177 */ +// calldataload +// /* "":7198:7215 */ +// swapn{118} +// /* "":7211:7214 */ +// 0xbc +// /* "":7198:7215 */ +// calldataload +// /* "":7236:7253 */ +// swapn{120} +// /* "":7249:7252 */ +// 0xbd +// /* "":7236:7253 */ +// calldataload +// /* "":7274:7291 */ +// swapn{122} +// /* "":7287:7290 */ +// 0xbe +// /* "":7274:7291 */ +// calldataload +// /* "":7312:7329 */ +// swapn{124} +// /* "":7325:7328 */ +// 0xbf +// /* "":7312:7329 */ +// calldataload +// /* "":7350:7367 */ +// swapn{126} +// /* "":7363:7366 */ +// 0xc0 +// /* "":7350:7367 */ +// calldataload +// /* "":7388:7405 */ +// swapn{128} +// /* "":7401:7404 */ +// 0xc1 +// /* "":7388:7405 */ +// calldataload +// /* "":7426:7443 */ +// swapn{130} +// /* "":7439:7442 */ +// 0xc2 +// /* "":7426:7443 */ +// calldataload +// /* "":7464:7481 */ +// swapn{132} +// /* "":7477:7480 */ +// 0xc3 +// /* "":7464:7481 */ +// calldataload +// /* "":7502:7519 */ +// swapn{134} +// /* "":7515:7518 */ +// 0xc4 +// /* "":7502:7519 */ +// calldataload +// /* "":7540:7557 */ +// swapn{136} +// /* "":7553:7556 */ +// 0xc5 +// /* "":7540:7557 */ +// calldataload +// /* "":7578:7595 */ +// swapn{138} +// /* "":7591:7594 */ +// 0xc6 +// /* "":7578:7595 */ +// calldataload +// /* "":7616:7633 */ +// swapn{140} +// /* "":7629:7632 */ +// 0xc7 +// /* "":7616:7633 */ +// calldataload +// /* "":7654:7671 */ +// swapn{142} +// /* "":7667:7670 */ +// 0xc8 +// /* "":7654:7671 */ +// calldataload +// /* "":7692:7709 */ +// swapn{144} +// /* "":7705:7708 */ +// 0xc9 +// /* "":7692:7709 */ +// calldataload +// /* "":7730:7747 */ +// swapn{146} +// /* "":7743:7746 */ +// 0xca +// /* "":7730:7747 */ +// calldataload +// /* "":7768:7785 */ +// swapn{148} +// /* "":7781:7784 */ +// 0xcb +// /* "":7768:7785 */ +// calldataload +// /* "":7806:7823 */ +// swapn{150} +// /* "":7819:7822 */ +// 0xcc +// /* "":7806:7823 */ +// calldataload +// /* "":7844:7861 */ +// swapn{152} +// /* "":7857:7860 */ +// 0xcd +// /* "":7844:7861 */ +// calldataload +// /* "":7882:7899 */ +// swapn{154} +// /* "":7895:7898 */ +// 0xce +// /* "":7882:7899 */ +// calldataload +// /* "":7920:7937 */ +// swapn{156} +// /* "":7933:7936 */ +// 0xcf +// /* "":7920:7937 */ +// calldataload +// /* "":7958:7975 */ +// swapn{158} +// /* "":7971:7974 */ +// 0xd0 +// /* "":7958:7975 */ +// calldataload +// /* "":7996:8013 */ +// swapn{160} +// /* "":8009:8012 */ +// 0xd1 +// /* "":7996:8013 */ +// calldataload +// /* "":8034:8051 */ +// swapn{162} +// /* "":8047:8050 */ +// 0xd2 +// /* "":8034:8051 */ +// calldataload +// /* "":8072:8089 */ +// swapn{164} +// /* "":8085:8088 */ +// 0xd3 +// /* "":8072:8089 */ +// calldataload +// /* "":8110:8127 */ +// swapn{166} +// /* "":8123:8126 */ +// 0xd4 +// /* "":8110:8127 */ +// calldataload +// /* "":8148:8165 */ +// swapn{168} +// /* "":8161:8164 */ +// 0xd5 +// /* "":8148:8165 */ +// calldataload +// /* "":8186:8203 */ +// swapn{170} +// /* "":8199:8202 */ +// 0xd6 +// /* "":8186:8203 */ +// calldataload +// /* "":8224:8241 */ +// swapn{172} +// /* "":8237:8240 */ +// 0xd7 +// /* "":8224:8241 */ +// calldataload +// /* "":8262:8279 */ +// swapn{174} +// /* "":8275:8278 */ +// 0xd8 +// /* "":8262:8279 */ +// calldataload +// /* "":8300:8317 */ +// swapn{176} +// /* "":8313:8316 */ +// 0xd9 +// /* "":8300:8317 */ +// calldataload +// /* "":8338:8355 */ +// swapn{178} +// /* "":8351:8354 */ +// 0xda +// /* "":8338:8355 */ +// calldataload +// /* "":8376:8393 */ +// swapn{180} +// /* "":8389:8392 */ +// 0xdb +// /* "":8376:8393 */ +// calldataload +// /* "":8414:8431 */ +// swapn{182} +// /* "":8427:8430 */ +// 0xdc +// /* "":8414:8431 */ +// calldataload +// /* "":8452:8469 */ +// swapn{184} +// /* "":8465:8468 */ +// 0xdd +// /* "":8452:8469 */ +// calldataload +// /* "":8490:8507 */ +// swapn{186} +// /* "":8503:8506 */ +// 0xde +// /* "":8490:8507 */ +// calldataload +// /* "":8528:8545 */ +// swapn{188} +// /* "":8541:8544 */ +// 0xdf +// /* "":8528:8545 */ +// calldataload +// /* "":8566:8583 */ +// swapn{190} +// /* "":8579:8582 */ +// 0xe0 +// /* "":8566:8583 */ +// calldataload +// /* "":8604:8621 */ +// swapn{192} +// /* "":8617:8620 */ +// 0xe1 +// /* "":8604:8621 */ +// calldataload +// /* "":8642:8659 */ +// swapn{194} +// /* "":8655:8658 */ +// 0xe2 +// /* "":8642:8659 */ +// calldataload +// /* "":8680:8697 */ +// swapn{196} +// /* "":8693:8696 */ +// 0xe3 +// /* "":8680:8697 */ +// calldataload +// /* "":8718:8735 */ +// swapn{198} +// /* "":8731:8734 */ +// 0xe4 +// /* "":8718:8735 */ +// calldataload +// /* "":8756:8773 */ +// swapn{200} +// /* "":8769:8772 */ +// 0xe5 +// /* "":8756:8773 */ +// calldataload +// /* "":8794:8811 */ +// swapn{202} +// /* "":8807:8810 */ +// 0xe6 +// /* "":8794:8811 */ +// calldataload +// /* "":8832:8849 */ +// swapn{204} +// /* "":8845:8848 */ +// 0xe7 +// /* "":8832:8849 */ +// calldataload +// /* "":8870:8887 */ +// swapn{206} +// /* "":8883:8886 */ +// 0xe8 +// /* "":8870:8887 */ +// calldataload +// /* "":8908:8925 */ +// swapn{208} +// /* "":8921:8924 */ +// 0xe9 +// /* "":8908:8925 */ +// calldataload +// /* "":8946:8963 */ +// swapn{210} +// /* "":8959:8962 */ +// 0xea +// /* "":8946:8963 */ +// calldataload +// /* "":8984:9001 */ +// swapn{212} +// /* "":8997:9000 */ +// 0xeb +// /* "":8984:9001 */ +// calldataload +// /* "":9022:9039 */ +// swapn{214} +// /* "":9035:9038 */ +// 0xec +// /* "":9022:9039 */ +// calldataload +// /* "":9060:9077 */ +// swapn{216} +// /* "":9073:9076 */ +// 0xed +// /* "":9060:9077 */ +// calldataload +// /* "":9098:9115 */ +// swapn{218} +// /* "":9111:9114 */ +// 0xee +// /* "":9098:9115 */ +// calldataload +// /* "":9136:9153 */ +// swapn{220} +// /* "":9149:9152 */ +// 0xef +// /* "":9136:9153 */ +// calldataload +// /* "":9174:9191 */ +// swapn{222} +// /* "":9187:9190 */ +// 0xf0 +// /* "":9174:9191 */ +// calldataload +// /* "":9212:9229 */ +// swapn{224} +// /* "":9225:9228 */ +// 0xf1 +// /* "":9212:9229 */ +// calldataload +// /* "":9250:9267 */ +// swapn{226} +// /* "":9263:9266 */ +// 0xf2 +// /* "":9250:9267 */ +// calldataload +// /* "":9288:9305 */ +// swapn{228} +// /* "":9301:9304 */ +// 0xf3 +// /* "":9288:9305 */ +// calldataload +// /* "":9326:9343 */ +// swapn{230} +// /* "":9339:9342 */ +// 0xf4 +// /* "":9326:9343 */ +// calldataload +// /* "":9364:9381 */ +// swapn{232} +// /* "":9377:9380 */ +// 0xf5 +// /* "":9364:9381 */ +// calldataload +// /* "":9402:9419 */ +// swapn{234} +// /* "":9415:9418 */ +// 0xf6 +// /* "":9402:9419 */ +// calldataload +// /* "":9440:9457 */ +// swapn{236} +// /* "":9453:9456 */ +// 0xf7 +// /* "":9440:9457 */ +// calldataload +// /* "":9478:9495 */ +// swapn{238} +// /* "":9491:9494 */ +// 0xf8 +// /* "":9478:9495 */ +// calldataload +// /* "":9516:9533 */ +// swapn{240} +// /* "":9529:9532 */ +// 0xf9 +// /* "":9516:9533 */ +// calldataload +// /* "":9554:9571 */ +// swapn{242} +// /* "":9567:9570 */ +// 0xfa +// /* "":9554:9571 */ +// calldataload +// /* "":9592:9609 */ +// swapn{244} +// /* "":9605:9608 */ +// 0xfb +// /* "":9592:9609 */ +// calldataload +// /* "":9630:9647 */ +// swapn{246} +// /* "":9643:9646 */ +// 0xfc +// /* "":9630:9647 */ +// calldataload +// /* "":9668:9685 */ +// swapn{248} +// /* "":9681:9684 */ +// 0xfd +// /* "":9668:9685 */ +// calldataload +// /* "":9706:9723 */ +// swapn{250} +// /* "":9719:9722 */ +// 0xfe +// /* "":9706:9723 */ +// calldataload +// /* "":9744:9761 */ +// swapn{252} +// /* "":9757:9760 */ +// 0xff +// /* "":9744:9761 */ +// calldataload +// /* "":9782:9799 */ +// swapn{254} +// /* "":9795:9798 */ +// 0x0100 +// /* "":9782:9799 */ +// calldataload +// /* "":9808:9821 */ +// swapn{256} +// /* "":9815:9816 */ +// 0x00 +// /* "":9808:9821 */ +// sstore +// /* "":9837:9838 */ +// 0x01 +// /* "":9830:9843 */ +// sstore +// /* "":9859:9860 */ +// 0x02 +// /* "":9852:9865 */ +// sstore +// /* "":9881:9882 */ +// 0x03 +// /* "":9874:9887 */ +// sstore +// /* "":9903:9904 */ +// 0x04 +// /* "":9896:9909 */ +// sstore +// /* "":9925:9926 */ +// 0x05 +// /* "":9918:9931 */ +// sstore +// /* "":9947:9948 */ +// 0x06 +// /* "":9940:9953 */ +// sstore +// /* "":9969:9970 */ +// 0x07 +// /* "":9962:9975 */ +// sstore +// /* "":9991:9992 */ +// 0x08 +// /* "":9984:9997 */ +// sstore +// /* "":10013:10014 */ +// 0x09 +// /* "":10006:10019 */ +// sstore +// /* "":10035:10037 */ +// 0x0a +// /* "":10028:10043 */ +// sstore +// /* "":10059:10061 */ +// 0x0b +// /* "":10052:10067 */ +// sstore +// /* "":10083:10085 */ +// 0x0c +// /* "":10076:10091 */ +// sstore +// /* "":10107:10109 */ +// 0x0d +// /* "":10100:10115 */ +// sstore +// /* "":10131:10133 */ +// 0x0e +// /* "":10124:10139 */ +// sstore +// /* "":10155:10157 */ +// 0x0f +// /* "":10148:10163 */ +// sstore +// /* "":10179:10181 */ +// 0x10 +// /* "":10172:10187 */ +// sstore +// /* "":10203:10205 */ +// 0x11 +// /* "":10196:10211 */ +// sstore +// /* "":10227:10229 */ +// 0x12 +// /* "":10220:10235 */ +// sstore +// /* "":10251:10253 */ +// 0x13 +// /* "":10244:10259 */ +// sstore +// /* "":10275:10277 */ +// 0x14 +// /* "":10268:10283 */ +// sstore +// /* "":10299:10301 */ +// 0x15 +// /* "":10292:10307 */ +// sstore +// /* "":10323:10325 */ +// 0x16 +// /* "":10316:10331 */ +// sstore +// /* "":10347:10349 */ +// 0x17 +// /* "":10340:10355 */ +// sstore +// /* "":10371:10373 */ +// 0x18 +// /* "":10364:10379 */ +// sstore +// /* "":10395:10397 */ +// 0x19 +// /* "":10388:10403 */ +// sstore +// /* "":10419:10421 */ +// 0x1a +// /* "":10412:10427 */ +// sstore +// /* "":10443:10445 */ +// 0x1b +// /* "":10436:10451 */ +// sstore +// /* "":10467:10469 */ +// 0x1c +// /* "":10460:10475 */ +// sstore +// /* "":10491:10493 */ +// 0x1d +// /* "":10484:10499 */ +// sstore +// /* "":10515:10517 */ +// 0x1e +// /* "":10508:10523 */ +// sstore +// /* "":10539:10541 */ +// 0x1f +// /* "":10532:10547 */ +// sstore +// /* "":10563:10565 */ +// 0x20 +// /* "":10556:10571 */ +// sstore +// /* "":10587:10589 */ +// 0x21 +// /* "":10580:10595 */ +// sstore +// /* "":10611:10613 */ +// 0x22 +// /* "":10604:10619 */ +// sstore +// /* "":10635:10637 */ +// 0x23 +// /* "":10628:10643 */ +// sstore +// /* "":10659:10661 */ +// 0x24 +// /* "":10652:10667 */ +// sstore +// /* "":10683:10685 */ +// 0x25 +// /* "":10676:10691 */ +// sstore +// /* "":10707:10709 */ +// 0x26 +// /* "":10700:10715 */ +// sstore +// /* "":10731:10733 */ +// 0x27 +// /* "":10724:10739 */ +// sstore +// /* "":10755:10757 */ +// 0x28 +// /* "":10748:10763 */ +// sstore +// /* "":10779:10781 */ +// 0x29 +// /* "":10772:10787 */ +// sstore +// /* "":10803:10805 */ +// 0x2a +// /* "":10796:10811 */ +// sstore +// /* "":10827:10829 */ +// 0x2b +// /* "":10820:10835 */ +// sstore +// /* "":10851:10853 */ +// 0x2c +// /* "":10844:10859 */ +// sstore +// /* "":10875:10877 */ +// 0x2d +// /* "":10868:10883 */ +// sstore +// /* "":10899:10901 */ +// 0x2e +// /* "":10892:10907 */ +// sstore +// /* "":10923:10925 */ +// 0x2f +// /* "":10916:10931 */ +// sstore +// /* "":10947:10949 */ +// 0x30 +// /* "":10940:10955 */ +// sstore +// /* "":10971:10973 */ +// 0x31 +// /* "":10964:10979 */ +// sstore +// /* "":10995:10997 */ +// 0x32 +// /* "":10988:11003 */ +// sstore +// /* "":11019:11021 */ +// 0x33 +// /* "":11012:11027 */ +// sstore +// /* "":11043:11045 */ +// 0x34 +// /* "":11036:11051 */ +// sstore +// /* "":11067:11069 */ +// 0x35 +// /* "":11060:11075 */ +// sstore +// /* "":11091:11093 */ +// 0x36 +// /* "":11084:11099 */ +// sstore +// /* "":11115:11117 */ +// 0x37 +// /* "":11108:11123 */ +// sstore +// /* "":11139:11141 */ +// 0x38 +// /* "":11132:11147 */ +// sstore +// /* "":11163:11165 */ +// 0x39 +// /* "":11156:11171 */ +// sstore +// /* "":11187:11189 */ +// 0x3a +// /* "":11180:11195 */ +// sstore +// /* "":11211:11213 */ +// 0x3b +// /* "":11204:11219 */ +// sstore +// /* "":11235:11237 */ +// 0x3c +// /* "":11228:11243 */ +// sstore +// /* "":11259:11261 */ +// 0x3d +// /* "":11252:11267 */ +// sstore +// /* "":11283:11285 */ +// 0x3e +// /* "":11276:11291 */ +// sstore +// /* "":11307:11309 */ +// 0x3f +// /* "":11300:11315 */ +// sstore +// /* "":11331:11333 */ +// 0x40 +// /* "":11324:11339 */ +// sstore +// /* "":11355:11357 */ +// 0x41 +// /* "":11348:11363 */ +// sstore +// /* "":11379:11381 */ +// 0x42 +// /* "":11372:11387 */ +// sstore +// /* "":11403:11405 */ +// 0x43 +// /* "":11396:11411 */ +// sstore +// /* "":11427:11429 */ +// 0x44 +// /* "":11420:11435 */ +// sstore +// /* "":11451:11453 */ +// 0x45 +// /* "":11444:11459 */ +// sstore +// /* "":11475:11477 */ +// 0x46 +// /* "":11468:11483 */ +// sstore +// /* "":11499:11501 */ +// 0x47 +// /* "":11492:11507 */ +// sstore +// /* "":11523:11525 */ +// 0x48 +// /* "":11516:11531 */ +// sstore +// /* "":11547:11549 */ +// 0x49 +// /* "":11540:11555 */ +// sstore +// /* "":11571:11573 */ +// 0x4a +// /* "":11564:11579 */ +// sstore +// /* "":11595:11597 */ +// 0x4b +// /* "":11588:11603 */ +// sstore +// /* "":11619:11621 */ +// 0x4c +// /* "":11612:11627 */ +// sstore +// /* "":11643:11645 */ +// 0x4d +// /* "":11636:11651 */ +// sstore +// /* "":11667:11669 */ +// 0x4e +// /* "":11660:11675 */ +// sstore +// /* "":11691:11693 */ +// 0x4f +// /* "":11684:11699 */ +// sstore +// /* "":11715:11717 */ +// 0x50 +// /* "":11708:11723 */ +// sstore +// /* "":11739:11741 */ +// 0x51 +// /* "":11732:11747 */ +// sstore +// /* "":11763:11765 */ +// 0x52 +// /* "":11756:11771 */ +// sstore +// /* "":11787:11789 */ +// 0x53 +// /* "":11780:11795 */ +// sstore +// /* "":11811:11813 */ +// 0x54 +// /* "":11804:11819 */ +// sstore +// /* "":11835:11837 */ +// 0x55 +// /* "":11828:11843 */ +// sstore +// /* "":11859:11861 */ +// 0x56 +// /* "":11852:11867 */ +// sstore +// /* "":11883:11885 */ +// 0x57 +// /* "":11876:11891 */ +// sstore +// /* "":11907:11909 */ +// 0x58 +// /* "":11900:11915 */ +// sstore +// /* "":11931:11933 */ +// 0x59 +// /* "":11924:11939 */ +// sstore +// /* "":11955:11957 */ +// 0x5a +// /* "":11948:11963 */ +// sstore +// /* "":11979:11981 */ +// 0x5b +// /* "":11972:11987 */ +// sstore +// /* "":12003:12005 */ +// 0x5c +// /* "":11996:12011 */ +// sstore +// /* "":12027:12029 */ +// 0x5d +// /* "":12020:12035 */ +// sstore +// /* "":12051:12053 */ +// 0x5e +// /* "":12044:12059 */ +// sstore +// /* "":12075:12077 */ +// 0x5f +// /* "":12068:12083 */ +// sstore +// /* "":12099:12101 */ +// 0x60 +// /* "":12092:12107 */ +// sstore +// /* "":12123:12125 */ +// 0x61 +// /* "":12116:12131 */ +// sstore +// /* "":12147:12149 */ +// 0x62 +// /* "":12140:12155 */ +// sstore +// /* "":12171:12173 */ +// 0x63 +// /* "":12164:12179 */ +// sstore +// /* "":12195:12198 */ +// 0x64 +// /* "":12188:12205 */ +// sstore +// /* "":12221:12224 */ +// 0x65 +// /* "":12214:12231 */ +// sstore +// /* "":12247:12250 */ +// 0x66 +// /* "":12240:12257 */ +// sstore +// /* "":12273:12276 */ +// 0x67 +// /* "":12266:12283 */ +// sstore +// /* "":12299:12302 */ +// 0x68 +// /* "":12292:12309 */ +// sstore +// /* "":12325:12328 */ +// 0x69 +// /* "":12318:12335 */ +// sstore +// /* "":12351:12354 */ +// 0x6a +// /* "":12344:12361 */ +// sstore +// /* "":12377:12380 */ +// 0x6b +// /* "":12370:12387 */ +// sstore +// /* "":12403:12406 */ +// 0x6c +// /* "":12396:12413 */ +// sstore +// /* "":12429:12432 */ +// 0x6d +// /* "":12422:12439 */ +// sstore +// /* "":12455:12458 */ +// 0x6e +// /* "":12448:12465 */ +// sstore +// /* "":12481:12484 */ +// 0x6f +// /* "":12474:12491 */ +// sstore +// /* "":12507:12510 */ +// 0x70 +// /* "":12500:12517 */ +// sstore +// /* "":12533:12536 */ +// 0x71 +// /* "":12526:12543 */ +// sstore +// /* "":12559:12562 */ +// 0x72 +// /* "":12552:12569 */ +// sstore +// /* "":12585:12588 */ +// 0x73 +// /* "":12578:12595 */ +// sstore +// /* "":12611:12614 */ +// 0x74 +// /* "":12604:12621 */ +// sstore +// /* "":12637:12640 */ +// 0x75 +// /* "":12630:12647 */ +// sstore +// /* "":12663:12666 */ +// 0x76 +// /* "":12656:12673 */ +// sstore +// /* "":12689:12692 */ +// 0x77 +// /* "":12682:12699 */ +// sstore +// /* "":12715:12718 */ +// 0x78 +// /* "":12708:12725 */ +// sstore +// /* "":12741:12744 */ +// 0x79 +// /* "":12734:12751 */ +// sstore +// /* "":12767:12770 */ +// 0x7a +// /* "":12760:12777 */ +// sstore +// /* "":12793:12796 */ +// 0x7b +// /* "":12786:12803 */ +// sstore +// /* "":12819:12822 */ +// 0x7c +// /* "":12812:12829 */ +// sstore +// /* "":12845:12848 */ +// 0x7d +// /* "":12838:12855 */ +// sstore +// /* "":12871:12874 */ +// 0x7e +// /* "":12864:12881 */ +// sstore +// /* "":12897:12900 */ +// 0x7f +// /* "":12890:12907 */ +// sstore +// /* "":12923:12926 */ +// 0x80 +// /* "":12916:12933 */ +// sstore +// /* "":12949:12952 */ +// 0x81 +// /* "":12942:12959 */ +// sstore +// /* "":12975:12978 */ +// 0x82 +// /* "":12968:12985 */ +// sstore +// /* "":13001:13004 */ +// 0x83 +// /* "":12994:13011 */ +// sstore +// /* "":13027:13030 */ +// 0x84 +// /* "":13020:13037 */ +// sstore +// /* "":13053:13056 */ +// 0x85 +// /* "":13046:13063 */ +// sstore +// /* "":13079:13082 */ +// 0x86 +// /* "":13072:13089 */ +// sstore +// /* "":13105:13108 */ +// 0x87 +// /* "":13098:13115 */ +// sstore +// /* "":13131:13134 */ +// 0x88 +// /* "":13124:13141 */ +// sstore +// /* "":13157:13160 */ +// 0x89 +// /* "":13150:13167 */ +// sstore +// /* "":13183:13186 */ +// 0x8a +// /* "":13176:13193 */ +// sstore +// /* "":13209:13212 */ +// 0x8b +// /* "":13202:13219 */ +// sstore +// /* "":13235:13238 */ +// 0x8c +// /* "":13228:13245 */ +// sstore +// /* "":13261:13264 */ +// 0x8d +// /* "":13254:13271 */ +// sstore +// /* "":13287:13290 */ +// 0x8e +// /* "":13280:13297 */ +// sstore +// /* "":13313:13316 */ +// 0x8f +// /* "":13306:13323 */ +// sstore +// /* "":13339:13342 */ +// 0x90 +// /* "":13332:13349 */ +// sstore +// /* "":13365:13368 */ +// 0x91 +// /* "":13358:13375 */ +// sstore +// /* "":13391:13394 */ +// 0x92 +// /* "":13384:13401 */ +// sstore +// /* "":13417:13420 */ +// 0x93 +// /* "":13410:13427 */ +// sstore +// /* "":13443:13446 */ +// 0x94 +// /* "":13436:13453 */ +// sstore +// /* "":13469:13472 */ +// 0x95 +// /* "":13462:13479 */ +// sstore +// /* "":13495:13498 */ +// 0x96 +// /* "":13488:13505 */ +// sstore +// /* "":13521:13524 */ +// 0x97 +// /* "":13514:13531 */ +// sstore +// /* "":13547:13550 */ +// 0x98 +// /* "":13540:13557 */ +// sstore +// /* "":13573:13576 */ +// 0x99 +// /* "":13566:13583 */ +// sstore +// /* "":13599:13602 */ +// 0x9a +// /* "":13592:13609 */ +// sstore +// /* "":13625:13628 */ +// 0x9b +// /* "":13618:13635 */ +// sstore +// /* "":13651:13654 */ +// 0x9c +// /* "":13644:13661 */ +// sstore +// /* "":13677:13680 */ +// 0x9d +// /* "":13670:13687 */ +// sstore +// /* "":13703:13706 */ +// 0x9e +// /* "":13696:13713 */ +// sstore +// /* "":13729:13732 */ +// 0x9f +// /* "":13722:13739 */ +// sstore +// /* "":13755:13758 */ +// 0xa0 +// /* "":13748:13765 */ +// sstore +// /* "":13781:13784 */ +// 0xa1 +// /* "":13774:13791 */ +// sstore +// /* "":13807:13810 */ +// 0xa2 +// /* "":13800:13817 */ +// sstore +// /* "":13833:13836 */ +// 0xa3 +// /* "":13826:13843 */ +// sstore +// /* "":13859:13862 */ +// 0xa4 +// /* "":13852:13869 */ +// sstore +// /* "":13885:13888 */ +// 0xa5 +// /* "":13878:13895 */ +// sstore +// /* "":13911:13914 */ +// 0xa6 +// /* "":13904:13921 */ +// sstore +// /* "":13937:13940 */ +// 0xa7 +// /* "":13930:13947 */ +// sstore +// /* "":13963:13966 */ +// 0xa8 +// /* "":13956:13973 */ +// sstore +// /* "":13989:13992 */ +// 0xa9 +// /* "":13982:13999 */ +// sstore +// /* "":14015:14018 */ +// 0xaa +// /* "":14008:14025 */ +// sstore +// /* "":14041:14044 */ +// 0xab +// /* "":14034:14051 */ +// sstore +// /* "":14067:14070 */ +// 0xac +// /* "":14060:14077 */ +// sstore +// /* "":14093:14096 */ +// 0xad +// /* "":14086:14103 */ +// sstore +// /* "":14119:14122 */ +// 0xae +// /* "":14112:14129 */ +// sstore +// /* "":14145:14148 */ +// 0xaf +// /* "":14138:14155 */ +// sstore +// /* "":14171:14174 */ +// 0xb0 +// /* "":14164:14181 */ +// sstore +// /* "":14197:14200 */ +// 0xb1 +// /* "":14190:14207 */ +// sstore +// /* "":14223:14226 */ +// 0xb2 +// /* "":14216:14233 */ +// sstore +// /* "":14249:14252 */ +// 0xb3 +// /* "":14242:14259 */ +// sstore +// /* "":14275:14278 */ +// 0xb4 +// /* "":14268:14285 */ +// sstore +// /* "":14301:14304 */ +// 0xb5 +// /* "":14294:14311 */ +// sstore +// /* "":14327:14330 */ +// 0xb6 +// /* "":14320:14337 */ +// sstore +// /* "":14353:14356 */ +// 0xb7 +// /* "":14346:14363 */ +// sstore +// /* "":14379:14382 */ +// 0xb8 +// /* "":14372:14389 */ +// sstore +// /* "":14405:14408 */ +// 0xb9 +// /* "":14398:14415 */ +// sstore +// /* "":14431:14434 */ +// 0xba +// /* "":14424:14441 */ +// sstore +// /* "":14457:14460 */ +// 0xbb +// /* "":14450:14467 */ +// sstore +// /* "":14483:14486 */ +// 0xbc +// /* "":14476:14493 */ +// sstore +// /* "":14509:14512 */ +// 0xbd +// /* "":14502:14519 */ +// sstore +// /* "":14535:14538 */ +// 0xbe +// /* "":14528:14545 */ +// sstore +// /* "":14561:14564 */ +// 0xbf +// /* "":14554:14571 */ +// sstore +// /* "":14587:14590 */ +// 0xc0 +// /* "":14580:14597 */ +// sstore +// /* "":14613:14616 */ +// 0xc1 +// /* "":14606:14623 */ +// sstore +// /* "":14639:14642 */ +// 0xc2 +// /* "":14632:14649 */ +// sstore +// /* "":14665:14668 */ +// 0xc3 +// /* "":14658:14675 */ +// sstore +// /* "":14691:14694 */ +// 0xc4 +// /* "":14684:14701 */ +// sstore +// /* "":14717:14720 */ +// 0xc5 +// /* "":14710:14727 */ +// sstore +// /* "":14743:14746 */ +// 0xc6 +// /* "":14736:14753 */ +// sstore +// /* "":14769:14772 */ +// 0xc7 +// /* "":14762:14779 */ +// sstore +// /* "":14795:14798 */ +// 0xc8 +// /* "":14788:14805 */ +// sstore +// /* "":14821:14824 */ +// 0xc9 +// /* "":14814:14831 */ +// sstore +// /* "":14847:14850 */ +// 0xca +// /* "":14840:14857 */ +// sstore +// /* "":14873:14876 */ +// 0xcb +// /* "":14866:14883 */ +// sstore +// /* "":14899:14902 */ +// 0xcc +// /* "":14892:14909 */ +// sstore +// /* "":14925:14928 */ +// 0xcd +// /* "":14918:14935 */ +// sstore +// /* "":14951:14954 */ +// 0xce +// /* "":14944:14961 */ +// sstore +// /* "":14977:14980 */ +// 0xcf +// /* "":14970:14987 */ +// sstore +// /* "":15003:15006 */ +// 0xd0 +// /* "":14996:15013 */ +// sstore +// /* "":15029:15032 */ +// 0xd1 +// /* "":15022:15039 */ +// sstore +// /* "":15055:15058 */ +// 0xd2 +// /* "":15048:15065 */ +// sstore +// /* "":15081:15084 */ +// 0xd3 +// /* "":15074:15091 */ +// sstore +// /* "":15107:15110 */ +// 0xd4 +// /* "":15100:15117 */ +// sstore +// /* "":15133:15136 */ +// 0xd5 +// /* "":15126:15143 */ +// sstore +// /* "":15159:15162 */ +// 0xd6 +// /* "":15152:15169 */ +// sstore +// /* "":15185:15188 */ +// 0xd7 +// /* "":15178:15195 */ +// sstore +// /* "":15211:15214 */ +// 0xd8 +// /* "":15204:15221 */ +// sstore +// /* "":15237:15240 */ +// 0xd9 +// /* "":15230:15247 */ +// sstore +// /* "":15263:15266 */ +// 0xda +// /* "":15256:15273 */ +// sstore +// /* "":15289:15292 */ +// 0xdb +// /* "":15282:15299 */ +// sstore +// /* "":15315:15318 */ +// 0xdc +// /* "":15308:15325 */ +// sstore +// /* "":15341:15344 */ +// 0xdd +// /* "":15334:15351 */ +// sstore +// /* "":15367:15370 */ +// 0xde +// /* "":15360:15377 */ +// sstore +// /* "":15393:15396 */ +// 0xdf +// /* "":15386:15403 */ +// sstore +// /* "":15419:15422 */ +// 0xe0 +// /* "":15412:15429 */ +// sstore +// /* "":15445:15448 */ +// 0xe1 +// /* "":15438:15455 */ +// sstore +// /* "":15471:15474 */ +// 0xe2 +// /* "":15464:15481 */ +// sstore +// /* "":15497:15500 */ +// 0xe3 +// /* "":15490:15507 */ +// sstore +// /* "":15523:15526 */ +// 0xe4 +// /* "":15516:15533 */ +// sstore +// /* "":15549:15552 */ +// 0xe5 +// /* "":15542:15559 */ +// sstore +// /* "":15575:15578 */ +// 0xe6 +// /* "":15568:15585 */ +// sstore +// /* "":15601:15604 */ +// 0xe7 +// /* "":15594:15611 */ +// sstore +// /* "":15627:15630 */ +// 0xe8 +// /* "":15620:15637 */ +// sstore +// /* "":15653:15656 */ +// 0xe9 +// /* "":15646:15663 */ +// sstore +// /* "":15679:15682 */ +// 0xea +// /* "":15672:15689 */ +// sstore +// /* "":15705:15708 */ +// 0xeb +// /* "":15698:15715 */ +// sstore +// /* "":15731:15734 */ +// 0xec +// /* "":15724:15741 */ +// sstore +// /* "":15757:15760 */ +// 0xed +// /* "":15750:15767 */ +// sstore +// /* "":15783:15786 */ +// 0xee +// /* "":15776:15793 */ +// sstore +// /* "":15809:15812 */ +// 0xef +// /* "":15802:15819 */ +// sstore +// /* "":15835:15838 */ +// 0xf0 +// /* "":15828:15845 */ +// sstore +// /* "":15861:15864 */ +// 0xf1 +// /* "":15854:15871 */ +// sstore +// /* "":15887:15890 */ +// 0xf2 +// /* "":15880:15897 */ +// sstore +// /* "":15913:15916 */ +// 0xf3 +// /* "":15906:15923 */ +// sstore +// /* "":15939:15942 */ +// 0xf4 +// /* "":15932:15949 */ +// sstore +// /* "":15965:15968 */ +// 0xf5 +// /* "":15958:15975 */ +// sstore +// /* "":15991:15994 */ +// 0xf6 +// /* "":15984:16001 */ +// sstore +// /* "":16017:16020 */ +// 0xf7 +// /* "":16010:16027 */ +// sstore +// /* "":16043:16046 */ +// 0xf8 +// /* "":16036:16053 */ +// sstore +// /* "":16069:16072 */ +// 0xf9 +// /* "":16062:16079 */ +// sstore +// /* "":16095:16098 */ +// 0xfa +// /* "":16088:16105 */ +// sstore +// /* "":16121:16124 */ +// 0xfb +// /* "":16114:16131 */ +// sstore +// /* "":16147:16150 */ +// 0xfc +// /* "":16140:16157 */ +// sstore +// /* "":16173:16176 */ +// 0xfd +// /* "":16166:16183 */ +// sstore +// /* "":16199:16202 */ +// 0xfe +// /* "":16192:16209 */ +// sstore +// /* "":16225:16228 */ +// 0xff +// /* "":16218:16235 */ +// sstore +// /* "":16251:16254 */ +// 0x0100 +// /* "":16244:16261 */ +// sstore +// /* "":25:16267 */ +// stop diff --git a/test/libyul/evmCodeTransform/literal_loop.yul b/test/libyul/evmCodeTransform/literal_loop.yul index d743836cbcdb..060d0f428f64 100644 --- a/test/libyul/evmCodeTransform/literal_loop.yul +++ b/test/libyul/evmCodeTransform/literal_loop.yul @@ -14,6 +14,7 @@ object "main" { } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":62:82 */ // dataSize(sub_0) diff --git a/test/libyul/evmCodeTransform/nonempty_initial_layout.yul b/test/libyul/evmCodeTransform/nonempty_initial_layout.yul index eb1a787c061f..df22777245e6 100644 --- a/test/libyul/evmCodeTransform/nonempty_initial_layout.yul +++ b/test/libyul/evmCodeTransform/nonempty_initial_layout.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":9:69 */ // 0x2000000000000000000000000000000000000000000000000000000000 diff --git a/test/libyul/evmCodeTransform/pops_in_reverting_branch.yul b/test/libyul/evmCodeTransform/pops_in_reverting_branch.yul index 78bf0a168268..5c1f027a47eb 100644 --- a/test/libyul/evmCodeTransform/pops_in_reverting_branch.yul +++ b/test/libyul/evmCodeTransform/pops_in_reverting_branch.yul @@ -10,6 +10,7 @@ object "main" { } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":51:52 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/eof/function_argument_reuse_without_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/eof/function_argument_reuse_without_retparams.yul new file mode 100644 index 000000000000..77423e88c067 --- /dev/null +++ b/test/libyul/evmCodeTransform/stackReuse/eof/function_argument_reuse_without_retparams.yul @@ -0,0 +1,45 @@ +{ + function f(x, y) { + mstore(0x80, x) + if calldataload(0) { sstore(y, y) } + } + + f(0, 0) +} +// ==== +// bytecodeFormat: >=EOFv1 +// stackOptimization: true +// ---- +// /* "":95:96 */ +// 0x00 +// /* "":90:97 */ +// dup1 +// callf{code_section_1} +// /* "":0:99 */ +// stop +// +// code_section_1: assembly { +// /* "":34:38 */ +// 0x80 +// /* "":27:42 */ +// mstore +// /* "":63:64 */ +// 0x00 +// /* "":50:65 */ +// calldataload +// /* "":47:82 */ +// rjumpi{tag_1} +// /* "":21:86 */ +// tag_2: +// /* "":4:86 */ +// pop +// retf +// /* "":66:82 */ +// tag_1: +// /* "":68:80 */ +// dup1 +// sstore +// /* "":66:82 */ +// 0x00 +// rjump{tag_2} +// } diff --git a/test/libyul/evmCodeTransform/stackReuse/for_1.yul b/test/libyul/evmCodeTransform/stackReuse/for_1.yul index b02710598fd5..92ecf2314055 100644 --- a/test/libyul/evmCodeTransform/stackReuse/for_1.yul +++ b/test/libyul/evmCodeTransform/stackReuse/for_1.yul @@ -1,6 +1,7 @@ { for { let z := 0 } 1 { } { let x := 3 } let t := 2 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":17:18 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/for_2.yul b/test/libyul/evmCodeTransform/stackReuse/for_2.yul index 37d372fb9949..20403c5121c1 100644 --- a/test/libyul/evmCodeTransform/stackReuse/for_2.yul +++ b/test/libyul/evmCodeTransform/stackReuse/for_2.yul @@ -1,6 +1,7 @@ { for { let z := 0 } 1 { } { z := 8 let x := 3 } let t := 2 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":17:18 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul index 96637da89fc1..d56e330918f9 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul @@ -1,10 +1,24 @@ { function f(a, b, c) -> x { pop(address()) sstore(a, c) pop(callvalue()) x := b } + pop(f(0, 0, 0)) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:88 */ +// /* "":95:105 */ +// tag_2 +// /* "":103:104 */ +// 0x00 +// /* "":95:105 */ +// dup1 +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":91:106 */ +// pop +// /* "":0:108 */ // stop // /* "":6:86 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul index b5cc611879ec..c7a82c412f6f 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul @@ -3,12 +3,24 @@ mstore(0x80, x) if calldataload(0) { sstore(y, y) } } + + f(0, 0) } // ==== -// stackOptimization: true // EVMVersion: >=shanghai +// bytecodeFormat: legacy +// stackOptimization: true // ---- -// /* "":0:88 */ +// /* "":90:97 */ +// tag_2 +// /* "":95:96 */ +// 0x00 +// /* "":90:97 */ +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":0:99 */ // stop // /* "":4:86 */ // tag_1: @@ -21,18 +33,18 @@ // /* "":50:65 */ // calldataload // /* "":47:82 */ -// tag_2 +// tag_3 // jumpi // /* "":21:86 */ -// tag_3: +// tag_4: // /* "":4:86 */ // pop // jump // out // /* "":66:82 */ -// tag_2: +// tag_3: // /* "":68:80 */ // dup1 // sstore // /* "":66:82 */ // 0x00 -// jump(tag_3) +// jump(tag_4) diff --git a/test/libyul/evmCodeTransform/stackReuse/function_call.yul b/test/libyul/evmCodeTransform/stackReuse/function_call.yul index 507b354413b6..669d62bb89bb 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_call.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_call.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:22 */ // tag_2 diff --git a/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul b/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul index 17ccdd3caf39..0b2ccf53e867 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul @@ -21,11 +21,43 @@ mstore(0x0340, a19) x := a20 } + + pop(f(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:662 */ +// /* "":670:731 */ +// tag_2 +// /* "":729:730 */ +// 0x00 +// /* "":670:731 */ +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":666:732 */ +// pop +// /* "":0:734 */ // stop // /* "":6:660 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params.yul b/test/libyul/evmCodeTransform/stackReuse/function_params.yul index e8d9bb30cc1b..024074088aac 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params.yul @@ -1,10 +1,22 @@ { function f(a, b) { } + + f(0, 0) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:28 */ +// /* "":32:39 */ +// tag_2 +// /* "":37:38 */ +// 0x00 +// /* "":32:39 */ +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":0:41 */ // stop // /* "":6:26 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul index 52920340055a..0cab17be4e24 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul @@ -1,25 +1,39 @@ -// This does not re-use the parameters for the return parameters +// This does not reuse the parameters for the return parameters // We do not expect parameters to be fully unused, so the stack // layout for a function is still fixed, even though parameters -// can be re-used. +// can be reused. { function f(a, b, c, d) -> x, y { } + + let x, y := f(0, 0, 0, 0) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":212:254 */ +// /* "":268:281 */ +// tag_2 +// /* "":279:280 */ +// 0x00 +// /* "":268:281 */ +// dup1 +// dup1 +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":210:283 */ // stop -// /* "":218:252 */ +// /* "":216:250 */ // tag_1: // pop // pop // pop // pop -// /* "":247:248 */ +// /* "":245:246 */ // 0x00 -// /* "":244:245 */ +// /* "":242:243 */ // 0x00 -// /* "":218:252 */ +// /* "":216:250 */ // swap2 // jump // out diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul index d0fc0506f88c..0817702d83c6 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul @@ -1,10 +1,24 @@ { function f(a, b, c, d) -> x, y { b := 3 let s := 9 y := 2 mstore(s, y) } + + let x, y := f(0, 0, 0, 0) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:80 */ +// /* "":97:110 */ +// tag_2 +// /* "":108:109 */ +// 0x00 +// /* "":97:110 */ +// dup1 +// dup1 +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":0:112 */ // stop // /* "":6:78 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul index bee0d3f635d9..fb3dac49aab1 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul @@ -1,10 +1,18 @@ { function f() -> x, y { } + + let x, y := f() } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:32 */ +// /* "":49:52 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":0:54 */ // stop // /* "":6:30 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul index 5a9e7704e68a..45323ea0c4ff 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul @@ -1,10 +1,20 @@ { function f() -> x { pop(address()) { pop(callvalue()) } } + + pop(f()) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:65 */ +// /* "":74:77 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":70:78 */ +// pop +// /* "":0:80 */ // stop // /* "":6:63 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul index 97bffac381a1..7871b50b9712 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul @@ -1,10 +1,20 @@ { function f() -> x { pop(address()) let y := callvalue() } + + pop(f()) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:65 */ +// /* "":74:77 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":70:78 */ +// pop +// /* "":0:80 */ // stop // /* "":6:63 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul index c18fb7c37e50..7edb118d2d77 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul @@ -1,10 +1,20 @@ { function f() -> x { pop(address()) for { pop(callvalue()) } 0 {} { } } + + pop(f()) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:78 */ +// /* "":86:89 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":82:90 */ +// pop +// /* "":0:92 */ // stop // /* "":6:76 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul index 08dda5a3bc28..ea0e63975214 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul @@ -1,10 +1,20 @@ { function f() -> x { pop(address()) if 1 { pop(callvalue()) } } + + pop(f()) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:70 */ +// /* "":78:81 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":74:82 */ +// pop +// /* "":0:84 */ // stop // /* "":6:68 */ // tag_1: @@ -19,17 +29,17 @@ // /* "":26:40 */ // pop // /* "":41:66 */ -// tag_2 +// tag_3 // jumpi // /* "":24:68 */ -// tag_3: +// tag_4: // /* "":6:68 */ // jump // out // /* "":46:66 */ -// tag_2: +// tag_3: // /* "":52:63 */ // callvalue // /* "":48:64 */ // pop // /* "":46:66 */ -// jump(tag_3) +// jump(tag_4) diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul index 9ac0c00bf8f2..6579d4176823 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul @@ -1,10 +1,20 @@ { function f() -> x { pop(address()) leave pop(callvalue()) } + + pop(f()) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:67 */ +// /* "":75:78 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":71:79 */ +// pop +// /* "":0:81 */ // stop // /* "":6:65 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul index fcc8278e6719..a4a56059cdb9 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul @@ -1,10 +1,20 @@ { function f() -> x { pop(address()) sstore(0, x) pop(callvalue()) } + + pop(f()) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:74 */ +// /* "":82:85 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":78:86 */ +// pop +// /* "":0:88 */ // stop // /* "":6:72 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul index 1cc19a464105..be9b6bbad698 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul @@ -1,10 +1,20 @@ { function f() -> x { pop(callvalue()) } + + pop(f()) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:46 */ +// /* "":54:57 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":50:58 */ +// pop +// /* "":0:60 */ // stop // /* "":6:44 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul index e44e3b43729b..e032b45e752a 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul @@ -1,10 +1,18 @@ { function f() -> x, y, z { pop(callvalue()) } + + let x, y, z := f() } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:52 */ +// /* "":71:74 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":0:76 */ // stop // /* "":6:50 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul b/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul index 3d6286efdb07..adf5ace07e50 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul @@ -1,11 +1,19 @@ { - function f() { } + function f() { } + + f() } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:22 */ +// /* "":28:31 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":0:33 */ // stop -// /* "":4:20 */ +// /* "":6:22 */ // tag_1: // jump // out diff --git a/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul b/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul index f8480bc91ea8..404e9b5ea391 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul @@ -5,9 +5,12 @@ let x := a a := 3 t := a } b := 7 + + pop(f(0, 0)) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x03 @@ -15,7 +18,19 @@ // pop // /* "":182:183 */ // 0x07 -// /* "":0:185 */ +// /* "":193:200 */ +// pop +// tag_2 +// /* "":198:199 */ +// 0x00 +// /* "":193:200 */ +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":189:201 */ +// pop +// /* "":0:203 */ // stop // /* "":21:172 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/functions_multi_return.yul b/test/libyul/evmCodeTransform/stackReuse/functions_multi_return.yul index 1ce02483dcbf..e834b7aa8ef6 100644 --- a/test/libyul/evmCodeTransform/stackReuse/functions_multi_return.yul +++ b/test/libyul/evmCodeTransform/stackReuse/functions_multi_return.yul @@ -9,6 +9,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":74:81 */ // tag_3 diff --git a/test/libyul/evmCodeTransform/stackReuse/if.yul b/test/libyul/evmCodeTransform/stackReuse/if.yul index cee19ab93fdc..23ab75b59bc8 100644 --- a/test/libyul/evmCodeTransform/stackReuse/if.yul +++ b/test/libyul/evmCodeTransform/stackReuse/if.yul @@ -2,6 +2,7 @@ { let z := mload(0) if z { let x := z } let t := 3 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":72:73 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/last_use_in_nested_block.yul b/test/libyul/evmCodeTransform/stackReuse/last_use_in_nested_block.yul index 49ffb3971be3..ed0a297bb649 100644 --- a/test/libyul/evmCodeTransform/stackReuse/last_use_in_nested_block.yul +++ b/test/libyul/evmCodeTransform/stackReuse/last_use_in_nested_block.yul @@ -1,6 +1,7 @@ { let z := 0 { pop(z) } let x := 1 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_same_variable_name.yul b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_same_variable_name.yul index 3404dc53628c..eee735565a68 100644 --- a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_same_variable_name.yul +++ b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_same_variable_name.yul @@ -1,6 +1,7 @@ { let z := mload(0) { let x := 1 x := 6 z := x } { let x := 2 z := x x := 4 } } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":17:18 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot.yul b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot.yul index a80e66c10efa..dde7e1269471 100644 --- a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot.yul +++ b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot.yul @@ -1,6 +1,7 @@ { let x := 1 x := 6 let y := 2 y := 4 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot_nested.yul b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot_nested.yul index db8783502340..fdf2f695bd90 100644 --- a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot_nested.yul +++ b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot_nested.yul @@ -1,6 +1,7 @@ { let x := 1 x := 6 { let y := 2 y := 4 } } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_not_same_scope.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_not_same_scope.yul index 9be91989d00a..4d0531a4dcfb 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_not_same_scope.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_not_same_scope.yul @@ -7,6 +7,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x05 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used.yul index 11e77c62694e..a7ef081e2601 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x05 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used_expr.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used_expr.yul index 214020ccdc37..adaa154614fb 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used_expr.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used_expr.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":37:38 */ // 0x02 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_not_last_used.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_not_last_used.yul index e3002f34d942..3d10ecd42018 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_not_last_used.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_not_last_used.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x05 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul index 13decd3231ae..b9bbeeb385fe 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul @@ -1,6 +1,7 @@ { let a, b, c, d let x := 2 let y := 3 mstore(x, a) mstore(y, c) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":2:16 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function.yul index 13e3065ccc97..1af5c6454acc 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function.yul @@ -4,6 +4,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":58:61 */ // tag_2 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function_with_gaps.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function_with_gaps.yul index f1cde362aef4..329d354ce6e6 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function_with_gaps.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function_with_gaps.yul @@ -8,6 +8,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":106:107 */ // 0x05 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_too_deep_slot.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_too_deep_slot.yul index 2adfe7892bce..a2f2a1b476df 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_too_deep_slot.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_too_deep_slot.yul @@ -32,6 +32,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x07 diff --git a/test/libyul/evmCodeTransform/stackReuse/single_var.yul b/test/libyul/evmCodeTransform/stackReuse/single_var.yul index 09a0d6feeb9e..d42e5928a155 100644 --- a/test/libyul/evmCodeTransform/stackReuse/single_var.yul +++ b/test/libyul/evmCodeTransform/stackReuse/single_var.yul @@ -1,6 +1,7 @@ { let x } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":2:7 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned.yul b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned.yul index ed497467d57e..3d6b68000188 100644 --- a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned.yul +++ b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned.yul @@ -1,6 +1,7 @@ { let x := 1 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code.yul b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code.yul index bec4c834ff58..707c8a30655b 100644 --- a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code.yul +++ b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code.yul @@ -1,6 +1,7 @@ { let x := 1 mstore(3, 4) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code_and_reused.yul b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code_and_reused.yul index b9a814700abd..8f3e28390fdb 100644 --- a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code_and_reused.yul +++ b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code_and_reused.yul @@ -1,6 +1,7 @@ { let x := 1 mstore(3, 4) pop(mload(x)) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/smoke.yul b/test/libyul/evmCodeTransform/stackReuse/smoke.yul index aa46f7a4a538..32b3704fd99a 100644 --- a/test/libyul/evmCodeTransform/stackReuse/smoke.yul +++ b/test/libyul/evmCodeTransform/stackReuse/smoke.yul @@ -1,6 +1,7 @@ {} // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:2 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/switch.yul b/test/libyul/evmCodeTransform/stackReuse/switch.yul index f72d80fad0b5..a7fb935a49f0 100644 --- a/test/libyul/evmCodeTransform/stackReuse/switch.yul +++ b/test/libyul/evmCodeTransform/stackReuse/switch.yul @@ -1,6 +1,7 @@ { let z := 0 switch z case 0 { let x := 2 let y := 3 } default { z := 3 } let t := 9 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stub.yul b/test/libyul/evmCodeTransform/stub.yul index ef7cd668c1c1..f8541dd3f1f7 100644 --- a/test/libyul/evmCodeTransform/stub.yul +++ b/test/libyul/evmCodeTransform/stub.yul @@ -19,6 +19,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":14:21 */ // tag_2 diff --git a/test/libyul/evmCodeTransform/unassigned_return_variable.yul b/test/libyul/evmCodeTransform/unassigned_return_variable.yul index 666fefe1aa64..5ab22f2221e2 100644 --- a/test/libyul/evmCodeTransform/unassigned_return_variable.yul +++ b/test/libyul/evmCodeTransform/unassigned_return_variable.yul @@ -3,12 +3,19 @@ function g(b,s) -> y { y := g(b, g(y, s)) } + + pop(g(0,0)) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- -// /* "":0:111 */ -// stop +// /* "":121:122 */ +// 0x00 +// /* "":117:123 */ +// dup1 +// tag_1 +// jump // in // /* "":60:109 */ // tag_1: // pop diff --git a/test/libyul/functionSideEffects/otherImmovables.yul b/test/libyul/functionSideEffects/otherImmovables.yul index bb02dba1d8ac..01dfd877cdee 100644 --- a/test/libyul/functionSideEffects/otherImmovables.yul +++ b/test/libyul/functionSideEffects/otherImmovables.yul @@ -4,6 +4,8 @@ function g() { stop() } function h() { invalid() } } +// ==== +// bytecodeFormat: legacy // ---- // : movable, movable apart from effects, can be removed, can be removed if no msize // a: can be removed, can be removed if no msize diff --git a/test/libyul/functionSideEffects/state.yul b/test/libyul/functionSideEffects/state.yul index e605ff1e514a..c8b467094132 100644 --- a/test/libyul/functionSideEffects/state.yul +++ b/test/libyul/functionSideEffects/state.yul @@ -3,6 +3,8 @@ function f() { a() } function g() { sstore(0, 1) } } +// ==== +// bytecodeFormat: legacy // ---- // : movable, movable apart from effects, can be removed, can be removed if no msize // a: writes other state, writes storage, writes memory diff --git a/test/libyul/functionSideEffects/storage.yul b/test/libyul/functionSideEffects/storage.yul index 038c368a29d9..3d1e2d836d37 100644 --- a/test/libyul/functionSideEffects/storage.yul +++ b/test/libyul/functionSideEffects/storage.yul @@ -4,6 +4,8 @@ function g() { pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32))} function h() { pop(sload(0))} } +// ==== +// bytecodeFormat: legacy // ---- // : movable, movable apart from effects, can be removed, can be removed if no msize // a: writes storage diff --git a/test/libyul/objectCompiler/data.yul b/test/libyul/objectCompiler/data.yul index ad8899fb11bd..53eb24ce1915 100644 --- a/test/libyul/objectCompiler/data.yul +++ b/test/libyul/objectCompiler/data.yul @@ -1,8 +1,12 @@ object "a" { code {} // Unreferenced data is not added to the assembled bytecode. + // TODO: This is not implemented for EOF. Should work for legacy and EOF when implemented. data "str" "Hello, World!" } +// ==== +// EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/datacopy.yul b/test/libyul/objectCompiler/datacopy.yul index 9f7fca9adc8d..ea00b4478461 100644 --- a/test/libyul/objectCompiler/datacopy.yul +++ b/test/libyul/objectCompiler/datacopy.yul @@ -11,6 +11,9 @@ object "a" { data "data1" "Hello, World!" } } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":77:92 */ diff --git a/test/libyul/objectCompiler/dataoffset_code.yul b/test/libyul/objectCompiler/dataoffset_code.yul index 8ca10add2f26..2a1aa04a14dd 100644 --- a/test/libyul/objectCompiler/dataoffset_code.yul +++ b/test/libyul/objectCompiler/dataoffset_code.yul @@ -5,6 +5,9 @@ object "a" { data "data1" "Hello, World!" } } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":44:61 */ diff --git a/test/libyul/objectCompiler/dataoffset_data.yul b/test/libyul/objectCompiler/dataoffset_data.yul index 915567489816..9490986819e0 100644 --- a/test/libyul/objectCompiler/dataoffset_data.yul +++ b/test/libyul/objectCompiler/dataoffset_data.yul @@ -2,6 +2,9 @@ object "a" { code { sstore(0, dataoffset("data1")) } data "data1" "Hello, World!" } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":56:75 */ diff --git a/test/libyul/objectCompiler/dataoffset_self.yul b/test/libyul/objectCompiler/dataoffset_self.yul index 681c24c0eecb..9f82f5568023 100644 --- a/test/libyul/objectCompiler/dataoffset_self.yul +++ b/test/libyul/objectCompiler/dataoffset_self.yul @@ -2,6 +2,9 @@ object "a" { code { sstore(0, dataoffset("a")) } data "data1" "Hello, World!" } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":44:59 */ diff --git a/test/libyul/objectCompiler/datasize_code.yul b/test/libyul/objectCompiler/datasize_code.yul index cab7987ea9cc..db2fee4d8392 100644 --- a/test/libyul/objectCompiler/datasize_code.yul +++ b/test/libyul/objectCompiler/datasize_code.yul @@ -5,6 +5,9 @@ object "a" { data "data1" "Hello, World!" } } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":44:59 */ diff --git a/test/libyul/objectCompiler/datasize_data.yul b/test/libyul/objectCompiler/datasize_data.yul index d1261d2464a4..52afde6fcad0 100644 --- a/test/libyul/objectCompiler/datasize_data.yul +++ b/test/libyul/objectCompiler/datasize_data.yul @@ -2,6 +2,9 @@ object "a" { code { sstore(0, datasize("data1")) } data "data1" "Hello, World!" } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":44:61 */ diff --git a/test/libyul/objectCompiler/datasize_self.yul b/test/libyul/objectCompiler/datasize_self.yul index 2a19d0a88f69..93512f1da5ac 100644 --- a/test/libyul/objectCompiler/datasize_self.yul +++ b/test/libyul/objectCompiler/datasize_self.yul @@ -2,6 +2,9 @@ object "a" { code { sstore(0, datasize("a")) } data "data1" "Hello, World!" } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":36:49 */ diff --git a/test/libyul/objectCompiler/eof/256_subcontainers.yul b/test/libyul/objectCompiler/eof/256_subcontainers.yul new file mode 100644 index 000000000000..fac0f7b5df29 --- /dev/null +++ b/test/libyul/objectCompiler/eof/256_subcontainers.yul @@ -0,0 +1,4112 @@ +object "a" { + code { + pop(eofcreate("s0000", 0, 0, 0, 0)) + pop(eofcreate("s0001", 0, 0, 0, 0)) + pop(eofcreate("s0002", 0, 0, 0, 0)) + pop(eofcreate("s0003", 0, 0, 0, 0)) + pop(eofcreate("s0004", 0, 0, 0, 0)) + pop(eofcreate("s0005", 0, 0, 0, 0)) + pop(eofcreate("s0006", 0, 0, 0, 0)) + pop(eofcreate("s0007", 0, 0, 0, 0)) + pop(eofcreate("s0008", 0, 0, 0, 0)) + pop(eofcreate("s0009", 0, 0, 0, 0)) + pop(eofcreate("s0010", 0, 0, 0, 0)) + pop(eofcreate("s0011", 0, 0, 0, 0)) + pop(eofcreate("s0012", 0, 0, 0, 0)) + pop(eofcreate("s0013", 0, 0, 0, 0)) + pop(eofcreate("s0014", 0, 0, 0, 0)) + pop(eofcreate("s0015", 0, 0, 0, 0)) + pop(eofcreate("s0016", 0, 0, 0, 0)) + pop(eofcreate("s0017", 0, 0, 0, 0)) + pop(eofcreate("s0018", 0, 0, 0, 0)) + pop(eofcreate("s0019", 0, 0, 0, 0)) + pop(eofcreate("s0020", 0, 0, 0, 0)) + pop(eofcreate("s0021", 0, 0, 0, 0)) + pop(eofcreate("s0022", 0, 0, 0, 0)) + pop(eofcreate("s0023", 0, 0, 0, 0)) + pop(eofcreate("s0024", 0, 0, 0, 0)) + pop(eofcreate("s0025", 0, 0, 0, 0)) + pop(eofcreate("s0026", 0, 0, 0, 0)) + pop(eofcreate("s0027", 0, 0, 0, 0)) + pop(eofcreate("s0028", 0, 0, 0, 0)) + pop(eofcreate("s0029", 0, 0, 0, 0)) + pop(eofcreate("s0030", 0, 0, 0, 0)) + pop(eofcreate("s0031", 0, 0, 0, 0)) + pop(eofcreate("s0032", 0, 0, 0, 0)) + pop(eofcreate("s0033", 0, 0, 0, 0)) + pop(eofcreate("s0034", 0, 0, 0, 0)) + pop(eofcreate("s0035", 0, 0, 0, 0)) + pop(eofcreate("s0036", 0, 0, 0, 0)) + pop(eofcreate("s0037", 0, 0, 0, 0)) + pop(eofcreate("s0038", 0, 0, 0, 0)) + pop(eofcreate("s0039", 0, 0, 0, 0)) + pop(eofcreate("s0040", 0, 0, 0, 0)) + pop(eofcreate("s0041", 0, 0, 0, 0)) + pop(eofcreate("s0042", 0, 0, 0, 0)) + pop(eofcreate("s0043", 0, 0, 0, 0)) + pop(eofcreate("s0044", 0, 0, 0, 0)) + pop(eofcreate("s0045", 0, 0, 0, 0)) + pop(eofcreate("s0046", 0, 0, 0, 0)) + pop(eofcreate("s0047", 0, 0, 0, 0)) + pop(eofcreate("s0048", 0, 0, 0, 0)) + pop(eofcreate("s0049", 0, 0, 0, 0)) + pop(eofcreate("s0050", 0, 0, 0, 0)) + pop(eofcreate("s0051", 0, 0, 0, 0)) + pop(eofcreate("s0052", 0, 0, 0, 0)) + pop(eofcreate("s0053", 0, 0, 0, 0)) + pop(eofcreate("s0054", 0, 0, 0, 0)) + pop(eofcreate("s0055", 0, 0, 0, 0)) + pop(eofcreate("s0056", 0, 0, 0, 0)) + pop(eofcreate("s0057", 0, 0, 0, 0)) + pop(eofcreate("s0058", 0, 0, 0, 0)) + pop(eofcreate("s0059", 0, 0, 0, 0)) + pop(eofcreate("s0060", 0, 0, 0, 0)) + pop(eofcreate("s0061", 0, 0, 0, 0)) + pop(eofcreate("s0062", 0, 0, 0, 0)) + pop(eofcreate("s0063", 0, 0, 0, 0)) + pop(eofcreate("s0064", 0, 0, 0, 0)) + pop(eofcreate("s0065", 0, 0, 0, 0)) + pop(eofcreate("s0066", 0, 0, 0, 0)) + pop(eofcreate("s0067", 0, 0, 0, 0)) + pop(eofcreate("s0068", 0, 0, 0, 0)) + pop(eofcreate("s0069", 0, 0, 0, 0)) + pop(eofcreate("s0070", 0, 0, 0, 0)) + pop(eofcreate("s0071", 0, 0, 0, 0)) + pop(eofcreate("s0072", 0, 0, 0, 0)) + pop(eofcreate("s0073", 0, 0, 0, 0)) + pop(eofcreate("s0074", 0, 0, 0, 0)) + pop(eofcreate("s0075", 0, 0, 0, 0)) + pop(eofcreate("s0076", 0, 0, 0, 0)) + pop(eofcreate("s0077", 0, 0, 0, 0)) + pop(eofcreate("s0078", 0, 0, 0, 0)) + pop(eofcreate("s0079", 0, 0, 0, 0)) + pop(eofcreate("s0080", 0, 0, 0, 0)) + pop(eofcreate("s0081", 0, 0, 0, 0)) + pop(eofcreate("s0082", 0, 0, 0, 0)) + pop(eofcreate("s0083", 0, 0, 0, 0)) + pop(eofcreate("s0084", 0, 0, 0, 0)) + pop(eofcreate("s0085", 0, 0, 0, 0)) + pop(eofcreate("s0086", 0, 0, 0, 0)) + pop(eofcreate("s0087", 0, 0, 0, 0)) + pop(eofcreate("s0088", 0, 0, 0, 0)) + pop(eofcreate("s0089", 0, 0, 0, 0)) + pop(eofcreate("s0090", 0, 0, 0, 0)) + pop(eofcreate("s0091", 0, 0, 0, 0)) + pop(eofcreate("s0092", 0, 0, 0, 0)) + pop(eofcreate("s0093", 0, 0, 0, 0)) + pop(eofcreate("s0094", 0, 0, 0, 0)) + pop(eofcreate("s0095", 0, 0, 0, 0)) + pop(eofcreate("s0096", 0, 0, 0, 0)) + pop(eofcreate("s0097", 0, 0, 0, 0)) + pop(eofcreate("s0098", 0, 0, 0, 0)) + pop(eofcreate("s0099", 0, 0, 0, 0)) + pop(eofcreate("s0100", 0, 0, 0, 0)) + pop(eofcreate("s0101", 0, 0, 0, 0)) + pop(eofcreate("s0102", 0, 0, 0, 0)) + pop(eofcreate("s0103", 0, 0, 0, 0)) + pop(eofcreate("s0104", 0, 0, 0, 0)) + pop(eofcreate("s0105", 0, 0, 0, 0)) + pop(eofcreate("s0106", 0, 0, 0, 0)) + pop(eofcreate("s0107", 0, 0, 0, 0)) + pop(eofcreate("s0108", 0, 0, 0, 0)) + pop(eofcreate("s0109", 0, 0, 0, 0)) + pop(eofcreate("s0110", 0, 0, 0, 0)) + pop(eofcreate("s0111", 0, 0, 0, 0)) + pop(eofcreate("s0112", 0, 0, 0, 0)) + pop(eofcreate("s0113", 0, 0, 0, 0)) + pop(eofcreate("s0114", 0, 0, 0, 0)) + pop(eofcreate("s0115", 0, 0, 0, 0)) + pop(eofcreate("s0116", 0, 0, 0, 0)) + pop(eofcreate("s0117", 0, 0, 0, 0)) + pop(eofcreate("s0118", 0, 0, 0, 0)) + pop(eofcreate("s0119", 0, 0, 0, 0)) + pop(eofcreate("s0120", 0, 0, 0, 0)) + pop(eofcreate("s0121", 0, 0, 0, 0)) + pop(eofcreate("s0122", 0, 0, 0, 0)) + pop(eofcreate("s0123", 0, 0, 0, 0)) + pop(eofcreate("s0124", 0, 0, 0, 0)) + pop(eofcreate("s0125", 0, 0, 0, 0)) + pop(eofcreate("s0126", 0, 0, 0, 0)) + pop(eofcreate("s0127", 0, 0, 0, 0)) + pop(eofcreate("s0128", 0, 0, 0, 0)) + pop(eofcreate("s0129", 0, 0, 0, 0)) + pop(eofcreate("s0130", 0, 0, 0, 0)) + pop(eofcreate("s0131", 0, 0, 0, 0)) + pop(eofcreate("s0132", 0, 0, 0, 0)) + pop(eofcreate("s0133", 0, 0, 0, 0)) + pop(eofcreate("s0134", 0, 0, 0, 0)) + pop(eofcreate("s0135", 0, 0, 0, 0)) + pop(eofcreate("s0136", 0, 0, 0, 0)) + pop(eofcreate("s0137", 0, 0, 0, 0)) + pop(eofcreate("s0138", 0, 0, 0, 0)) + pop(eofcreate("s0139", 0, 0, 0, 0)) + pop(eofcreate("s0140", 0, 0, 0, 0)) + pop(eofcreate("s0141", 0, 0, 0, 0)) + pop(eofcreate("s0142", 0, 0, 0, 0)) + pop(eofcreate("s0143", 0, 0, 0, 0)) + pop(eofcreate("s0144", 0, 0, 0, 0)) + pop(eofcreate("s0145", 0, 0, 0, 0)) + pop(eofcreate("s0146", 0, 0, 0, 0)) + pop(eofcreate("s0147", 0, 0, 0, 0)) + pop(eofcreate("s0148", 0, 0, 0, 0)) + pop(eofcreate("s0149", 0, 0, 0, 0)) + pop(eofcreate("s0150", 0, 0, 0, 0)) + pop(eofcreate("s0151", 0, 0, 0, 0)) + pop(eofcreate("s0152", 0, 0, 0, 0)) + pop(eofcreate("s0153", 0, 0, 0, 0)) + pop(eofcreate("s0154", 0, 0, 0, 0)) + pop(eofcreate("s0155", 0, 0, 0, 0)) + pop(eofcreate("s0156", 0, 0, 0, 0)) + pop(eofcreate("s0157", 0, 0, 0, 0)) + pop(eofcreate("s0158", 0, 0, 0, 0)) + pop(eofcreate("s0159", 0, 0, 0, 0)) + pop(eofcreate("s0160", 0, 0, 0, 0)) + pop(eofcreate("s0161", 0, 0, 0, 0)) + pop(eofcreate("s0162", 0, 0, 0, 0)) + pop(eofcreate("s0163", 0, 0, 0, 0)) + pop(eofcreate("s0164", 0, 0, 0, 0)) + pop(eofcreate("s0165", 0, 0, 0, 0)) + pop(eofcreate("s0166", 0, 0, 0, 0)) + pop(eofcreate("s0167", 0, 0, 0, 0)) + pop(eofcreate("s0168", 0, 0, 0, 0)) + pop(eofcreate("s0169", 0, 0, 0, 0)) + pop(eofcreate("s0170", 0, 0, 0, 0)) + pop(eofcreate("s0171", 0, 0, 0, 0)) + pop(eofcreate("s0172", 0, 0, 0, 0)) + pop(eofcreate("s0173", 0, 0, 0, 0)) + pop(eofcreate("s0174", 0, 0, 0, 0)) + pop(eofcreate("s0175", 0, 0, 0, 0)) + pop(eofcreate("s0176", 0, 0, 0, 0)) + pop(eofcreate("s0177", 0, 0, 0, 0)) + pop(eofcreate("s0178", 0, 0, 0, 0)) + pop(eofcreate("s0179", 0, 0, 0, 0)) + pop(eofcreate("s0180", 0, 0, 0, 0)) + pop(eofcreate("s0181", 0, 0, 0, 0)) + pop(eofcreate("s0182", 0, 0, 0, 0)) + pop(eofcreate("s0183", 0, 0, 0, 0)) + pop(eofcreate("s0184", 0, 0, 0, 0)) + pop(eofcreate("s0185", 0, 0, 0, 0)) + pop(eofcreate("s0186", 0, 0, 0, 0)) + pop(eofcreate("s0187", 0, 0, 0, 0)) + pop(eofcreate("s0188", 0, 0, 0, 0)) + pop(eofcreate("s0189", 0, 0, 0, 0)) + pop(eofcreate("s0190", 0, 0, 0, 0)) + pop(eofcreate("s0191", 0, 0, 0, 0)) + pop(eofcreate("s0192", 0, 0, 0, 0)) + pop(eofcreate("s0193", 0, 0, 0, 0)) + pop(eofcreate("s0194", 0, 0, 0, 0)) + pop(eofcreate("s0195", 0, 0, 0, 0)) + pop(eofcreate("s0196", 0, 0, 0, 0)) + pop(eofcreate("s0197", 0, 0, 0, 0)) + pop(eofcreate("s0198", 0, 0, 0, 0)) + pop(eofcreate("s0199", 0, 0, 0, 0)) + pop(eofcreate("s0200", 0, 0, 0, 0)) + pop(eofcreate("s0201", 0, 0, 0, 0)) + pop(eofcreate("s0202", 0, 0, 0, 0)) + pop(eofcreate("s0203", 0, 0, 0, 0)) + pop(eofcreate("s0204", 0, 0, 0, 0)) + pop(eofcreate("s0205", 0, 0, 0, 0)) + pop(eofcreate("s0206", 0, 0, 0, 0)) + pop(eofcreate("s0207", 0, 0, 0, 0)) + pop(eofcreate("s0208", 0, 0, 0, 0)) + pop(eofcreate("s0209", 0, 0, 0, 0)) + pop(eofcreate("s0210", 0, 0, 0, 0)) + pop(eofcreate("s0211", 0, 0, 0, 0)) + pop(eofcreate("s0212", 0, 0, 0, 0)) + pop(eofcreate("s0213", 0, 0, 0, 0)) + pop(eofcreate("s0214", 0, 0, 0, 0)) + pop(eofcreate("s0215", 0, 0, 0, 0)) + pop(eofcreate("s0216", 0, 0, 0, 0)) + pop(eofcreate("s0217", 0, 0, 0, 0)) + pop(eofcreate("s0218", 0, 0, 0, 0)) + pop(eofcreate("s0219", 0, 0, 0, 0)) + pop(eofcreate("s0220", 0, 0, 0, 0)) + pop(eofcreate("s0221", 0, 0, 0, 0)) + pop(eofcreate("s0222", 0, 0, 0, 0)) + pop(eofcreate("s0223", 0, 0, 0, 0)) + pop(eofcreate("s0224", 0, 0, 0, 0)) + pop(eofcreate("s0225", 0, 0, 0, 0)) + pop(eofcreate("s0226", 0, 0, 0, 0)) + pop(eofcreate("s0227", 0, 0, 0, 0)) + pop(eofcreate("s0228", 0, 0, 0, 0)) + pop(eofcreate("s0229", 0, 0, 0, 0)) + pop(eofcreate("s0230", 0, 0, 0, 0)) + pop(eofcreate("s0231", 0, 0, 0, 0)) + pop(eofcreate("s0232", 0, 0, 0, 0)) + pop(eofcreate("s0233", 0, 0, 0, 0)) + pop(eofcreate("s0234", 0, 0, 0, 0)) + pop(eofcreate("s0235", 0, 0, 0, 0)) + pop(eofcreate("s0236", 0, 0, 0, 0)) + pop(eofcreate("s0237", 0, 0, 0, 0)) + pop(eofcreate("s0238", 0, 0, 0, 0)) + pop(eofcreate("s0239", 0, 0, 0, 0)) + pop(eofcreate("s0240", 0, 0, 0, 0)) + pop(eofcreate("s0241", 0, 0, 0, 0)) + pop(eofcreate("s0242", 0, 0, 0, 0)) + pop(eofcreate("s0243", 0, 0, 0, 0)) + pop(eofcreate("s0244", 0, 0, 0, 0)) + pop(eofcreate("s0245", 0, 0, 0, 0)) + pop(eofcreate("s0246", 0, 0, 0, 0)) + pop(eofcreate("s0247", 0, 0, 0, 0)) + pop(eofcreate("s0248", 0, 0, 0, 0)) + pop(eofcreate("s0249", 0, 0, 0, 0)) + pop(eofcreate("s0250", 0, 0, 0, 0)) + pop(eofcreate("s0251", 0, 0, 0, 0)) + pop(eofcreate("s0252", 0, 0, 0, 0)) + pop(eofcreate("s0253", 0, 0, 0, 0)) + pop(eofcreate("s0254", 0, 0, 0, 0)) + pop(eofcreate("s0255", 0, 0, 0, 0)) + } + + object "s0000" {code{}} + object "s0001" {code{}} + object "s0002" {code{}} + object "s0003" {code{}} + object "s0004" {code{}} + object "s0005" {code{}} + object "s0006" {code{}} + object "s0007" {code{}} + object "s0008" {code{}} + object "s0009" {code{}} + object "s0010" {code{}} + object "s0011" {code{}} + object "s0012" {code{}} + object "s0013" {code{}} + object "s0014" {code{}} + object "s0015" {code{}} + object "s0016" {code{}} + object "s0017" {code{}} + object "s0018" {code{}} + object "s0019" {code{}} + object "s0020" {code{}} + object "s0021" {code{}} + object "s0022" {code{}} + object "s0023" {code{}} + object "s0024" {code{}} + object "s0025" {code{}} + object "s0026" {code{}} + object "s0027" {code{}} + object "s0028" {code{}} + object "s0029" {code{}} + object "s0030" {code{}} + object "s0031" {code{}} + object "s0032" {code{}} + object "s0033" {code{}} + object "s0034" {code{}} + object "s0035" {code{}} + object "s0036" {code{}} + object "s0037" {code{}} + object "s0038" {code{}} + object "s0039" {code{}} + object "s0040" {code{}} + object "s0041" {code{}} + object "s0042" {code{}} + object "s0043" {code{}} + object "s0044" {code{}} + object "s0045" {code{}} + object "s0046" {code{}} + object "s0047" {code{}} + object "s0048" {code{}} + object "s0049" {code{}} + object "s0050" {code{}} + object "s0051" {code{}} + object "s0052" {code{}} + object "s0053" {code{}} + object "s0054" {code{}} + object "s0055" {code{}} + object "s0056" {code{}} + object "s0057" {code{}} + object "s0058" {code{}} + object "s0059" {code{}} + object "s0060" {code{}} + object "s0061" {code{}} + object "s0062" {code{}} + object "s0063" {code{}} + object "s0064" {code{}} + object "s0065" {code{}} + object "s0066" {code{}} + object "s0067" {code{}} + object "s0068" {code{}} + object "s0069" {code{}} + object "s0070" {code{}} + object "s0071" {code{}} + object "s0072" {code{}} + object "s0073" {code{}} + object "s0074" {code{}} + object "s0075" {code{}} + object "s0076" {code{}} + object "s0077" {code{}} + object "s0078" {code{}} + object "s0079" {code{}} + object "s0080" {code{}} + object "s0081" {code{}} + object "s0082" {code{}} + object "s0083" {code{}} + object "s0084" {code{}} + object "s0085" {code{}} + object "s0086" {code{}} + object "s0087" {code{}} + object "s0088" {code{}} + object "s0089" {code{}} + object "s0090" {code{}} + object "s0091" {code{}} + object "s0092" {code{}} + object "s0093" {code{}} + object "s0094" {code{}} + object "s0095" {code{}} + object "s0096" {code{}} + object "s0097" {code{}} + object "s0098" {code{}} + object "s0099" {code{}} + object "s0100" {code{}} + object "s0101" {code{}} + object "s0102" {code{}} + object "s0103" {code{}} + object "s0104" {code{}} + object "s0105" {code{}} + object "s0106" {code{}} + object "s0107" {code{}} + object "s0108" {code{}} + object "s0109" {code{}} + object "s0110" {code{}} + object "s0111" {code{}} + object "s0112" {code{}} + object "s0113" {code{}} + object "s0114" {code{}} + object "s0115" {code{}} + object "s0116" {code{}} + object "s0117" {code{}} + object "s0118" {code{}} + object "s0119" {code{}} + object "s0120" {code{}} + object "s0121" {code{}} + object "s0122" {code{}} + object "s0123" {code{}} + object "s0124" {code{}} + object "s0125" {code{}} + object "s0126" {code{}} + object "s0127" {code{}} + object "s0128" {code{}} + object "s0129" {code{}} + object "s0130" {code{}} + object "s0131" {code{}} + object "s0132" {code{}} + object "s0133" {code{}} + object "s0134" {code{}} + object "s0135" {code{}} + object "s0136" {code{}} + object "s0137" {code{}} + object "s0138" {code{}} + object "s0139" {code{}} + object "s0140" {code{}} + object "s0141" {code{}} + object "s0142" {code{}} + object "s0143" {code{}} + object "s0144" {code{}} + object "s0145" {code{}} + object "s0146" {code{}} + object "s0147" {code{}} + object "s0148" {code{}} + object "s0149" {code{}} + object "s0150" {code{}} + object "s0151" {code{}} + object "s0152" {code{}} + object "s0153" {code{}} + object "s0154" {code{}} + object "s0155" {code{}} + object "s0156" {code{}} + object "s0157" {code{}} + object "s0158" {code{}} + object "s0159" {code{}} + object "s0160" {code{}} + object "s0161" {code{}} + object "s0162" {code{}} + object "s0163" {code{}} + object "s0164" {code{}} + object "s0165" {code{}} + object "s0166" {code{}} + object "s0167" {code{}} + object "s0168" {code{}} + object "s0169" {code{}} + object "s0170" {code{}} + object "s0171" {code{}} + object "s0172" {code{}} + object "s0173" {code{}} + object "s0174" {code{}} + object "s0175" {code{}} + object "s0176" {code{}} + object "s0177" {code{}} + object "s0178" {code{}} + object "s0179" {code{}} + object "s0180" {code{}} + object "s0181" {code{}} + object "s0182" {code{}} + object "s0183" {code{}} + object "s0184" {code{}} + object "s0185" {code{}} + object "s0186" {code{}} + object "s0187" {code{}} + object "s0188" {code{}} + object "s0189" {code{}} + object "s0190" {code{}} + object "s0191" {code{}} + object "s0192" {code{}} + object "s0193" {code{}} + object "s0194" {code{}} + object "s0195" {code{}} + object "s0196" {code{}} + object "s0197" {code{}} + object "s0198" {code{}} + object "s0199" {code{}} + object "s0200" {code{}} + object "s0201" {code{}} + object "s0202" {code{}} + object "s0203" {code{}} + object "s0204" {code{}} + object "s0205" {code{}} + object "s0206" {code{}} + object "s0207" {code{}} + object "s0208" {code{}} + object "s0209" {code{}} + object "s0210" {code{}} + object "s0211" {code{}} + object "s0212" {code{}} + object "s0213" {code{}} + object "s0214" {code{}} + object "s0215" {code{}} + object "s0216" {code{}} + object "s0217" {code{}} + object "s0218" {code{}} + object "s0219" {code{}} + object "s0220" {code{}} + object "s0221" {code{}} + object "s0222" {code{}} + object "s0223" {code{}} + object "s0224" {code{}} + object "s0225" {code{}} + object "s0226" {code{}} + object "s0227" {code{}} + object "s0228" {code{}} + object "s0229" {code{}} + object "s0230" {code{}} + object "s0231" {code{}} + object "s0232" {code{}} + object "s0233" {code{}} + object "s0234" {code{}} + object "s0235" {code{}} + object "s0236" {code{}} + object "s0237" {code{}} + object "s0238" {code{}} + object "s0239" {code{}} + object "s0240" {code{}} + object "s0241" {code{}} + object "s0242" {code{}} + object "s0243" {code{}} + object "s0244" {code{}} + object "s0245" {code{}} + object "s0246" {code{}} + object "s0247" {code{}} + object "s0248" {code{}} + object "s0249" {code{}} + object "s0250" {code{}} + object "s0251" {code{}} + object "s0252" {code{}} + object "s0253" {code{}} + object "s0254" {code{}} + object "s0255" {code{}} +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":78:79 */ +// 0x00 +// /* "source":50:80 */ +// dup1 +// dup1 +// dup1 +// eofcreate{0} +// /* "source":46:81 */ +// pop +// /* "source":126:127 */ +// 0x00 +// /* "source":98:128 */ +// dup1 +// dup1 +// dup1 +// eofcreate{1} +// /* "source":94:129 */ +// pop +// /* "source":174:175 */ +// 0x00 +// /* "source":146:176 */ +// dup1 +// dup1 +// dup1 +// eofcreate{2} +// /* "source":142:177 */ +// pop +// /* "source":222:223 */ +// 0x00 +// /* "source":194:224 */ +// dup1 +// dup1 +// dup1 +// eofcreate{3} +// /* "source":190:225 */ +// pop +// /* "source":270:271 */ +// 0x00 +// /* "source":242:272 */ +// dup1 +// dup1 +// dup1 +// eofcreate{4} +// /* "source":238:273 */ +// pop +// /* "source":318:319 */ +// 0x00 +// /* "source":290:320 */ +// dup1 +// dup1 +// dup1 +// eofcreate{5} +// /* "source":286:321 */ +// pop +// /* "source":366:367 */ +// 0x00 +// /* "source":338:368 */ +// dup1 +// dup1 +// dup1 +// eofcreate{6} +// /* "source":334:369 */ +// pop +// /* "source":414:415 */ +// 0x00 +// /* "source":386:416 */ +// dup1 +// dup1 +// dup1 +// eofcreate{7} +// /* "source":382:417 */ +// pop +// /* "source":462:463 */ +// 0x00 +// /* "source":434:464 */ +// dup1 +// dup1 +// dup1 +// eofcreate{8} +// /* "source":430:465 */ +// pop +// /* "source":510:511 */ +// 0x00 +// /* "source":482:512 */ +// dup1 +// dup1 +// dup1 +// eofcreate{9} +// /* "source":478:513 */ +// pop +// /* "source":558:559 */ +// 0x00 +// /* "source":530:560 */ +// dup1 +// dup1 +// dup1 +// eofcreate{10} +// /* "source":526:561 */ +// pop +// /* "source":606:607 */ +// 0x00 +// /* "source":578:608 */ +// dup1 +// dup1 +// dup1 +// eofcreate{11} +// /* "source":574:609 */ +// pop +// /* "source":654:655 */ +// 0x00 +// /* "source":626:656 */ +// dup1 +// dup1 +// dup1 +// eofcreate{12} +// /* "source":622:657 */ +// pop +// /* "source":702:703 */ +// 0x00 +// /* "source":674:704 */ +// dup1 +// dup1 +// dup1 +// eofcreate{13} +// /* "source":670:705 */ +// pop +// /* "source":750:751 */ +// 0x00 +// /* "source":722:752 */ +// dup1 +// dup1 +// dup1 +// eofcreate{14} +// /* "source":718:753 */ +// pop +// /* "source":798:799 */ +// 0x00 +// /* "source":770:800 */ +// dup1 +// dup1 +// dup1 +// eofcreate{15} +// /* "source":766:801 */ +// pop +// /* "source":846:847 */ +// 0x00 +// /* "source":818:848 */ +// dup1 +// dup1 +// dup1 +// eofcreate{16} +// /* "source":814:849 */ +// pop +// /* "source":894:895 */ +// 0x00 +// /* "source":866:896 */ +// dup1 +// dup1 +// dup1 +// eofcreate{17} +// /* "source":862:897 */ +// pop +// /* "source":942:943 */ +// 0x00 +// /* "source":914:944 */ +// dup1 +// dup1 +// dup1 +// eofcreate{18} +// /* "source":910:945 */ +// pop +// /* "source":990:991 */ +// 0x00 +// /* "source":962:992 */ +// dup1 +// dup1 +// dup1 +// eofcreate{19} +// /* "source":958:993 */ +// pop +// /* "source":1038:1039 */ +// 0x00 +// /* "source":1010:1040 */ +// dup1 +// dup1 +// dup1 +// eofcreate{20} +// /* "source":1006:1041 */ +// pop +// /* "source":1086:1087 */ +// 0x00 +// /* "source":1058:1088 */ +// dup1 +// dup1 +// dup1 +// eofcreate{21} +// /* "source":1054:1089 */ +// pop +// /* "source":1134:1135 */ +// 0x00 +// /* "source":1106:1136 */ +// dup1 +// dup1 +// dup1 +// eofcreate{22} +// /* "source":1102:1137 */ +// pop +// /* "source":1182:1183 */ +// 0x00 +// /* "source":1154:1184 */ +// dup1 +// dup1 +// dup1 +// eofcreate{23} +// /* "source":1150:1185 */ +// pop +// /* "source":1230:1231 */ +// 0x00 +// /* "source":1202:1232 */ +// dup1 +// dup1 +// dup1 +// eofcreate{24} +// /* "source":1198:1233 */ +// pop +// /* "source":1278:1279 */ +// 0x00 +// /* "source":1250:1280 */ +// dup1 +// dup1 +// dup1 +// eofcreate{25} +// /* "source":1246:1281 */ +// pop +// /* "source":1326:1327 */ +// 0x00 +// /* "source":1298:1328 */ +// dup1 +// dup1 +// dup1 +// eofcreate{26} +// /* "source":1294:1329 */ +// pop +// /* "source":1374:1375 */ +// 0x00 +// /* "source":1346:1376 */ +// dup1 +// dup1 +// dup1 +// eofcreate{27} +// /* "source":1342:1377 */ +// pop +// /* "source":1422:1423 */ +// 0x00 +// /* "source":1394:1424 */ +// dup1 +// dup1 +// dup1 +// eofcreate{28} +// /* "source":1390:1425 */ +// pop +// /* "source":1470:1471 */ +// 0x00 +// /* "source":1442:1472 */ +// dup1 +// dup1 +// dup1 +// eofcreate{29} +// /* "source":1438:1473 */ +// pop +// /* "source":1518:1519 */ +// 0x00 +// /* "source":1490:1520 */ +// dup1 +// dup1 +// dup1 +// eofcreate{30} +// /* "source":1486:1521 */ +// pop +// /* "source":1566:1567 */ +// 0x00 +// /* "source":1538:1568 */ +// dup1 +// dup1 +// dup1 +// eofcreate{31} +// /* "source":1534:1569 */ +// pop +// /* "source":1614:1615 */ +// 0x00 +// /* "source":1586:1616 */ +// dup1 +// dup1 +// dup1 +// eofcreate{32} +// /* "source":1582:1617 */ +// pop +// /* "source":1662:1663 */ +// 0x00 +// /* "source":1634:1664 */ +// dup1 +// dup1 +// dup1 +// eofcreate{33} +// /* "source":1630:1665 */ +// pop +// /* "source":1710:1711 */ +// 0x00 +// /* "source":1682:1712 */ +// dup1 +// dup1 +// dup1 +// eofcreate{34} +// /* "source":1678:1713 */ +// pop +// /* "source":1758:1759 */ +// 0x00 +// /* "source":1730:1760 */ +// dup1 +// dup1 +// dup1 +// eofcreate{35} +// /* "source":1726:1761 */ +// pop +// /* "source":1806:1807 */ +// 0x00 +// /* "source":1778:1808 */ +// dup1 +// dup1 +// dup1 +// eofcreate{36} +// /* "source":1774:1809 */ +// pop +// /* "source":1854:1855 */ +// 0x00 +// /* "source":1826:1856 */ +// dup1 +// dup1 +// dup1 +// eofcreate{37} +// /* "source":1822:1857 */ +// pop +// /* "source":1902:1903 */ +// 0x00 +// /* "source":1874:1904 */ +// dup1 +// dup1 +// dup1 +// eofcreate{38} +// /* "source":1870:1905 */ +// pop +// /* "source":1950:1951 */ +// 0x00 +// /* "source":1922:1952 */ +// dup1 +// dup1 +// dup1 +// eofcreate{39} +// /* "source":1918:1953 */ +// pop +// /* "source":1998:1999 */ +// 0x00 +// /* "source":1970:2000 */ +// dup1 +// dup1 +// dup1 +// eofcreate{40} +// /* "source":1966:2001 */ +// pop +// /* "source":2046:2047 */ +// 0x00 +// /* "source":2018:2048 */ +// dup1 +// dup1 +// dup1 +// eofcreate{41} +// /* "source":2014:2049 */ +// pop +// /* "source":2094:2095 */ +// 0x00 +// /* "source":2066:2096 */ +// dup1 +// dup1 +// dup1 +// eofcreate{42} +// /* "source":2062:2097 */ +// pop +// /* "source":2142:2143 */ +// 0x00 +// /* "source":2114:2144 */ +// dup1 +// dup1 +// dup1 +// eofcreate{43} +// /* "source":2110:2145 */ +// pop +// /* "source":2190:2191 */ +// 0x00 +// /* "source":2162:2192 */ +// dup1 +// dup1 +// dup1 +// eofcreate{44} +// /* "source":2158:2193 */ +// pop +// /* "source":2238:2239 */ +// 0x00 +// /* "source":2210:2240 */ +// dup1 +// dup1 +// dup1 +// eofcreate{45} +// /* "source":2206:2241 */ +// pop +// /* "source":2286:2287 */ +// 0x00 +// /* "source":2258:2288 */ +// dup1 +// dup1 +// dup1 +// eofcreate{46} +// /* "source":2254:2289 */ +// pop +// /* "source":2334:2335 */ +// 0x00 +// /* "source":2306:2336 */ +// dup1 +// dup1 +// dup1 +// eofcreate{47} +// /* "source":2302:2337 */ +// pop +// /* "source":2382:2383 */ +// 0x00 +// /* "source":2354:2384 */ +// dup1 +// dup1 +// dup1 +// eofcreate{48} +// /* "source":2350:2385 */ +// pop +// /* "source":2430:2431 */ +// 0x00 +// /* "source":2402:2432 */ +// dup1 +// dup1 +// dup1 +// eofcreate{49} +// /* "source":2398:2433 */ +// pop +// /* "source":2478:2479 */ +// 0x00 +// /* "source":2450:2480 */ +// dup1 +// dup1 +// dup1 +// eofcreate{50} +// /* "source":2446:2481 */ +// pop +// /* "source":2526:2527 */ +// 0x00 +// /* "source":2498:2528 */ +// dup1 +// dup1 +// dup1 +// eofcreate{51} +// /* "source":2494:2529 */ +// pop +// /* "source":2574:2575 */ +// 0x00 +// /* "source":2546:2576 */ +// dup1 +// dup1 +// dup1 +// eofcreate{52} +// /* "source":2542:2577 */ +// pop +// /* "source":2622:2623 */ +// 0x00 +// /* "source":2594:2624 */ +// dup1 +// dup1 +// dup1 +// eofcreate{53} +// /* "source":2590:2625 */ +// pop +// /* "source":2670:2671 */ +// 0x00 +// /* "source":2642:2672 */ +// dup1 +// dup1 +// dup1 +// eofcreate{54} +// /* "source":2638:2673 */ +// pop +// /* "source":2718:2719 */ +// 0x00 +// /* "source":2690:2720 */ +// dup1 +// dup1 +// dup1 +// eofcreate{55} +// /* "source":2686:2721 */ +// pop +// /* "source":2766:2767 */ +// 0x00 +// /* "source":2738:2768 */ +// dup1 +// dup1 +// dup1 +// eofcreate{56} +// /* "source":2734:2769 */ +// pop +// /* "source":2814:2815 */ +// 0x00 +// /* "source":2786:2816 */ +// dup1 +// dup1 +// dup1 +// eofcreate{57} +// /* "source":2782:2817 */ +// pop +// /* "source":2862:2863 */ +// 0x00 +// /* "source":2834:2864 */ +// dup1 +// dup1 +// dup1 +// eofcreate{58} +// /* "source":2830:2865 */ +// pop +// /* "source":2910:2911 */ +// 0x00 +// /* "source":2882:2912 */ +// dup1 +// dup1 +// dup1 +// eofcreate{59} +// /* "source":2878:2913 */ +// pop +// /* "source":2958:2959 */ +// 0x00 +// /* "source":2930:2960 */ +// dup1 +// dup1 +// dup1 +// eofcreate{60} +// /* "source":2926:2961 */ +// pop +// /* "source":3006:3007 */ +// 0x00 +// /* "source":2978:3008 */ +// dup1 +// dup1 +// dup1 +// eofcreate{61} +// /* "source":2974:3009 */ +// pop +// /* "source":3054:3055 */ +// 0x00 +// /* "source":3026:3056 */ +// dup1 +// dup1 +// dup1 +// eofcreate{62} +// /* "source":3022:3057 */ +// pop +// /* "source":3102:3103 */ +// 0x00 +// /* "source":3074:3104 */ +// dup1 +// dup1 +// dup1 +// eofcreate{63} +// /* "source":3070:3105 */ +// pop +// /* "source":3150:3151 */ +// 0x00 +// /* "source":3122:3152 */ +// dup1 +// dup1 +// dup1 +// eofcreate{64} +// /* "source":3118:3153 */ +// pop +// /* "source":3198:3199 */ +// 0x00 +// /* "source":3170:3200 */ +// dup1 +// dup1 +// dup1 +// eofcreate{65} +// /* "source":3166:3201 */ +// pop +// /* "source":3246:3247 */ +// 0x00 +// /* "source":3218:3248 */ +// dup1 +// dup1 +// dup1 +// eofcreate{66} +// /* "source":3214:3249 */ +// pop +// /* "source":3294:3295 */ +// 0x00 +// /* "source":3266:3296 */ +// dup1 +// dup1 +// dup1 +// eofcreate{67} +// /* "source":3262:3297 */ +// pop +// /* "source":3342:3343 */ +// 0x00 +// /* "source":3314:3344 */ +// dup1 +// dup1 +// dup1 +// eofcreate{68} +// /* "source":3310:3345 */ +// pop +// /* "source":3390:3391 */ +// 0x00 +// /* "source":3362:3392 */ +// dup1 +// dup1 +// dup1 +// eofcreate{69} +// /* "source":3358:3393 */ +// pop +// /* "source":3438:3439 */ +// 0x00 +// /* "source":3410:3440 */ +// dup1 +// dup1 +// dup1 +// eofcreate{70} +// /* "source":3406:3441 */ +// pop +// /* "source":3486:3487 */ +// 0x00 +// /* "source":3458:3488 */ +// dup1 +// dup1 +// dup1 +// eofcreate{71} +// /* "source":3454:3489 */ +// pop +// /* "source":3534:3535 */ +// 0x00 +// /* "source":3506:3536 */ +// dup1 +// dup1 +// dup1 +// eofcreate{72} +// /* "source":3502:3537 */ +// pop +// /* "source":3582:3583 */ +// 0x00 +// /* "source":3554:3584 */ +// dup1 +// dup1 +// dup1 +// eofcreate{73} +// /* "source":3550:3585 */ +// pop +// /* "source":3630:3631 */ +// 0x00 +// /* "source":3602:3632 */ +// dup1 +// dup1 +// dup1 +// eofcreate{74} +// /* "source":3598:3633 */ +// pop +// /* "source":3678:3679 */ +// 0x00 +// /* "source":3650:3680 */ +// dup1 +// dup1 +// dup1 +// eofcreate{75} +// /* "source":3646:3681 */ +// pop +// /* "source":3726:3727 */ +// 0x00 +// /* "source":3698:3728 */ +// dup1 +// dup1 +// dup1 +// eofcreate{76} +// /* "source":3694:3729 */ +// pop +// /* "source":3774:3775 */ +// 0x00 +// /* "source":3746:3776 */ +// dup1 +// dup1 +// dup1 +// eofcreate{77} +// /* "source":3742:3777 */ +// pop +// /* "source":3822:3823 */ +// 0x00 +// /* "source":3794:3824 */ +// dup1 +// dup1 +// dup1 +// eofcreate{78} +// /* "source":3790:3825 */ +// pop +// /* "source":3870:3871 */ +// 0x00 +// /* "source":3842:3872 */ +// dup1 +// dup1 +// dup1 +// eofcreate{79} +// /* "source":3838:3873 */ +// pop +// /* "source":3918:3919 */ +// 0x00 +// /* "source":3890:3920 */ +// dup1 +// dup1 +// dup1 +// eofcreate{80} +// /* "source":3886:3921 */ +// pop +// /* "source":3966:3967 */ +// 0x00 +// /* "source":3938:3968 */ +// dup1 +// dup1 +// dup1 +// eofcreate{81} +// /* "source":3934:3969 */ +// pop +// /* "source":4014:4015 */ +// 0x00 +// /* "source":3986:4016 */ +// dup1 +// dup1 +// dup1 +// eofcreate{82} +// /* "source":3982:4017 */ +// pop +// /* "source":4062:4063 */ +// 0x00 +// /* "source":4034:4064 */ +// dup1 +// dup1 +// dup1 +// eofcreate{83} +// /* "source":4030:4065 */ +// pop +// /* "source":4110:4111 */ +// 0x00 +// /* "source":4082:4112 */ +// dup1 +// dup1 +// dup1 +// eofcreate{84} +// /* "source":4078:4113 */ +// pop +// /* "source":4158:4159 */ +// 0x00 +// /* "source":4130:4160 */ +// dup1 +// dup1 +// dup1 +// eofcreate{85} +// /* "source":4126:4161 */ +// pop +// /* "source":4206:4207 */ +// 0x00 +// /* "source":4178:4208 */ +// dup1 +// dup1 +// dup1 +// eofcreate{86} +// /* "source":4174:4209 */ +// pop +// /* "source":4254:4255 */ +// 0x00 +// /* "source":4226:4256 */ +// dup1 +// dup1 +// dup1 +// eofcreate{87} +// /* "source":4222:4257 */ +// pop +// /* "source":4302:4303 */ +// 0x00 +// /* "source":4274:4304 */ +// dup1 +// dup1 +// dup1 +// eofcreate{88} +// /* "source":4270:4305 */ +// pop +// /* "source":4350:4351 */ +// 0x00 +// /* "source":4322:4352 */ +// dup1 +// dup1 +// dup1 +// eofcreate{89} +// /* "source":4318:4353 */ +// pop +// /* "source":4398:4399 */ +// 0x00 +// /* "source":4370:4400 */ +// dup1 +// dup1 +// dup1 +// eofcreate{90} +// /* "source":4366:4401 */ +// pop +// /* "source":4446:4447 */ +// 0x00 +// /* "source":4418:4448 */ +// dup1 +// dup1 +// dup1 +// eofcreate{91} +// /* "source":4414:4449 */ +// pop +// /* "source":4494:4495 */ +// 0x00 +// /* "source":4466:4496 */ +// dup1 +// dup1 +// dup1 +// eofcreate{92} +// /* "source":4462:4497 */ +// pop +// /* "source":4542:4543 */ +// 0x00 +// /* "source":4514:4544 */ +// dup1 +// dup1 +// dup1 +// eofcreate{93} +// /* "source":4510:4545 */ +// pop +// /* "source":4590:4591 */ +// 0x00 +// /* "source":4562:4592 */ +// dup1 +// dup1 +// dup1 +// eofcreate{94} +// /* "source":4558:4593 */ +// pop +// /* "source":4638:4639 */ +// 0x00 +// /* "source":4610:4640 */ +// dup1 +// dup1 +// dup1 +// eofcreate{95} +// /* "source":4606:4641 */ +// pop +// /* "source":4686:4687 */ +// 0x00 +// /* "source":4658:4688 */ +// dup1 +// dup1 +// dup1 +// eofcreate{96} +// /* "source":4654:4689 */ +// pop +// /* "source":4734:4735 */ +// 0x00 +// /* "source":4706:4736 */ +// dup1 +// dup1 +// dup1 +// eofcreate{97} +// /* "source":4702:4737 */ +// pop +// /* "source":4782:4783 */ +// 0x00 +// /* "source":4754:4784 */ +// dup1 +// dup1 +// dup1 +// eofcreate{98} +// /* "source":4750:4785 */ +// pop +// /* "source":4830:4831 */ +// 0x00 +// /* "source":4802:4832 */ +// dup1 +// dup1 +// dup1 +// eofcreate{99} +// /* "source":4798:4833 */ +// pop +// /* "source":4878:4879 */ +// 0x00 +// /* "source":4850:4880 */ +// dup1 +// dup1 +// dup1 +// eofcreate{100} +// /* "source":4846:4881 */ +// pop +// /* "source":4926:4927 */ +// 0x00 +// /* "source":4898:4928 */ +// dup1 +// dup1 +// dup1 +// eofcreate{101} +// /* "source":4894:4929 */ +// pop +// /* "source":4974:4975 */ +// 0x00 +// /* "source":4946:4976 */ +// dup1 +// dup1 +// dup1 +// eofcreate{102} +// /* "source":4942:4977 */ +// pop +// /* "source":5022:5023 */ +// 0x00 +// /* "source":4994:5024 */ +// dup1 +// dup1 +// dup1 +// eofcreate{103} +// /* "source":4990:5025 */ +// pop +// /* "source":5070:5071 */ +// 0x00 +// /* "source":5042:5072 */ +// dup1 +// dup1 +// dup1 +// eofcreate{104} +// /* "source":5038:5073 */ +// pop +// /* "source":5118:5119 */ +// 0x00 +// /* "source":5090:5120 */ +// dup1 +// dup1 +// dup1 +// eofcreate{105} +// /* "source":5086:5121 */ +// pop +// /* "source":5166:5167 */ +// 0x00 +// /* "source":5138:5168 */ +// dup1 +// dup1 +// dup1 +// eofcreate{106} +// /* "source":5134:5169 */ +// pop +// /* "source":5214:5215 */ +// 0x00 +// /* "source":5186:5216 */ +// dup1 +// dup1 +// dup1 +// eofcreate{107} +// /* "source":5182:5217 */ +// pop +// /* "source":5262:5263 */ +// 0x00 +// /* "source":5234:5264 */ +// dup1 +// dup1 +// dup1 +// eofcreate{108} +// /* "source":5230:5265 */ +// pop +// /* "source":5310:5311 */ +// 0x00 +// /* "source":5282:5312 */ +// dup1 +// dup1 +// dup1 +// eofcreate{109} +// /* "source":5278:5313 */ +// pop +// /* "source":5358:5359 */ +// 0x00 +// /* "source":5330:5360 */ +// dup1 +// dup1 +// dup1 +// eofcreate{110} +// /* "source":5326:5361 */ +// pop +// /* "source":5406:5407 */ +// 0x00 +// /* "source":5378:5408 */ +// dup1 +// dup1 +// dup1 +// eofcreate{111} +// /* "source":5374:5409 */ +// pop +// /* "source":5454:5455 */ +// 0x00 +// /* "source":5426:5456 */ +// dup1 +// dup1 +// dup1 +// eofcreate{112} +// /* "source":5422:5457 */ +// pop +// /* "source":5502:5503 */ +// 0x00 +// /* "source":5474:5504 */ +// dup1 +// dup1 +// dup1 +// eofcreate{113} +// /* "source":5470:5505 */ +// pop +// /* "source":5550:5551 */ +// 0x00 +// /* "source":5522:5552 */ +// dup1 +// dup1 +// dup1 +// eofcreate{114} +// /* "source":5518:5553 */ +// pop +// /* "source":5598:5599 */ +// 0x00 +// /* "source":5570:5600 */ +// dup1 +// dup1 +// dup1 +// eofcreate{115} +// /* "source":5566:5601 */ +// pop +// /* "source":5646:5647 */ +// 0x00 +// /* "source":5618:5648 */ +// dup1 +// dup1 +// dup1 +// eofcreate{116} +// /* "source":5614:5649 */ +// pop +// /* "source":5694:5695 */ +// 0x00 +// /* "source":5666:5696 */ +// dup1 +// dup1 +// dup1 +// eofcreate{117} +// /* "source":5662:5697 */ +// pop +// /* "source":5742:5743 */ +// 0x00 +// /* "source":5714:5744 */ +// dup1 +// dup1 +// dup1 +// eofcreate{118} +// /* "source":5710:5745 */ +// pop +// /* "source":5790:5791 */ +// 0x00 +// /* "source":5762:5792 */ +// dup1 +// dup1 +// dup1 +// eofcreate{119} +// /* "source":5758:5793 */ +// pop +// /* "source":5838:5839 */ +// 0x00 +// /* "source":5810:5840 */ +// dup1 +// dup1 +// dup1 +// eofcreate{120} +// /* "source":5806:5841 */ +// pop +// /* "source":5886:5887 */ +// 0x00 +// /* "source":5858:5888 */ +// dup1 +// dup1 +// dup1 +// eofcreate{121} +// /* "source":5854:5889 */ +// pop +// /* "source":5934:5935 */ +// 0x00 +// /* "source":5906:5936 */ +// dup1 +// dup1 +// dup1 +// eofcreate{122} +// /* "source":5902:5937 */ +// pop +// /* "source":5982:5983 */ +// 0x00 +// /* "source":5954:5984 */ +// dup1 +// dup1 +// dup1 +// eofcreate{123} +// /* "source":5950:5985 */ +// pop +// /* "source":6030:6031 */ +// 0x00 +// /* "source":6002:6032 */ +// dup1 +// dup1 +// dup1 +// eofcreate{124} +// /* "source":5998:6033 */ +// pop +// /* "source":6078:6079 */ +// 0x00 +// /* "source":6050:6080 */ +// dup1 +// dup1 +// dup1 +// eofcreate{125} +// /* "source":6046:6081 */ +// pop +// /* "source":6126:6127 */ +// 0x00 +// /* "source":6098:6128 */ +// dup1 +// dup1 +// dup1 +// eofcreate{126} +// /* "source":6094:6129 */ +// pop +// /* "source":6174:6175 */ +// 0x00 +// /* "source":6146:6176 */ +// dup1 +// dup1 +// dup1 +// eofcreate{127} +// /* "source":6142:6177 */ +// pop +// /* "source":6222:6223 */ +// 0x00 +// /* "source":6194:6224 */ +// dup1 +// dup1 +// dup1 +// eofcreate{128} +// /* "source":6190:6225 */ +// pop +// /* "source":6270:6271 */ +// 0x00 +// /* "source":6242:6272 */ +// dup1 +// dup1 +// dup1 +// eofcreate{129} +// /* "source":6238:6273 */ +// pop +// /* "source":6318:6319 */ +// 0x00 +// /* "source":6290:6320 */ +// dup1 +// dup1 +// dup1 +// eofcreate{130} +// /* "source":6286:6321 */ +// pop +// /* "source":6366:6367 */ +// 0x00 +// /* "source":6338:6368 */ +// dup1 +// dup1 +// dup1 +// eofcreate{131} +// /* "source":6334:6369 */ +// pop +// /* "source":6414:6415 */ +// 0x00 +// /* "source":6386:6416 */ +// dup1 +// dup1 +// dup1 +// eofcreate{132} +// /* "source":6382:6417 */ +// pop +// /* "source":6462:6463 */ +// 0x00 +// /* "source":6434:6464 */ +// dup1 +// dup1 +// dup1 +// eofcreate{133} +// /* "source":6430:6465 */ +// pop +// /* "source":6510:6511 */ +// 0x00 +// /* "source":6482:6512 */ +// dup1 +// dup1 +// dup1 +// eofcreate{134} +// /* "source":6478:6513 */ +// pop +// /* "source":6558:6559 */ +// 0x00 +// /* "source":6530:6560 */ +// dup1 +// dup1 +// dup1 +// eofcreate{135} +// /* "source":6526:6561 */ +// pop +// /* "source":6606:6607 */ +// 0x00 +// /* "source":6578:6608 */ +// dup1 +// dup1 +// dup1 +// eofcreate{136} +// /* "source":6574:6609 */ +// pop +// /* "source":6654:6655 */ +// 0x00 +// /* "source":6626:6656 */ +// dup1 +// dup1 +// dup1 +// eofcreate{137} +// /* "source":6622:6657 */ +// pop +// /* "source":6702:6703 */ +// 0x00 +// /* "source":6674:6704 */ +// dup1 +// dup1 +// dup1 +// eofcreate{138} +// /* "source":6670:6705 */ +// pop +// /* "source":6750:6751 */ +// 0x00 +// /* "source":6722:6752 */ +// dup1 +// dup1 +// dup1 +// eofcreate{139} +// /* "source":6718:6753 */ +// pop +// /* "source":6798:6799 */ +// 0x00 +// /* "source":6770:6800 */ +// dup1 +// dup1 +// dup1 +// eofcreate{140} +// /* "source":6766:6801 */ +// pop +// /* "source":6846:6847 */ +// 0x00 +// /* "source":6818:6848 */ +// dup1 +// dup1 +// dup1 +// eofcreate{141} +// /* "source":6814:6849 */ +// pop +// /* "source":6894:6895 */ +// 0x00 +// /* "source":6866:6896 */ +// dup1 +// dup1 +// dup1 +// eofcreate{142} +// /* "source":6862:6897 */ +// pop +// /* "source":6942:6943 */ +// 0x00 +// /* "source":6914:6944 */ +// dup1 +// dup1 +// dup1 +// eofcreate{143} +// /* "source":6910:6945 */ +// pop +// /* "source":6990:6991 */ +// 0x00 +// /* "source":6962:6992 */ +// dup1 +// dup1 +// dup1 +// eofcreate{144} +// /* "source":6958:6993 */ +// pop +// /* "source":7038:7039 */ +// 0x00 +// /* "source":7010:7040 */ +// dup1 +// dup1 +// dup1 +// eofcreate{145} +// /* "source":7006:7041 */ +// pop +// /* "source":7086:7087 */ +// 0x00 +// /* "source":7058:7088 */ +// dup1 +// dup1 +// dup1 +// eofcreate{146} +// /* "source":7054:7089 */ +// pop +// /* "source":7134:7135 */ +// 0x00 +// /* "source":7106:7136 */ +// dup1 +// dup1 +// dup1 +// eofcreate{147} +// /* "source":7102:7137 */ +// pop +// /* "source":7182:7183 */ +// 0x00 +// /* "source":7154:7184 */ +// dup1 +// dup1 +// dup1 +// eofcreate{148} +// /* "source":7150:7185 */ +// pop +// /* "source":7230:7231 */ +// 0x00 +// /* "source":7202:7232 */ +// dup1 +// dup1 +// dup1 +// eofcreate{149} +// /* "source":7198:7233 */ +// pop +// /* "source":7278:7279 */ +// 0x00 +// /* "source":7250:7280 */ +// dup1 +// dup1 +// dup1 +// eofcreate{150} +// /* "source":7246:7281 */ +// pop +// /* "source":7326:7327 */ +// 0x00 +// /* "source":7298:7328 */ +// dup1 +// dup1 +// dup1 +// eofcreate{151} +// /* "source":7294:7329 */ +// pop +// /* "source":7374:7375 */ +// 0x00 +// /* "source":7346:7376 */ +// dup1 +// dup1 +// dup1 +// eofcreate{152} +// /* "source":7342:7377 */ +// pop +// /* "source":7422:7423 */ +// 0x00 +// /* "source":7394:7424 */ +// dup1 +// dup1 +// dup1 +// eofcreate{153} +// /* "source":7390:7425 */ +// pop +// /* "source":7470:7471 */ +// 0x00 +// /* "source":7442:7472 */ +// dup1 +// dup1 +// dup1 +// eofcreate{154} +// /* "source":7438:7473 */ +// pop +// /* "source":7518:7519 */ +// 0x00 +// /* "source":7490:7520 */ +// dup1 +// dup1 +// dup1 +// eofcreate{155} +// /* "source":7486:7521 */ +// pop +// /* "source":7566:7567 */ +// 0x00 +// /* "source":7538:7568 */ +// dup1 +// dup1 +// dup1 +// eofcreate{156} +// /* "source":7534:7569 */ +// pop +// /* "source":7614:7615 */ +// 0x00 +// /* "source":7586:7616 */ +// dup1 +// dup1 +// dup1 +// eofcreate{157} +// /* "source":7582:7617 */ +// pop +// /* "source":7662:7663 */ +// 0x00 +// /* "source":7634:7664 */ +// dup1 +// dup1 +// dup1 +// eofcreate{158} +// /* "source":7630:7665 */ +// pop +// /* "source":7710:7711 */ +// 0x00 +// /* "source":7682:7712 */ +// dup1 +// dup1 +// dup1 +// eofcreate{159} +// /* "source":7678:7713 */ +// pop +// /* "source":7758:7759 */ +// 0x00 +// /* "source":7730:7760 */ +// dup1 +// dup1 +// dup1 +// eofcreate{160} +// /* "source":7726:7761 */ +// pop +// /* "source":7806:7807 */ +// 0x00 +// /* "source":7778:7808 */ +// dup1 +// dup1 +// dup1 +// eofcreate{161} +// /* "source":7774:7809 */ +// pop +// /* "source":7854:7855 */ +// 0x00 +// /* "source":7826:7856 */ +// dup1 +// dup1 +// dup1 +// eofcreate{162} +// /* "source":7822:7857 */ +// pop +// /* "source":7902:7903 */ +// 0x00 +// /* "source":7874:7904 */ +// dup1 +// dup1 +// dup1 +// eofcreate{163} +// /* "source":7870:7905 */ +// pop +// /* "source":7950:7951 */ +// 0x00 +// /* "source":7922:7952 */ +// dup1 +// dup1 +// dup1 +// eofcreate{164} +// /* "source":7918:7953 */ +// pop +// /* "source":7998:7999 */ +// 0x00 +// /* "source":7970:8000 */ +// dup1 +// dup1 +// dup1 +// eofcreate{165} +// /* "source":7966:8001 */ +// pop +// /* "source":8046:8047 */ +// 0x00 +// /* "source":8018:8048 */ +// dup1 +// dup1 +// dup1 +// eofcreate{166} +// /* "source":8014:8049 */ +// pop +// /* "source":8094:8095 */ +// 0x00 +// /* "source":8066:8096 */ +// dup1 +// dup1 +// dup1 +// eofcreate{167} +// /* "source":8062:8097 */ +// pop +// /* "source":8142:8143 */ +// 0x00 +// /* "source":8114:8144 */ +// dup1 +// dup1 +// dup1 +// eofcreate{168} +// /* "source":8110:8145 */ +// pop +// /* "source":8190:8191 */ +// 0x00 +// /* "source":8162:8192 */ +// dup1 +// dup1 +// dup1 +// eofcreate{169} +// /* "source":8158:8193 */ +// pop +// /* "source":8238:8239 */ +// 0x00 +// /* "source":8210:8240 */ +// dup1 +// dup1 +// dup1 +// eofcreate{170} +// /* "source":8206:8241 */ +// pop +// /* "source":8286:8287 */ +// 0x00 +// /* "source":8258:8288 */ +// dup1 +// dup1 +// dup1 +// eofcreate{171} +// /* "source":8254:8289 */ +// pop +// /* "source":8334:8335 */ +// 0x00 +// /* "source":8306:8336 */ +// dup1 +// dup1 +// dup1 +// eofcreate{172} +// /* "source":8302:8337 */ +// pop +// /* "source":8382:8383 */ +// 0x00 +// /* "source":8354:8384 */ +// dup1 +// dup1 +// dup1 +// eofcreate{173} +// /* "source":8350:8385 */ +// pop +// /* "source":8430:8431 */ +// 0x00 +// /* "source":8402:8432 */ +// dup1 +// dup1 +// dup1 +// eofcreate{174} +// /* "source":8398:8433 */ +// pop +// /* "source":8478:8479 */ +// 0x00 +// /* "source":8450:8480 */ +// dup1 +// dup1 +// dup1 +// eofcreate{175} +// /* "source":8446:8481 */ +// pop +// /* "source":8526:8527 */ +// 0x00 +// /* "source":8498:8528 */ +// dup1 +// dup1 +// dup1 +// eofcreate{176} +// /* "source":8494:8529 */ +// pop +// /* "source":8574:8575 */ +// 0x00 +// /* "source":8546:8576 */ +// dup1 +// dup1 +// dup1 +// eofcreate{177} +// /* "source":8542:8577 */ +// pop +// /* "source":8622:8623 */ +// 0x00 +// /* "source":8594:8624 */ +// dup1 +// dup1 +// dup1 +// eofcreate{178} +// /* "source":8590:8625 */ +// pop +// /* "source":8670:8671 */ +// 0x00 +// /* "source":8642:8672 */ +// dup1 +// dup1 +// dup1 +// eofcreate{179} +// /* "source":8638:8673 */ +// pop +// /* "source":8718:8719 */ +// 0x00 +// /* "source":8690:8720 */ +// dup1 +// dup1 +// dup1 +// eofcreate{180} +// /* "source":8686:8721 */ +// pop +// /* "source":8766:8767 */ +// 0x00 +// /* "source":8738:8768 */ +// dup1 +// dup1 +// dup1 +// eofcreate{181} +// /* "source":8734:8769 */ +// pop +// /* "source":8814:8815 */ +// 0x00 +// /* "source":8786:8816 */ +// dup1 +// dup1 +// dup1 +// eofcreate{182} +// /* "source":8782:8817 */ +// pop +// /* "source":8862:8863 */ +// 0x00 +// /* "source":8834:8864 */ +// dup1 +// dup1 +// dup1 +// eofcreate{183} +// /* "source":8830:8865 */ +// pop +// /* "source":8910:8911 */ +// 0x00 +// /* "source":8882:8912 */ +// dup1 +// dup1 +// dup1 +// eofcreate{184} +// /* "source":8878:8913 */ +// pop +// /* "source":8958:8959 */ +// 0x00 +// /* "source":8930:8960 */ +// dup1 +// dup1 +// dup1 +// eofcreate{185} +// /* "source":8926:8961 */ +// pop +// /* "source":9006:9007 */ +// 0x00 +// /* "source":8978:9008 */ +// dup1 +// dup1 +// dup1 +// eofcreate{186} +// /* "source":8974:9009 */ +// pop +// /* "source":9054:9055 */ +// 0x00 +// /* "source":9026:9056 */ +// dup1 +// dup1 +// dup1 +// eofcreate{187} +// /* "source":9022:9057 */ +// pop +// /* "source":9102:9103 */ +// 0x00 +// /* "source":9074:9104 */ +// dup1 +// dup1 +// dup1 +// eofcreate{188} +// /* "source":9070:9105 */ +// pop +// /* "source":9150:9151 */ +// 0x00 +// /* "source":9122:9152 */ +// dup1 +// dup1 +// dup1 +// eofcreate{189} +// /* "source":9118:9153 */ +// pop +// /* "source":9198:9199 */ +// 0x00 +// /* "source":9170:9200 */ +// dup1 +// dup1 +// dup1 +// eofcreate{190} +// /* "source":9166:9201 */ +// pop +// /* "source":9246:9247 */ +// 0x00 +// /* "source":9218:9248 */ +// dup1 +// dup1 +// dup1 +// eofcreate{191} +// /* "source":9214:9249 */ +// pop +// /* "source":9294:9295 */ +// 0x00 +// /* "source":9266:9296 */ +// dup1 +// dup1 +// dup1 +// eofcreate{192} +// /* "source":9262:9297 */ +// pop +// /* "source":9342:9343 */ +// 0x00 +// /* "source":9314:9344 */ +// dup1 +// dup1 +// dup1 +// eofcreate{193} +// /* "source":9310:9345 */ +// pop +// /* "source":9390:9391 */ +// 0x00 +// /* "source":9362:9392 */ +// dup1 +// dup1 +// dup1 +// eofcreate{194} +// /* "source":9358:9393 */ +// pop +// /* "source":9438:9439 */ +// 0x00 +// /* "source":9410:9440 */ +// dup1 +// dup1 +// dup1 +// eofcreate{195} +// /* "source":9406:9441 */ +// pop +// /* "source":9486:9487 */ +// 0x00 +// /* "source":9458:9488 */ +// dup1 +// dup1 +// dup1 +// eofcreate{196} +// /* "source":9454:9489 */ +// pop +// /* "source":9534:9535 */ +// 0x00 +// /* "source":9506:9536 */ +// dup1 +// dup1 +// dup1 +// eofcreate{197} +// /* "source":9502:9537 */ +// pop +// /* "source":9582:9583 */ +// 0x00 +// /* "source":9554:9584 */ +// dup1 +// dup1 +// dup1 +// eofcreate{198} +// /* "source":9550:9585 */ +// pop +// /* "source":9630:9631 */ +// 0x00 +// /* "source":9602:9632 */ +// dup1 +// dup1 +// dup1 +// eofcreate{199} +// /* "source":9598:9633 */ +// pop +// /* "source":9678:9679 */ +// 0x00 +// /* "source":9650:9680 */ +// dup1 +// dup1 +// dup1 +// eofcreate{200} +// /* "source":9646:9681 */ +// pop +// /* "source":9726:9727 */ +// 0x00 +// /* "source":9698:9728 */ +// dup1 +// dup1 +// dup1 +// eofcreate{201} +// /* "source":9694:9729 */ +// pop +// /* "source":9774:9775 */ +// 0x00 +// /* "source":9746:9776 */ +// dup1 +// dup1 +// dup1 +// eofcreate{202} +// /* "source":9742:9777 */ +// pop +// /* "source":9822:9823 */ +// 0x00 +// /* "source":9794:9824 */ +// dup1 +// dup1 +// dup1 +// eofcreate{203} +// /* "source":9790:9825 */ +// pop +// /* "source":9870:9871 */ +// 0x00 +// /* "source":9842:9872 */ +// dup1 +// dup1 +// dup1 +// eofcreate{204} +// /* "source":9838:9873 */ +// pop +// /* "source":9918:9919 */ +// 0x00 +// /* "source":9890:9920 */ +// dup1 +// dup1 +// dup1 +// eofcreate{205} +// /* "source":9886:9921 */ +// pop +// /* "source":9966:9967 */ +// 0x00 +// /* "source":9938:9968 */ +// dup1 +// dup1 +// dup1 +// eofcreate{206} +// /* "source":9934:9969 */ +// pop +// /* "source":10014:10015 */ +// 0x00 +// /* "source":9986:10016 */ +// dup1 +// dup1 +// dup1 +// eofcreate{207} +// /* "source":9982:10017 */ +// pop +// /* "source":10062:10063 */ +// 0x00 +// /* "source":10034:10064 */ +// dup1 +// dup1 +// dup1 +// eofcreate{208} +// /* "source":10030:10065 */ +// pop +// /* "source":10110:10111 */ +// 0x00 +// /* "source":10082:10112 */ +// dup1 +// dup1 +// dup1 +// eofcreate{209} +// /* "source":10078:10113 */ +// pop +// /* "source":10158:10159 */ +// 0x00 +// /* "source":10130:10160 */ +// dup1 +// dup1 +// dup1 +// eofcreate{210} +// /* "source":10126:10161 */ +// pop +// /* "source":10206:10207 */ +// 0x00 +// /* "source":10178:10208 */ +// dup1 +// dup1 +// dup1 +// eofcreate{211} +// /* "source":10174:10209 */ +// pop +// /* "source":10254:10255 */ +// 0x00 +// /* "source":10226:10256 */ +// dup1 +// dup1 +// dup1 +// eofcreate{212} +// /* "source":10222:10257 */ +// pop +// /* "source":10302:10303 */ +// 0x00 +// /* "source":10274:10304 */ +// dup1 +// dup1 +// dup1 +// eofcreate{213} +// /* "source":10270:10305 */ +// pop +// /* "source":10350:10351 */ +// 0x00 +// /* "source":10322:10352 */ +// dup1 +// dup1 +// dup1 +// eofcreate{214} +// /* "source":10318:10353 */ +// pop +// /* "source":10398:10399 */ +// 0x00 +// /* "source":10370:10400 */ +// dup1 +// dup1 +// dup1 +// eofcreate{215} +// /* "source":10366:10401 */ +// pop +// /* "source":10446:10447 */ +// 0x00 +// /* "source":10418:10448 */ +// dup1 +// dup1 +// dup1 +// eofcreate{216} +// /* "source":10414:10449 */ +// pop +// /* "source":10494:10495 */ +// 0x00 +// /* "source":10466:10496 */ +// dup1 +// dup1 +// dup1 +// eofcreate{217} +// /* "source":10462:10497 */ +// pop +// /* "source":10542:10543 */ +// 0x00 +// /* "source":10514:10544 */ +// dup1 +// dup1 +// dup1 +// eofcreate{218} +// /* "source":10510:10545 */ +// pop +// /* "source":10590:10591 */ +// 0x00 +// /* "source":10562:10592 */ +// dup1 +// dup1 +// dup1 +// eofcreate{219} +// /* "source":10558:10593 */ +// pop +// /* "source":10638:10639 */ +// 0x00 +// /* "source":10610:10640 */ +// dup1 +// dup1 +// dup1 +// eofcreate{220} +// /* "source":10606:10641 */ +// pop +// /* "source":10686:10687 */ +// 0x00 +// /* "source":10658:10688 */ +// dup1 +// dup1 +// dup1 +// eofcreate{221} +// /* "source":10654:10689 */ +// pop +// /* "source":10734:10735 */ +// 0x00 +// /* "source":10706:10736 */ +// dup1 +// dup1 +// dup1 +// eofcreate{222} +// /* "source":10702:10737 */ +// pop +// /* "source":10782:10783 */ +// 0x00 +// /* "source":10754:10784 */ +// dup1 +// dup1 +// dup1 +// eofcreate{223} +// /* "source":10750:10785 */ +// pop +// /* "source":10830:10831 */ +// 0x00 +// /* "source":10802:10832 */ +// dup1 +// dup1 +// dup1 +// eofcreate{224} +// /* "source":10798:10833 */ +// pop +// /* "source":10878:10879 */ +// 0x00 +// /* "source":10850:10880 */ +// dup1 +// dup1 +// dup1 +// eofcreate{225} +// /* "source":10846:10881 */ +// pop +// /* "source":10926:10927 */ +// 0x00 +// /* "source":10898:10928 */ +// dup1 +// dup1 +// dup1 +// eofcreate{226} +// /* "source":10894:10929 */ +// pop +// /* "source":10974:10975 */ +// 0x00 +// /* "source":10946:10976 */ +// dup1 +// dup1 +// dup1 +// eofcreate{227} +// /* "source":10942:10977 */ +// pop +// /* "source":11022:11023 */ +// 0x00 +// /* "source":10994:11024 */ +// dup1 +// dup1 +// dup1 +// eofcreate{228} +// /* "source":10990:11025 */ +// pop +// /* "source":11070:11071 */ +// 0x00 +// /* "source":11042:11072 */ +// dup1 +// dup1 +// dup1 +// eofcreate{229} +// /* "source":11038:11073 */ +// pop +// /* "source":11118:11119 */ +// 0x00 +// /* "source":11090:11120 */ +// dup1 +// dup1 +// dup1 +// eofcreate{230} +// /* "source":11086:11121 */ +// pop +// /* "source":11166:11167 */ +// 0x00 +// /* "source":11138:11168 */ +// dup1 +// dup1 +// dup1 +// eofcreate{231} +// /* "source":11134:11169 */ +// pop +// /* "source":11214:11215 */ +// 0x00 +// /* "source":11186:11216 */ +// dup1 +// dup1 +// dup1 +// eofcreate{232} +// /* "source":11182:11217 */ +// pop +// /* "source":11262:11263 */ +// 0x00 +// /* "source":11234:11264 */ +// dup1 +// dup1 +// dup1 +// eofcreate{233} +// /* "source":11230:11265 */ +// pop +// /* "source":11310:11311 */ +// 0x00 +// /* "source":11282:11312 */ +// dup1 +// dup1 +// dup1 +// eofcreate{234} +// /* "source":11278:11313 */ +// pop +// /* "source":11358:11359 */ +// 0x00 +// /* "source":11330:11360 */ +// dup1 +// dup1 +// dup1 +// eofcreate{235} +// /* "source":11326:11361 */ +// pop +// /* "source":11406:11407 */ +// 0x00 +// /* "source":11378:11408 */ +// dup1 +// dup1 +// dup1 +// eofcreate{236} +// /* "source":11374:11409 */ +// pop +// /* "source":11454:11455 */ +// 0x00 +// /* "source":11426:11456 */ +// dup1 +// dup1 +// dup1 +// eofcreate{237} +// /* "source":11422:11457 */ +// pop +// /* "source":11502:11503 */ +// 0x00 +// /* "source":11474:11504 */ +// dup1 +// dup1 +// dup1 +// eofcreate{238} +// /* "source":11470:11505 */ +// pop +// /* "source":11550:11551 */ +// 0x00 +// /* "source":11522:11552 */ +// dup1 +// dup1 +// dup1 +// eofcreate{239} +// /* "source":11518:11553 */ +// pop +// /* "source":11598:11599 */ +// 0x00 +// /* "source":11570:11600 */ +// dup1 +// dup1 +// dup1 +// eofcreate{240} +// /* "source":11566:11601 */ +// pop +// /* "source":11646:11647 */ +// 0x00 +// /* "source":11618:11648 */ +// dup1 +// dup1 +// dup1 +// eofcreate{241} +// /* "source":11614:11649 */ +// pop +// /* "source":11694:11695 */ +// 0x00 +// /* "source":11666:11696 */ +// dup1 +// dup1 +// dup1 +// eofcreate{242} +// /* "source":11662:11697 */ +// pop +// /* "source":11742:11743 */ +// 0x00 +// /* "source":11714:11744 */ +// dup1 +// dup1 +// dup1 +// eofcreate{243} +// /* "source":11710:11745 */ +// pop +// /* "source":11790:11791 */ +// 0x00 +// /* "source":11762:11792 */ +// dup1 +// dup1 +// dup1 +// eofcreate{244} +// /* "source":11758:11793 */ +// pop +// /* "source":11838:11839 */ +// 0x00 +// /* "source":11810:11840 */ +// dup1 +// dup1 +// dup1 +// eofcreate{245} +// /* "source":11806:11841 */ +// pop +// /* "source":11886:11887 */ +// 0x00 +// /* "source":11858:11888 */ +// dup1 +// dup1 +// dup1 +// eofcreate{246} +// /* "source":11854:11889 */ +// pop +// /* "source":11934:11935 */ +// 0x00 +// /* "source":11906:11936 */ +// dup1 +// dup1 +// dup1 +// eofcreate{247} +// /* "source":11902:11937 */ +// pop +// /* "source":11982:11983 */ +// 0x00 +// /* "source":11954:11984 */ +// dup1 +// dup1 +// dup1 +// eofcreate{248} +// /* "source":11950:11985 */ +// pop +// /* "source":12030:12031 */ +// 0x00 +// /* "source":12002:12032 */ +// dup1 +// dup1 +// dup1 +// eofcreate{249} +// /* "source":11998:12033 */ +// pop +// /* "source":12078:12079 */ +// 0x00 +// /* "source":12050:12080 */ +// dup1 +// dup1 +// dup1 +// eofcreate{250} +// /* "source":12046:12081 */ +// pop +// /* "source":12126:12127 */ +// 0x00 +// /* "source":12098:12128 */ +// dup1 +// dup1 +// dup1 +// eofcreate{251} +// /* "source":12094:12129 */ +// pop +// /* "source":12174:12175 */ +// 0x00 +// /* "source":12146:12176 */ +// dup1 +// dup1 +// dup1 +// eofcreate{252} +// /* "source":12142:12177 */ +// pop +// /* "source":12222:12223 */ +// 0x00 +// /* "source":12194:12224 */ +// dup1 +// dup1 +// dup1 +// eofcreate{253} +// /* "source":12190:12225 */ +// pop +// /* "source":12270:12271 */ +// 0x00 +// /* "source":12242:12272 */ +// dup1 +// dup1 +// dup1 +// eofcreate{254} +// /* "source":12238:12273 */ +// pop +// /* "source":12318:12319 */ +// 0x00 +// /* "source":12290:12320 */ +// dup1 +// dup1 +// dup1 +// eofcreate{255} +// /* "source":12286:12321 */ +// pop +// /* "source":22:12337 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":12372:12379 */ +// stop +// } +// +// sub_1: assembly { +// /* "source":12420:12427 */ +// stop +// } +// +// sub_2: assembly { +// /* "source":12468:12475 */ +// stop +// } +// +// sub_3: assembly { +// /* "source":12516:12523 */ +// stop +// } +// +// sub_4: assembly { +// /* "source":12564:12571 */ +// stop +// } +// +// sub_5: assembly { +// /* "source":12612:12619 */ +// stop +// } +// +// sub_6: assembly { +// /* "source":12660:12667 */ +// stop +// } +// +// sub_7: assembly { +// /* "source":12708:12715 */ +// stop +// } +// +// sub_8: assembly { +// /* "source":12756:12763 */ +// stop +// } +// +// sub_9: assembly { +// /* "source":12804:12811 */ +// stop +// } +// +// sub_10: assembly { +// /* "source":12852:12859 */ +// stop +// } +// +// sub_11: assembly { +// /* "source":12900:12907 */ +// stop +// } +// +// sub_12: assembly { +// /* "source":12948:12955 */ +// stop +// } +// +// sub_13: assembly { +// /* "source":12996:13003 */ +// stop +// } +// +// sub_14: assembly { +// /* "source":13044:13051 */ +// stop +// } +// +// sub_15: assembly { +// /* "source":13092:13099 */ +// stop +// } +// +// sub_16: assembly { +// /* "source":13140:13147 */ +// stop +// } +// +// sub_17: assembly { +// /* "source":13188:13195 */ +// stop +// } +// +// sub_18: assembly { +// /* "source":13236:13243 */ +// stop +// } +// +// sub_19: assembly { +// /* "source":13284:13291 */ +// stop +// } +// +// sub_20: assembly { +// /* "source":13332:13339 */ +// stop +// } +// +// sub_21: assembly { +// /* "source":13380:13387 */ +// stop +// } +// +// sub_22: assembly { +// /* "source":13428:13435 */ +// stop +// } +// +// sub_23: assembly { +// /* "source":13476:13483 */ +// stop +// } +// +// sub_24: assembly { +// /* "source":13524:13531 */ +// stop +// } +// +// sub_25: assembly { +// /* "source":13572:13579 */ +// stop +// } +// +// sub_26: assembly { +// /* "source":13620:13627 */ +// stop +// } +// +// sub_27: assembly { +// /* "source":13668:13675 */ +// stop +// } +// +// sub_28: assembly { +// /* "source":13716:13723 */ +// stop +// } +// +// sub_29: assembly { +// /* "source":13764:13771 */ +// stop +// } +// +// sub_30: assembly { +// /* "source":13812:13819 */ +// stop +// } +// +// sub_31: assembly { +// /* "source":13860:13867 */ +// stop +// } +// +// sub_32: assembly { +// /* "source":13908:13915 */ +// stop +// } +// +// sub_33: assembly { +// /* "source":13956:13963 */ +// stop +// } +// +// sub_34: assembly { +// /* "source":14004:14011 */ +// stop +// } +// +// sub_35: assembly { +// /* "source":14052:14059 */ +// stop +// } +// +// sub_36: assembly { +// /* "source":14100:14107 */ +// stop +// } +// +// sub_37: assembly { +// /* "source":14148:14155 */ +// stop +// } +// +// sub_38: assembly { +// /* "source":14196:14203 */ +// stop +// } +// +// sub_39: assembly { +// /* "source":14244:14251 */ +// stop +// } +// +// sub_40: assembly { +// /* "source":14292:14299 */ +// stop +// } +// +// sub_41: assembly { +// /* "source":14340:14347 */ +// stop +// } +// +// sub_42: assembly { +// /* "source":14388:14395 */ +// stop +// } +// +// sub_43: assembly { +// /* "source":14436:14443 */ +// stop +// } +// +// sub_44: assembly { +// /* "source":14484:14491 */ +// stop +// } +// +// sub_45: assembly { +// /* "source":14532:14539 */ +// stop +// } +// +// sub_46: assembly { +// /* "source":14580:14587 */ +// stop +// } +// +// sub_47: assembly { +// /* "source":14628:14635 */ +// stop +// } +// +// sub_48: assembly { +// /* "source":14676:14683 */ +// stop +// } +// +// sub_49: assembly { +// /* "source":14724:14731 */ +// stop +// } +// +// sub_50: assembly { +// /* "source":14772:14779 */ +// stop +// } +// +// sub_51: assembly { +// /* "source":14820:14827 */ +// stop +// } +// +// sub_52: assembly { +// /* "source":14868:14875 */ +// stop +// } +// +// sub_53: assembly { +// /* "source":14916:14923 */ +// stop +// } +// +// sub_54: assembly { +// /* "source":14964:14971 */ +// stop +// } +// +// sub_55: assembly { +// /* "source":15012:15019 */ +// stop +// } +// +// sub_56: assembly { +// /* "source":15060:15067 */ +// stop +// } +// +// sub_57: assembly { +// /* "source":15108:15115 */ +// stop +// } +// +// sub_58: assembly { +// /* "source":15156:15163 */ +// stop +// } +// +// sub_59: assembly { +// /* "source":15204:15211 */ +// stop +// } +// +// sub_60: assembly { +// /* "source":15252:15259 */ +// stop +// } +// +// sub_61: assembly { +// /* "source":15300:15307 */ +// stop +// } +// +// sub_62: assembly { +// /* "source":15348:15355 */ +// stop +// } +// +// sub_63: assembly { +// /* "source":15396:15403 */ +// stop +// } +// +// sub_64: assembly { +// /* "source":15444:15451 */ +// stop +// } +// +// sub_65: assembly { +// /* "source":15492:15499 */ +// stop +// } +// +// sub_66: assembly { +// /* "source":15540:15547 */ +// stop +// } +// +// sub_67: assembly { +// /* "source":15588:15595 */ +// stop +// } +// +// sub_68: assembly { +// /* "source":15636:15643 */ +// stop +// } +// +// sub_69: assembly { +// /* "source":15684:15691 */ +// stop +// } +// +// sub_70: assembly { +// /* "source":15732:15739 */ +// stop +// } +// +// sub_71: assembly { +// /* "source":15780:15787 */ +// stop +// } +// +// sub_72: assembly { +// /* "source":15828:15835 */ +// stop +// } +// +// sub_73: assembly { +// /* "source":15876:15883 */ +// stop +// } +// +// sub_74: assembly { +// /* "source":15924:15931 */ +// stop +// } +// +// sub_75: assembly { +// /* "source":15972:15979 */ +// stop +// } +// +// sub_76: assembly { +// /* "source":16020:16027 */ +// stop +// } +// +// sub_77: assembly { +// /* "source":16068:16075 */ +// stop +// } +// +// sub_78: assembly { +// /* "source":16116:16123 */ +// stop +// } +// +// sub_79: assembly { +// /* "source":16164:16171 */ +// stop +// } +// +// sub_80: assembly { +// /* "source":16212:16219 */ +// stop +// } +// +// sub_81: assembly { +// /* "source":16260:16267 */ +// stop +// } +// +// sub_82: assembly { +// /* "source":16308:16315 */ +// stop +// } +// +// sub_83: assembly { +// /* "source":16356:16363 */ +// stop +// } +// +// sub_84: assembly { +// /* "source":16404:16411 */ +// stop +// } +// +// sub_85: assembly { +// /* "source":16452:16459 */ +// stop +// } +// +// sub_86: assembly { +// /* "source":16500:16507 */ +// stop +// } +// +// sub_87: assembly { +// /* "source":16548:16555 */ +// stop +// } +// +// sub_88: assembly { +// /* "source":16596:16603 */ +// stop +// } +// +// sub_89: assembly { +// /* "source":16644:16651 */ +// stop +// } +// +// sub_90: assembly { +// /* "source":16692:16699 */ +// stop +// } +// +// sub_91: assembly { +// /* "source":16740:16747 */ +// stop +// } +// +// sub_92: assembly { +// /* "source":16788:16795 */ +// stop +// } +// +// sub_93: assembly { +// /* "source":16836:16843 */ +// stop +// } +// +// sub_94: assembly { +// /* "source":16884:16891 */ +// stop +// } +// +// sub_95: assembly { +// /* "source":16932:16939 */ +// stop +// } +// +// sub_96: assembly { +// /* "source":16980:16987 */ +// stop +// } +// +// sub_97: assembly { +// /* "source":17028:17035 */ +// stop +// } +// +// sub_98: assembly { +// /* "source":17076:17083 */ +// stop +// } +// +// sub_99: assembly { +// /* "source":17124:17131 */ +// stop +// } +// +// sub_100: assembly { +// /* "source":17172:17179 */ +// stop +// } +// +// sub_101: assembly { +// /* "source":17220:17227 */ +// stop +// } +// +// sub_102: assembly { +// /* "source":17268:17275 */ +// stop +// } +// +// sub_103: assembly { +// /* "source":17316:17323 */ +// stop +// } +// +// sub_104: assembly { +// /* "source":17364:17371 */ +// stop +// } +// +// sub_105: assembly { +// /* "source":17412:17419 */ +// stop +// } +// +// sub_106: assembly { +// /* "source":17460:17467 */ +// stop +// } +// +// sub_107: assembly { +// /* "source":17508:17515 */ +// stop +// } +// +// sub_108: assembly { +// /* "source":17556:17563 */ +// stop +// } +// +// sub_109: assembly { +// /* "source":17604:17611 */ +// stop +// } +// +// sub_110: assembly { +// /* "source":17652:17659 */ +// stop +// } +// +// sub_111: assembly { +// /* "source":17700:17707 */ +// stop +// } +// +// sub_112: assembly { +// /* "source":17748:17755 */ +// stop +// } +// +// sub_113: assembly { +// /* "source":17796:17803 */ +// stop +// } +// +// sub_114: assembly { +// /* "source":17844:17851 */ +// stop +// } +// +// sub_115: assembly { +// /* "source":17892:17899 */ +// stop +// } +// +// sub_116: assembly { +// /* "source":17940:17947 */ +// stop +// } +// +// sub_117: assembly { +// /* "source":17988:17995 */ +// stop +// } +// +// sub_118: assembly { +// /* "source":18036:18043 */ +// stop +// } +// +// sub_119: assembly { +// /* "source":18084:18091 */ +// stop +// } +// +// sub_120: assembly { +// /* "source":18132:18139 */ +// stop +// } +// +// sub_121: assembly { +// /* "source":18180:18187 */ +// stop +// } +// +// sub_122: assembly { +// /* "source":18228:18235 */ +// stop +// } +// +// sub_123: assembly { +// /* "source":18276:18283 */ +// stop +// } +// +// sub_124: assembly { +// /* "source":18324:18331 */ +// stop +// } +// +// sub_125: assembly { +// /* "source":18372:18379 */ +// stop +// } +// +// sub_126: assembly { +// /* "source":18420:18427 */ +// stop +// } +// +// sub_127: assembly { +// /* "source":18468:18475 */ +// stop +// } +// +// sub_128: assembly { +// /* "source":18516:18523 */ +// stop +// } +// +// sub_129: assembly { +// /* "source":18564:18571 */ +// stop +// } +// +// sub_130: assembly { +// /* "source":18612:18619 */ +// stop +// } +// +// sub_131: assembly { +// /* "source":18660:18667 */ +// stop +// } +// +// sub_132: assembly { +// /* "source":18708:18715 */ +// stop +// } +// +// sub_133: assembly { +// /* "source":18756:18763 */ +// stop +// } +// +// sub_134: assembly { +// /* "source":18804:18811 */ +// stop +// } +// +// sub_135: assembly { +// /* "source":18852:18859 */ +// stop +// } +// +// sub_136: assembly { +// /* "source":18900:18907 */ +// stop +// } +// +// sub_137: assembly { +// /* "source":18948:18955 */ +// stop +// } +// +// sub_138: assembly { +// /* "source":18996:19003 */ +// stop +// } +// +// sub_139: assembly { +// /* "source":19044:19051 */ +// stop +// } +// +// sub_140: assembly { +// /* "source":19092:19099 */ +// stop +// } +// +// sub_141: assembly { +// /* "source":19140:19147 */ +// stop +// } +// +// sub_142: assembly { +// /* "source":19188:19195 */ +// stop +// } +// +// sub_143: assembly { +// /* "source":19236:19243 */ +// stop +// } +// +// sub_144: assembly { +// /* "source":19284:19291 */ +// stop +// } +// +// sub_145: assembly { +// /* "source":19332:19339 */ +// stop +// } +// +// sub_146: assembly { +// /* "source":19380:19387 */ +// stop +// } +// +// sub_147: assembly { +// /* "source":19428:19435 */ +// stop +// } +// +// sub_148: assembly { +// /* "source":19476:19483 */ +// stop +// } +// +// sub_149: assembly { +// /* "source":19524:19531 */ +// stop +// } +// +// sub_150: assembly { +// /* "source":19572:19579 */ +// stop +// } +// +// sub_151: assembly { +// /* "source":19620:19627 */ +// stop +// } +// +// sub_152: assembly { +// /* "source":19668:19675 */ +// stop +// } +// +// sub_153: assembly { +// /* "source":19716:19723 */ +// stop +// } +// +// sub_154: assembly { +// /* "source":19764:19771 */ +// stop +// } +// +// sub_155: assembly { +// /* "source":19812:19819 */ +// stop +// } +// +// sub_156: assembly { +// /* "source":19860:19867 */ +// stop +// } +// +// sub_157: assembly { +// /* "source":19908:19915 */ +// stop +// } +// +// sub_158: assembly { +// /* "source":19956:19963 */ +// stop +// } +// +// sub_159: assembly { +// /* "source":20004:20011 */ +// stop +// } +// +// sub_160: assembly { +// /* "source":20052:20059 */ +// stop +// } +// +// sub_161: assembly { +// /* "source":20100:20107 */ +// stop +// } +// +// sub_162: assembly { +// /* "source":20148:20155 */ +// stop +// } +// +// sub_163: assembly { +// /* "source":20196:20203 */ +// stop +// } +// +// sub_164: assembly { +// /* "source":20244:20251 */ +// stop +// } +// +// sub_165: assembly { +// /* "source":20292:20299 */ +// stop +// } +// +// sub_166: assembly { +// /* "source":20340:20347 */ +// stop +// } +// +// sub_167: assembly { +// /* "source":20388:20395 */ +// stop +// } +// +// sub_168: assembly { +// /* "source":20436:20443 */ +// stop +// } +// +// sub_169: assembly { +// /* "source":20484:20491 */ +// stop +// } +// +// sub_170: assembly { +// /* "source":20532:20539 */ +// stop +// } +// +// sub_171: assembly { +// /* "source":20580:20587 */ +// stop +// } +// +// sub_172: assembly { +// /* "source":20628:20635 */ +// stop +// } +// +// sub_173: assembly { +// /* "source":20676:20683 */ +// stop +// } +// +// sub_174: assembly { +// /* "source":20724:20731 */ +// stop +// } +// +// sub_175: assembly { +// /* "source":20772:20779 */ +// stop +// } +// +// sub_176: assembly { +// /* "source":20820:20827 */ +// stop +// } +// +// sub_177: assembly { +// /* "source":20868:20875 */ +// stop +// } +// +// sub_178: assembly { +// /* "source":20916:20923 */ +// stop +// } +// +// sub_179: assembly { +// /* "source":20964:20971 */ +// stop +// } +// +// sub_180: assembly { +// /* "source":21012:21019 */ +// stop +// } +// +// sub_181: assembly { +// /* "source":21060:21067 */ +// stop +// } +// +// sub_182: assembly { +// /* "source":21108:21115 */ +// stop +// } +// +// sub_183: assembly { +// /* "source":21156:21163 */ +// stop +// } +// +// sub_184: assembly { +// /* "source":21204:21211 */ +// stop +// } +// +// sub_185: assembly { +// /* "source":21252:21259 */ +// stop +// } +// +// sub_186: assembly { +// /* "source":21300:21307 */ +// stop +// } +// +// sub_187: assembly { +// /* "source":21348:21355 */ +// stop +// } +// +// sub_188: assembly { +// /* "source":21396:21403 */ +// stop +// } +// +// sub_189: assembly { +// /* "source":21444:21451 */ +// stop +// } +// +// sub_190: assembly { +// /* "source":21492:21499 */ +// stop +// } +// +// sub_191: assembly { +// /* "source":21540:21547 */ +// stop +// } +// +// sub_192: assembly { +// /* "source":21588:21595 */ +// stop +// } +// +// sub_193: assembly { +// /* "source":21636:21643 */ +// stop +// } +// +// sub_194: assembly { +// /* "source":21684:21691 */ +// stop +// } +// +// sub_195: assembly { +// /* "source":21732:21739 */ +// stop +// } +// +// sub_196: assembly { +// /* "source":21780:21787 */ +// stop +// } +// +// sub_197: assembly { +// /* "source":21828:21835 */ +// stop +// } +// +// sub_198: assembly { +// /* "source":21876:21883 */ +// stop +// } +// +// sub_199: assembly { +// /* "source":21924:21931 */ +// stop +// } +// +// sub_200: assembly { +// /* "source":21972:21979 */ +// stop +// } +// +// sub_201: assembly { +// /* "source":22020:22027 */ +// stop +// } +// +// sub_202: assembly { +// /* "source":22068:22075 */ +// stop +// } +// +// sub_203: assembly { +// /* "source":22116:22123 */ +// stop +// } +// +// sub_204: assembly { +// /* "source":22164:22171 */ +// stop +// } +// +// sub_205: assembly { +// /* "source":22212:22219 */ +// stop +// } +// +// sub_206: assembly { +// /* "source":22260:22267 */ +// stop +// } +// +// sub_207: assembly { +// /* "source":22308:22315 */ +// stop +// } +// +// sub_208: assembly { +// /* "source":22356:22363 */ +// stop +// } +// +// sub_209: assembly { +// /* "source":22404:22411 */ +// stop +// } +// +// sub_210: assembly { +// /* "source":22452:22459 */ +// stop +// } +// +// sub_211: assembly { +// /* "source":22500:22507 */ +// stop +// } +// +// sub_212: assembly { +// /* "source":22548:22555 */ +// stop +// } +// +// sub_213: assembly { +// /* "source":22596:22603 */ +// stop +// } +// +// sub_214: assembly { +// /* "source":22644:22651 */ +// stop +// } +// +// sub_215: assembly { +// /* "source":22692:22699 */ +// stop +// } +// +// sub_216: assembly { +// /* "source":22740:22747 */ +// stop +// } +// +// sub_217: assembly { +// /* "source":22788:22795 */ +// stop +// } +// +// sub_218: assembly { +// /* "source":22836:22843 */ +// stop +// } +// +// sub_219: assembly { +// /* "source":22884:22891 */ +// stop +// } +// +// sub_220: assembly { +// /* "source":22932:22939 */ +// stop +// } +// +// sub_221: assembly { +// /* "source":22980:22987 */ +// stop +// } +// +// sub_222: assembly { +// /* "source":23028:23035 */ +// stop +// } +// +// sub_223: assembly { +// /* "source":23076:23083 */ +// stop +// } +// +// sub_224: assembly { +// /* "source":23124:23131 */ +// stop +// } +// +// sub_225: assembly { +// /* "source":23172:23179 */ +// stop +// } +// +// sub_226: assembly { +// /* "source":23220:23227 */ +// stop +// } +// +// sub_227: assembly { +// /* "source":23268:23275 */ +// stop +// } +// +// sub_228: assembly { +// /* "source":23316:23323 */ +// stop +// } +// +// sub_229: assembly { +// /* "source":23364:23371 */ +// stop +// } +// +// sub_230: assembly { +// /* "source":23412:23419 */ +// stop +// } +// +// sub_231: assembly { +// /* "source":23460:23467 */ +// stop +// } +// +// sub_232: assembly { +// /* "source":23508:23515 */ +// stop +// } +// +// sub_233: assembly { +// /* "source":23556:23563 */ +// stop +// } +// +// sub_234: assembly { +// /* "source":23604:23611 */ +// stop +// } +// +// sub_235: assembly { +// /* "source":23652:23659 */ +// stop +// } +// +// sub_236: assembly { +// /* "source":23700:23707 */ +// stop +// } +// +// sub_237: assembly { +// /* "source":23748:23755 */ +// stop +// } +// +// sub_238: assembly { +// /* "source":23796:23803 */ +// stop +// } +// +// sub_239: assembly { +// /* "source":23844:23851 */ +// stop +// } +// +// sub_240: assembly { +// /* "source":23892:23899 */ +// stop +// } +// +// sub_241: assembly { +// /* "source":23940:23947 */ +// stop +// } +// +// sub_242: assembly { +// /* "source":23988:23995 */ +// stop +// } +// +// sub_243: assembly { +// /* "source":24036:24043 */ +// stop +// } +// +// sub_244: assembly { +// /* "source":24084:24091 */ +// stop +// } +// +// sub_245: assembly { +// /* "source":24132:24139 */ +// stop +// } +// +// sub_246: assembly { +// /* "source":24180:24187 */ +// stop +// } +// +// sub_247: assembly { +// /* "source":24228:24235 */ +// stop +// } +// +// sub_248: assembly { +// /* "source":24276:24283 */ +// stop +// } +// +// sub_249: assembly { +// /* "source":24324:24331 */ +// stop +// } +// +// sub_250: assembly { +// /* "source":24372:24379 */ +// stop +// } +// +// sub_251: assembly { +// /* "source":24420:24427 */ +// stop +// } +// +// sub_252: assembly { +// /* "source":24468:24475 */ +// stop +// } +// +// sub_253: assembly { +// /* "source":24516:24523 */ +// stop +// } +// +// sub_254: assembly { +// /* "source":24564:24571 */ +// stop +// } +// +// sub_255: assembly { +// /* "source":24612:24619 */ +// stop +// } +// Bytecode: ef00010100040200010701030100001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001404000000008000045f808080ec00505f808080ec01505f808080ec02505f808080ec03505f808080ec04505f808080ec05505f808080ec06505f808080ec07505f808080ec08505f808080ec09505f808080ec0a505f808080ec0b505f808080ec0c505f808080ec0d505f808080ec0e505f808080ec0f505f808080ec10505f808080ec11505f808080ec12505f808080ec13505f808080ec14505f808080ec15505f808080ec16505f808080ec17505f808080ec18505f808080ec19505f808080ec1a505f808080ec1b505f808080ec1c505f808080ec1d505f808080ec1e505f808080ec1f505f808080ec20505f808080ec21505f808080ec22505f808080ec23505f808080ec24505f808080ec25505f808080ec26505f808080ec27505f808080ec28505f808080ec29505f808080ec2a505f808080ec2b505f808080ec2c505f808080ec2d505f808080ec2e505f808080ec2f505f808080ec30505f808080ec31505f808080ec32505f808080ec33505f808080ec34505f808080ec35505f808080ec36505f808080ec37505f808080ec38505f808080ec39505f808080ec3a505f808080ec3b505f808080ec3c505f808080ec3d505f808080ec3e505f808080ec3f505f808080ec40505f808080ec41505f808080ec42505f808080ec43505f808080ec44505f808080ec45505f808080ec46505f808080ec47505f808080ec48505f808080ec49505f808080ec4a505f808080ec4b505f808080ec4c505f808080ec4d505f808080ec4e505f808080ec4f505f808080ec50505f808080ec51505f808080ec52505f808080ec53505f808080ec54505f808080ec55505f808080ec56505f808080ec57505f808080ec58505f808080ec59505f808080ec5a505f808080ec5b505f808080ec5c505f808080ec5d505f808080ec5e505f808080ec5f505f808080ec60505f808080ec61505f808080ec62505f808080ec63505f808080ec64505f808080ec65505f808080ec66505f808080ec67505f808080ec68505f808080ec69505f808080ec6a505f808080ec6b505f808080ec6c505f808080ec6d505f808080ec6e505f808080ec6f505f808080ec70505f808080ec71505f808080ec72505f808080ec73505f808080ec74505f808080ec75505f808080ec76505f808080ec77505f808080ec78505f808080ec79505f808080ec7a505f808080ec7b505f808080ec7c505f808080ec7d505f808080ec7e505f808080ec7f505f808080ec80505f808080ec81505f808080ec82505f808080ec83505f808080ec84505f808080ec85505f808080ec86505f808080ec87505f808080ec88505f808080ec89505f808080ec8a505f808080ec8b505f808080ec8c505f808080ec8d505f808080ec8e505f808080ec8f505f808080ec90505f808080ec91505f808080ec92505f808080ec93505f808080ec94505f808080ec95505f808080ec96505f808080ec97505f808080ec98505f808080ec99505f808080ec9a505f808080ec9b505f808080ec9c505f808080ec9d505f808080ec9e505f808080ec9f505f808080eca0505f808080eca1505f808080eca2505f808080eca3505f808080eca4505f808080eca5505f808080eca6505f808080eca7505f808080eca8505f808080eca9505f808080ecaa505f808080ecab505f808080ecac505f808080ecad505f808080ecae505f808080ecaf505f808080ecb0505f808080ecb1505f808080ecb2505f808080ecb3505f808080ecb4505f808080ecb5505f808080ecb6505f808080ecb7505f808080ecb8505f808080ecb9505f808080ecba505f808080ecbb505f808080ecbc505f808080ecbd505f808080ecbe505f808080ecbf505f808080ecc0505f808080ecc1505f808080ecc2505f808080ecc3505f808080ecc4505f808080ecc5505f808080ecc6505f808080ecc7505f808080ecc8505f808080ecc9505f808080ecca505f808080eccb505f808080eccc505f808080eccd505f808080ecce505f808080eccf505f808080ecd0505f808080ecd1505f808080ecd2505f808080ecd3505f808080ecd4505f808080ecd5505f808080ecd6505f808080ecd7505f808080ecd8505f808080ecd9505f808080ecda505f808080ecdb505f808080ecdc505f808080ecdd505f808080ecde505f808080ecdf505f808080ece0505f808080ece1505f808080ece2505f808080ece3505f808080ece4505f808080ece5505f808080ece6505f808080ece7505f808080ece8505f808080ece9505f808080ecea505f808080eceb505f808080ecec505f808080eced505f808080ecee505f808080ecef505f808080ecf0505f808080ecf1505f808080ecf2505f808080ecf3505f808080ecf4505f808080ecf5505f808080ecf6505f808080ecf7505f808080ecf8505f808080ecf9505f808080ecfa505f808080ecfb505f808080ecfc505f808080ecfd505f808080ecfe505f808080ecff5000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD SMOD ADD SUB ADD STOP STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ DIV STOP STOP STOP STOP DUP1 STOP DIV PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x10 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x11 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x12 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x13 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x14 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x15 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x16 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x17 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x18 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x19 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x20 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x21 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x22 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x23 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x24 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x25 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x26 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x27 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x28 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x29 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x30 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x31 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x32 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x33 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x34 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x35 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x36 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x37 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x38 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x39 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x40 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x41 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x42 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x43 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x44 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x45 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x46 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x47 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x48 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x49 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x50 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x51 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x52 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x53 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x54 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x55 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x56 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x57 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x58 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x59 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x60 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x61 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x62 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x63 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x64 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x65 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x66 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x67 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x68 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x69 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x70 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x71 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x72 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x73 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x74 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x75 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x76 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x77 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x78 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x79 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x80 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x81 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x82 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x83 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x84 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x85 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x86 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x87 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x88 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x89 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x90 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x91 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x92 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x93 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x94 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x95 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x96 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x97 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x98 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x99 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xED POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFF POP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP +// SourceMappings: 78:1:0:-:0;50:30;;;;46:35;126:1;98:30;;;;94:35;174:1;146:30;;;;142:35;222:1;194:30;;;;190:35;270:1;242:30;;;;238:35;318:1;290:30;;;;286:35;366:1;338:30;;;;334:35;414:1;386:30;;;;382:35;462:1;434:30;;;;430:35;510:1;482:30;;;;478:35;558:1;530:30;;;;526:35;606:1;578:30;;;;574:35;654:1;626:30;;;;622:35;702:1;674:30;;;;670:35;750:1;722:30;;;;718:35;798:1;770:30;;;;766:35;846:1;818:30;;;;814:35;894:1;866:30;;;;862:35;942:1;914:30;;;;910:35;990:1;962:30;;;;958:35;1038:1;1010:30;;;;1006:35;1086:1;1058:30;;;;1054:35;1134:1;1106:30;;;;1102:35;1182:1;1154:30;;;;1150:35;1230:1;1202:30;;;;1198:35;1278:1;1250:30;;;;1246:35;1326:1;1298:30;;;;1294:35;1374:1;1346:30;;;;1342:35;1422:1;1394:30;;;;1390:35;1470:1;1442:30;;;;1438:35;1518:1;1490:30;;;;1486:35;1566:1;1538:30;;;;1534:35;1614:1;1586:30;;;;1582:35;1662:1;1634:30;;;;1630:35;1710:1;1682:30;;;;1678:35;1758:1;1730:30;;;;1726:35;1806:1;1778:30;;;;1774:35;1854:1;1826:30;;;;1822:35;1902:1;1874:30;;;;1870:35;1950:1;1922:30;;;;1918:35;1998:1;1970:30;;;;1966:35;2046:1;2018:30;;;;2014:35;2094:1;2066:30;;;;2062:35;2142:1;2114:30;;;;2110:35;2190:1;2162:30;;;;2158:35;2238:1;2210:30;;;;2206:35;2286:1;2258:30;;;;2254:35;2334:1;2306:30;;;;2302:35;2382:1;2354:30;;;;2350:35;2430:1;2402:30;;;;2398:35;2478:1;2450:30;;;;2446:35;2526:1;2498:30;;;;2494:35;2574:1;2546:30;;;;2542:35;2622:1;2594:30;;;;2590:35;2670:1;2642:30;;;;2638:35;2718:1;2690:30;;;;2686:35;2766:1;2738:30;;;;2734:35;2814:1;2786:30;;;;2782:35;2862:1;2834:30;;;;2830:35;2910:1;2882:30;;;;2878:35;2958:1;2930:30;;;;2926:35;3006:1;2978:30;;;;2974:35;3054:1;3026:30;;;;3022:35;3102:1;3074:30;;;;3070:35;3150:1;3122:30;;;;3118:35;3198:1;3170:30;;;;3166:35;3246:1;3218:30;;;;3214:35;3294:1;3266:30;;;;3262:35;3342:1;3314:30;;;;3310:35;3390:1;3362:30;;;;3358:35;3438:1;3410:30;;;;3406:35;3486:1;3458:30;;;;3454:35;3534:1;3506:30;;;;3502:35;3582:1;3554:30;;;;3550:35;3630:1;3602:30;;;;3598:35;3678:1;3650:30;;;;3646:35;3726:1;3698:30;;;;3694:35;3774:1;3746:30;;;;3742:35;3822:1;3794:30;;;;3790:35;3870:1;3842:30;;;;3838:35;3918:1;3890:30;;;;3886:35;3966:1;3938:30;;;;3934:35;4014:1;3986:30;;;;3982:35;4062:1;4034:30;;;;4030:35;4110:1;4082:30;;;;4078:35;4158:1;4130:30;;;;4126:35;4206:1;4178:30;;;;4174:35;4254:1;4226:30;;;;4222:35;4302:1;4274:30;;;;4270:35;4350:1;4322:30;;;;4318:35;4398:1;4370:30;;;;4366:35;4446:1;4418:30;;;;4414:35;4494:1;4466:30;;;;4462:35;4542:1;4514:30;;;;4510:35;4590:1;4562:30;;;;4558:35;4638:1;4610:30;;;;4606:35;4686:1;4658:30;;;;4654:35;4734:1;4706:30;;;;4702:35;4782:1;4754:30;;;;4750:35;4830:1;4802:30;;;;4798:35;4878:1;4850:30;;;;4846:35;4926:1;4898:30;;;;4894:35;4974:1;4946:30;;;;4942:35;5022:1;4994:30;;;;4990:35;5070:1;5042:30;;;;5038:35;5118:1;5090:30;;;;5086:35;5166:1;5138:30;;;;5134:35;5214:1;5186:30;;;;5182:35;5262:1;5234:30;;;;5230:35;5310:1;5282:30;;;;5278:35;5358:1;5330:30;;;;5326:35;5406:1;5378:30;;;;5374:35;5454:1;5426:30;;;;5422:35;5502:1;5474:30;;;;5470:35;5550:1;5522:30;;;;5518:35;5598:1;5570:30;;;;5566:35;5646:1;5618:30;;;;5614:35;5694:1;5666:30;;;;5662:35;5742:1;5714:30;;;;5710:35;5790:1;5762:30;;;;5758:35;5838:1;5810:30;;;;5806:35;5886:1;5858:30;;;;5854:35;5934:1;5906:30;;;;5902:35;5982:1;5954:30;;;;5950:35;6030:1;6002:30;;;;5998:35;6078:1;6050:30;;;;6046:35;6126:1;6098:30;;;;6094:35;6174:1;6146:30;;;;6142:35;6222:1;6194:30;;;;6190:35;6270:1;6242:30;;;;6238:35;6318:1;6290:30;;;;6286:35;6366:1;6338:30;;;;6334:35;6414:1;6386:30;;;;6382:35;6462:1;6434:30;;;;6430:35;6510:1;6482:30;;;;6478:35;6558:1;6530:30;;;;6526:35;6606:1;6578:30;;;;6574:35;6654:1;6626:30;;;;6622:35;6702:1;6674:30;;;;6670:35;6750:1;6722:30;;;;6718:35;6798:1;6770:30;;;;6766:35;6846:1;6818:30;;;;6814:35;6894:1;6866:30;;;;6862:35;6942:1;6914:30;;;;6910:35;6990:1;6962:30;;;;6958:35;7038:1;7010:30;;;;7006:35;7086:1;7058:30;;;;7054:35;7134:1;7106:30;;;;7102:35;7182:1;7154:30;;;;7150:35;7230:1;7202:30;;;;7198:35;7278:1;7250:30;;;;7246:35;7326:1;7298:30;;;;7294:35;7374:1;7346:30;;;;7342:35;7422:1;7394:30;;;;7390:35;7470:1;7442:30;;;;7438:35;7518:1;7490:30;;;;7486:35;7566:1;7538:30;;;;7534:35;7614:1;7586:30;;;;7582:35;7662:1;7634:30;;;;7630:35;7710:1;7682:30;;;;7678:35;7758:1;7730:30;;;;7726:35;7806:1;7778:30;;;;7774:35;7854:1;7826:30;;;;7822:35;7902:1;7874:30;;;;7870:35;7950:1;7922:30;;;;7918:35;7998:1;7970:30;;;;7966:35;8046:1;8018:30;;;;8014:35;8094:1;8066:30;;;;8062:35;8142:1;8114:30;;;;8110:35;8190:1;8162:30;;;;8158:35;8238:1;8210:30;;;;8206:35;8286:1;8258:30;;;;8254:35;8334:1;8306:30;;;;8302:35;8382:1;8354:30;;;;8350:35;8430:1;8402:30;;;;8398:35;8478:1;8450:30;;;;8446:35;8526:1;8498:30;;;;8494:35;8574:1;8546:30;;;;8542:35;8622:1;8594:30;;;;8590:35;8670:1;8642:30;;;;8638:35;8718:1;8690:30;;;;8686:35;8766:1;8738:30;;;;8734:35;8814:1;8786:30;;;;8782:35;8862:1;8834:30;;;;8830:35;8910:1;8882:30;;;;8878:35;8958:1;8930:30;;;;8926:35;9006:1;8978:30;;;;8974:35;9054:1;9026:30;;;;9022:35;9102:1;9074:30;;;;9070:35;9150:1;9122:30;;;;9118:35;9198:1;9170:30;;;;9166:35;9246:1;9218:30;;;;9214:35;9294:1;9266:30;;;;9262:35;9342:1;9314:30;;;;9310:35;9390:1;9362:30;;;;9358:35;9438:1;9410:30;;;;9406:35;9486:1;9458:30;;;;9454:35;9534:1;9506:30;;;;9502:35;9582:1;9554:30;;;;9550:35;9630:1;9602:30;;;;9598:35;9678:1;9650:30;;;;9646:35;9726:1;9698:30;;;;9694:35;9774:1;9746:30;;;;9742:35;9822:1;9794:30;;;;9790:35;9870:1;9842:30;;;;9838:35;9918:1;9890:30;;;;9886:35;9966:1;9938:30;;;;9934:35;10014:1;9986:30;;;;9982:35;10062:1;10034:30;;;;10030:35;10110:1;10082:30;;;;10078:35;10158:1;10130:30;;;;10126:35;10206:1;10178:30;;;;10174:35;10254:1;10226:30;;;;10222:35;10302:1;10274:30;;;;10270:35;10350:1;10322:30;;;;10318:35;10398:1;10370:30;;;;10366:35;10446:1;10418:30;;;;10414:35;10494:1;10466:30;;;;10462:35;10542:1;10514:30;;;;10510:35;10590:1;10562:30;;;;10558:35;10638:1;10610:30;;;;10606:35;10686:1;10658:30;;;;10654:35;10734:1;10706:30;;;;10702:35;10782:1;10754:30;;;;10750:35;10830:1;10802:30;;;;10798:35;10878:1;10850:30;;;;10846:35;10926:1;10898:30;;;;10894:35;10974:1;10946:30;;;;10942:35;11022:1;10994:30;;;;10990:35;11070:1;11042:30;;;;11038:35;11118:1;11090:30;;;;11086:35;11166:1;11138:30;;;;11134:35;11214:1;11186:30;;;;11182:35;11262:1;11234:30;;;;11230:35;11310:1;11282:30;;;;11278:35;11358:1;11330:30;;;;11326:35;11406:1;11378:30;;;;11374:35;11454:1;11426:30;;;;11422:35;11502:1;11474:30;;;;11470:35;11550:1;11522:30;;;;11518:35;11598:1;11570:30;;;;11566:35;11646:1;11618:30;;;;11614:35;11694:1;11666:30;;;;11662:35;11742:1;11714:30;;;;11710:35;11790:1;11762:30;;;;11758:35;11838:1;11810:30;;;;11806:35;11886:1;11858:30;;;;11854:35;11934:1;11906:30;;;;11902:35;11982:1;11954:30;;;;11950:35;12030:1;12002:30;;;;11998:35;12078:1;12050:30;;;;12046:35;12126:1;12098:30;;;;12094:35;12174:1;12146:30;;;;12142:35;12222:1;12194:30;;;;12190:35;12270:1;12242:30;;;;12238:35;12318:1;12290:30;;;;12286:35;22:12315 diff --git a/test/libyul/objectCompiler/eof/creation_with_immutables.yul b/test/libyul/objectCompiler/eof/creation_with_immutables.yul new file mode 100644 index 000000000000..abac2440ceaa --- /dev/null +++ b/test/libyul/objectCompiler/eof/creation_with_immutables.yul @@ -0,0 +1,99 @@ +object "a" { + code { + mstore(0, eofcreate("b", 0, 0, 0, 0)) + return(0, 32) + } + + object "b" { + code { + mstore(0, 0x1122334455667788990011223344556677889900112233445566778899001122) + mstore(32, 0x1122334455667788990011223344556677889900112233445566778899001122) + returncontract("c", 0, 64) + } + object "c" { + code { + let d0 := auxdataloadn(0) + let d1 := auxdataloadn(32) + + mstore(0, d0) + mstore(32, d1) + + return(0, 64) + } + } + } + + data "data1" hex"48656c6c6f2c20576f726c6421" +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":80:81 */ +// 0x00 +// /* "source":56:82 */ +// dup1 +// dup1 +// dup1 +// eofcreate{0} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:83 */ +// mstore +// /* "source":106:108 */ +// 0x20 +// /* "source":103:104 */ +// 0x00 +// /* "source":96:109 */ +// return +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// +// sub_0: assembly { +// /* "source":198:264 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":195:196 */ +// 0x00 +// /* "source":188:265 */ +// mstore +// /* "source":293:359 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":289:291 */ +// 0x20 +// /* "source":282:360 */ +// mstore +// /* "source":400:402 */ +// 0x40 +// /* "source":397:398 */ +// 0x00 +// /* "source":377:403 */ +// returncontract{0} +// stop +// +// sub_0: assembly { +// /* "source":516:531 */ +// auxdataloadn{0} +// /* "source":562:578 */ +// auxdataloadn{32} +// /* "source":599:612 */ +// swap1 +// /* "source":606:607 */ +// 0x00 +// /* "source":599:612 */ +// mstore +// /* "source":640:642 */ +// 0x20 +// /* "source":633:647 */ +// mstore +// /* "source":678:680 */ +// 0x40 +// /* "source":675:676 */ +// 0x00 +// /* "source":668:681 */ +// return +// } +// } +// Bytecode: ef0001010004020001000c030001008704000d00008000045f808080ec005f5260205ff3ef0001010004020001004c030001002304000000008000027f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205260405fee00ef000101000402000100100400400000800003ef0000ef0020905f5260205260405ff348656c6c6f2c20576f726c6421 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0xC SUB STOP ADD STOP DUP8 DIV STOP 0xD STOP STOP DUP1 STOP DIV PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0x4C SUB STOP ADD STOP 0x23 DIV STOP STOP STOP STOP DUP1 STOP MUL PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH0 MSTORE PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH1 0x20 MSTORE PUSH1 0x40 PUSH0 RETURNCONTRACT 0x0 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP LT DIV STOP BLOCKHASH STOP STOP DUP1 STOP SUB DATALOADN 0x0 DATALOADN 0x20 SWAP1 PUSH0 MSTORE PUSH1 0x20 MSTORE PUSH1 0x40 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 +// SourceMappings: 80:1:0:-:0;56:26;;;;53:1;46:37;106:2;103:1;96:13 diff --git a/test/libyul/objectCompiler/eof/dataloadn.yul b/test/libyul/objectCompiler/eof/dataloadn.yul new file mode 100644 index 000000000000..95b220e4591c --- /dev/null +++ b/test/libyul/objectCompiler/eof/dataloadn.yul @@ -0,0 +1,31 @@ +object "a" { + code { + { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + } + data "data1" hex"48656c6c6f2c20576f726c6421" +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":56:71 */ +// auxdataloadn{0} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:72 */ +// mstore +// /* "source":95:97 */ +// 0x20 +// /* "source":92:93 */ +// 0x00 +// /* "source":85:98 */ +// return +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// Bytecode: ef0001010004020001000904002d0000800002ef000d5f5260205ff348656c6c6f2c20576f726c6421 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP MULMOD DIV STOP 0x2D STOP STOP DUP1 STOP MUL DATALOADN 0xD PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 +// SourceMappings: 56:15:0:-:0;53:1;46:26;95:2;92:1;85:13 diff --git a/test/libyul/objectCompiler/eof/extcall.yul b/test/libyul/objectCompiler/eof/extcall.yul new file mode 100644 index 000000000000..d0322b1a9e2e --- /dev/null +++ b/test/libyul/objectCompiler/eof/extcall.yul @@ -0,0 +1,52 @@ +object "a" { + code { + sstore(0, extcall(address(), 0, 0, 10)) + sstore(1, extdelegatecall(address(), 0, 0)) + sstore(2, extstaticcall(address(), 0, 0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":81:83 */ +// 0x0a +// /* "source":78:79 */ +// 0x00 +// /* "source":64:73 */ +// dup1 +// address +// /* "source":56:84 */ +// extcall +// /* "source":53:54 */ +// 0x00 +// /* "source":46:85 */ +// sstore +// /* "source":138:139 */ +// 0x00 +// /* "source":124:133 */ +// dup1 +// address +// /* "source":108:140 */ +// extdelegatecall +// /* "source":105:106 */ +// 0x01 +// /* "source":98:141 */ +// sstore +// /* "source":192:193 */ +// 0x00 +// /* "source":178:187 */ +// dup1 +// address +// /* "source":164:194 */ +// extstaticcall +// /* "source":161:162 */ +// 0x02 +// /* "source":154:195 */ +// sstore +// /* "source":22:211 */ +// stop +// Bytecode: ef000101000402000100170400000000800004600a5f8030f85f555f8030f96001555f8030fb60025500 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP OR DIV STOP STOP STOP STOP DUP1 STOP DIV PUSH1 0xA PUSH0 DUP1 ADDRESS EXTCALL PUSH0 SSTORE PUSH0 DUP1 ADDRESS EXTDELEGATECALL PUSH1 0x1 SSTORE PUSH0 DUP1 ADDRESS EXTSTATICCALL PUSH1 0x2 SSTORE STOP +// SourceMappings: 81:2:0:-:0;78:1;64:9;;56:28;53:1;46:39;138:1;124:9;;108:32;105:1;98:43;192:1;178:9;;164:30;161:1;154:41;22:189 diff --git a/test/libyul/objectCompiler/eof/functions.yul b/test/libyul/objectCompiler/eof/functions.yul new file mode 100644 index 000000000000..65361efa3b5e --- /dev/null +++ b/test/libyul/objectCompiler/eof/functions.yul @@ -0,0 +1,84 @@ +object "a" { + code { + mstore(0, fun1(calldataload(0))) + + if calldataload(32) { + non_ret_fun() + } + + return(0, 32) + + function fun1(i) -> r { + if i { + r := 5 + leave + } + r := 99 + } + + function non_ret_fun() { + revert(0, 0) + } + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":74:75 */ +// 0x00 +// /* "source":61:76 */ +// calldataload +// /* "source":56:77 */ +// callf{code_section_1} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:78 */ +// mstore +// /* "source":107:109 */ +// 0x20 +// /* "source":94:110 */ +// calldataload +// /* "source":91:128 */ +// rjumpi{tag_1} +// /* "source":22:386 */ +// tag_2: +// /* "source":151:153 */ +// 0x20 +// /* "source":148:149 */ +// 0x00 +// /* "source":141:154 */ +// return +// /* "source":111:128 */ +// tag_1: +// /* "source":113:126 */ +// jumpf{code_section_2} +// +// code_section_1: assembly { +// /* "source":217:294 */ +// rjumpi{tag_3} +// /* "source":203:324 */ +// tag_4: +// /* "source":312:314 */ +// 0x63 +// /* "source":173:324 */ +// retf +// /* "source":234:294 */ +// tag_3: +// /* "source":257:258 */ +// 0x05 +// /* "source":275:280 */ +// retf +// } +// +// code_section_2: assembly { +// /* "source":376:377 */ +// 0x00 +// /* "source":366:378 */ +// dup1 +// revert +// } +// Bytecode: ef000101000c020003001400090003040000000080000201010001008000025f35e300015f52602035e1000460205ff3e50002e100036063e46005e45f80fd +// Opcodes: 0xEF STOP ADD ADD STOP 0xC MUL STOP SUB STOP EQ STOP MULMOD STOP SUB DIV STOP STOP STOP STOP DUP1 STOP MUL ADD ADD STOP ADD STOP DUP1 STOP MUL PUSH0 CALLDATALOAD CALLF 0x1 PUSH0 MSTORE PUSH1 0x20 CALLDATALOAD RJUMPI 0x4 PUSH1 0x20 PUSH0 RETURN JUMPF 0x2 RJUMPI 0x3 PUSH1 0x63 RETF PUSH1 0x5 RETF PUSH0 DUP1 REVERT +// SourceMappings: 74:1:0:-:0;61:15;56:21::i;53:1::-;46:32;107:2;94:16;91:37;22:364;151:2;148:1;141:13;111:17;113:13::i217:77:0:-:0;203:121;312:2;173:151::o;234:60::-;257:1;275:5::o376:1:0:-:0;366:12; diff --git a/test/libyul/objectCompiler/eof/leading_and_trailing_dots.yul b/test/libyul/objectCompiler/eof/leading_and_trailing_dots.yul new file mode 100644 index 000000000000..f62e24233db1 --- /dev/null +++ b/test/libyul/objectCompiler/eof/leading_and_trailing_dots.yul @@ -0,0 +1,30 @@ +{ + function e(_._) { + e(0) + } + e(2) + function f(n._) { + f(0) + } + f(2) + function g(_.n) { + g(0) + } + g(2) +} +// ==== +// bytecodeFormat: >=EOFv1 +// outputs: Assembly +// ---- +// Assembly: +// /* "source":53:54 */ +// 0x02 +// /* "source":51:55 */ +// jumpf{code_section_1} +// +// code_section_1: assembly { +// /* "source":136:137 */ +// 0x00 +// /* "source":134:138 */ +// jumpf{code_section_1} +// } diff --git a/test/libyul/objectCompiler/eof/long_object_name.yul b/test/libyul/objectCompiler/eof/long_object_name.yul new file mode 100644 index 000000000000..680a268885d9 --- /dev/null +++ b/test/libyul/objectCompiler/eof/long_object_name.yul @@ -0,0 +1,33 @@ +object "t" { + code { + sstore(0, eofcreate("name_that_is_longer_than_32_bytes_name_that_is_longer_than_32_bytes_name_that_is_longer_than_32_bytes", 0, 0, 0, 0)) + } + object "name_that_is_longer_than_32_bytes_name_that_is_longer_than_32_bytes_name_that_is_longer_than_32_bytes" { + code {} + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// optimizationPreset: full +// outputs: Assembly +// ---- +// Assembly: +// /* "source":180:181 */ +// 0x00 +// /* "source":56:182 */ +// dup1 +// dup1 +// dup1 +// eofcreate{0} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:183 */ +// sstore +// /* "source":22:199 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":330:337 */ +// stop +// } diff --git a/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul b/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul new file mode 100644 index 000000000000..f4792619f185 --- /dev/null +++ b/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul @@ -0,0 +1,29 @@ +object "Contract" { + code { + f() + g() + + function f() { revert(0, 0) } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":53:56 */ +// jumpf{code_section_1} +// +// code_section_1: assembly { +// /* "source":124:125 */ +// 0x00 +// /* "source":114:126 */ +// dup1 +// revert +// } +// Bytecode: ef000101000802000200030003040000000080000000800002e500015f80fd +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP SUB STOP SUB DIV STOP STOP STOP STOP DUP1 STOP STOP STOP DUP1 STOP MUL JUMPF 0x1 PUSH0 DUP1 REVERT +// SourceMappings: 53:3:0:i:0124:1:0:-:0;114:12; diff --git a/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul b/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul new file mode 100644 index 000000000000..0276b4cad5e9 --- /dev/null +++ b/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul @@ -0,0 +1,25 @@ +object "Contract" { + code { + f() + g() + + function f() { f() } + function g() { mstore(0, 2) } + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":53:56 */ +// jumpf{code_section_1} +// +// code_section_1: assembly { +// /* "source":114:117 */ +// jumpf{code_section_1} +// } +// Bytecode: ef000101000802000200030003040000000080000000800000e50001e50001 +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP SUB STOP SUB DIV STOP STOP STOP STOP DUP1 STOP STOP STOP DUP1 STOP STOP JUMPF 0x1 JUMPF 0x1 +// SourceMappings: 53:3:0:i:0114:3:0:i:0 diff --git a/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul b/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul new file mode 100644 index 000000000000..35f503c708fa --- /dev/null +++ b/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul @@ -0,0 +1,80 @@ +object "a" { + code { + mstore(0, eofcreate("c", 0, 0, 0, 0)) + return(0, 32) + } + + object "b" { + code { + mstore(0, 0x1122334455667788990011223344556677889900112233445566778899001122) + mstore(32, 0x1122334455667788990011223344556677889900112233445566778899001122) + } + } + + object "c" { + code { + mstore(0, 0x1122334455667788990011223344556677889900112233445566778899001122) + mstore(32, 0x1122334455667788990011223344556677889900112233445566778899001122) + } + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":80:81 */ +// 0x00 +// /* "source":56:82 */ +// dup1 +// dup1 +// dup1 +// eofcreate{1} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:83 */ +// mstore +// /* "source":106:108 */ +// 0x20 +// /* "source":103:104 */ +// 0x00 +// /* "source":96:109 */ +// return +// stop +// +// sub_0: assembly { +// /* "source":198:264 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":195:196 */ +// 0x00 +// /* "source":188:265 */ +// mstore +// /* "source":293:359 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":289:291 */ +// 0x20 +// /* "source":282:360 */ +// mstore +// /* "source":156:384 */ +// stop +// } +// +// sub_1: assembly { +// /* "source":463:529 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":460:461 */ +// 0x00 +// /* "source":453:530 */ +// mstore +// /* "source":558:624 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":554:556 */ +// 0x20 +// /* "source":547:625 */ +// mstore +// /* "source":421:649 */ +// stop +// } +// Bytecode: ef0001010004020001000c030001005b04000000008000045f808080ec005f5260205ff3ef0001010004020001004804000000008000027f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205200 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0xC SUB STOP ADD STOP JUMPDEST DIV STOP STOP STOP STOP DUP1 STOP DIV PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP BASEFEE DIV STOP STOP STOP STOP DUP1 STOP MUL PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH0 MSTORE PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH1 0x20 MSTORE STOP +// SourceMappings: 80:1:0:-:0;56:26;;;;53:1;46:37;106:2;103:1;96:13 diff --git a/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul b/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul new file mode 100644 index 000000000000..8cbb294cda49 --- /dev/null +++ b/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul @@ -0,0 +1,33 @@ +object "Contract" { + code { + g() + + function f() { mstore(0, 3) } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":41:44 */ +// callf{code_section_1} +// /* "source":29:98 */ +// stop +// +// code_section_1: assembly { +// /* "source":88:89 */ +// 0x02 +// /* "source":85:86 */ +// 0x00 +// /* "source":78:90 */ +// mstore +// /* "source":55:92 */ +// retf +// } +// Bytecode: ef000101000802000200040005040000000080000000000002e300010060025f52e4 +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP DIV STOP SDIV DIV STOP STOP STOP STOP DUP1 STOP STOP STOP STOP STOP MUL CALLF 0x1 STOP PUSH1 0x2 PUSH0 MSTORE RETF +// SourceMappings: 41:3:0:i:0;29:69::-88:1:0:-:0;85;78:12;55:37::o diff --git a/test/libyul/objectCompiler/eof/rjumps.yul b/test/libyul/objectCompiler/eof/rjumps.yul new file mode 100644 index 000000000000..49665784e9a2 --- /dev/null +++ b/test/libyul/objectCompiler/eof/rjumps.yul @@ -0,0 +1,39 @@ +object "a" { + code { + if true { + mstore(0, 1) + } + + return(0, 32) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":49:53 */ +// 0x01 +// /* "source":46:70 */ +// rjumpi{tag_1} +// /* "source":22:112 */ +// tag_2: +// /* "source":93:95 */ +// 0x20 +// /* "source":90:91 */ +// 0x00 +// /* "source":83:96 */ +// return +// /* "source":54:70 */ +// tag_1: +// /* "source":66:67 */ +// 0x01 +// /* "source":63:64 */ +// 0x00 +// /* "source":56:68 */ +// mstore +// /* "source":54:70 */ +// rjump{tag_2} +// Bytecode: ef0001010004020001001004000000008000026001e1000460205ff360015f52e0fff5 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP LT DIV STOP STOP STOP STOP DUP1 STOP MUL PUSH1 0x1 RJUMPI 0x4 PUSH1 0x20 PUSH0 RETURN PUSH1 0x1 PUSH0 MSTORE RJUMP 0xFFF5 +// SourceMappings: 49:4:0:-:0;46:24;22:90;93:2;90:1;83:13;54:16;66:1;63;56:12;54:16 diff --git a/test/libyul/objectCompiler/eof/simple.yul b/test/libyul/objectCompiler/eof/simple.yul new file mode 100644 index 000000000000..cfb95fbecfb1 --- /dev/null +++ b/test/libyul/objectCompiler/eof/simple.yul @@ -0,0 +1,19 @@ +{ + sstore(0, 1) +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":41:42 */ +// 0x01 +// /* "source":38:39 */ +// 0x00 +// /* "source":31:43 */ +// sstore +// /* "source":27:47 */ +// stop +// Bytecode: ef00010100040200010005040000000080000260015f5500 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP SDIV DIV STOP STOP STOP STOP DUP1 STOP MUL PUSH1 0x1 PUSH0 SSTORE STOP +// SourceMappings: 41:1:0:-:0;38;31:12;27:20 diff --git a/test/libyul/objectCompiler/eof/smoke.yul b/test/libyul/objectCompiler/eof/smoke.yul new file mode 100644 index 000000000000..eecfac9a8741 --- /dev/null +++ b/test/libyul/objectCompiler/eof/smoke.yul @@ -0,0 +1,12 @@ +{ +} +// ==== +// EVMVersion: >=constantinople +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":27:34 */ +// stop +// Bytecode: ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP +// SourceMappings: 27:7:0:-:0 diff --git a/test/libyul/objectCompiler/eof/subObject.yul b/test/libyul/objectCompiler/eof/subObject.yul new file mode 100644 index 000000000000..2f1771d79008 --- /dev/null +++ b/test/libyul/objectCompiler/eof/subObject.yul @@ -0,0 +1,29 @@ +object "a" { + code {} + // Unreferenced data is not added to the assembled bytecode. + // TODO: This is not implemented for EOF. Uncomment line below when implemented. + // data "str" "Hello, World!" + // Unreferenced object is not added to the assembled bytecode. + object "sub" { code { sstore(0, 1) } } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":22:29 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":76:77 */ +// 0x01 +// /* "source":73:74 */ +// 0x00 +// /* "source":66:78 */ +// sstore +// /* "source":62:82 */ +// stop +// } +// Bytecode: ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP +// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/eof/subSubObject.yul b/test/libyul/objectCompiler/eof/subSubObject.yul new file mode 100644 index 000000000000..39dd209bfd90 --- /dev/null +++ b/test/libyul/objectCompiler/eof/subSubObject.yul @@ -0,0 +1,49 @@ +object "a" { + code {} + // Unreferenced data is not added to the assembled bytecode. + // TODO: This is not implemented for EOF. Uncomment line below when implemented. + // data "str" "Hello, World!" + // Unreferenced object is not added to the assembled bytecode. + object "sub" { + code { sstore(0, 1) } + object "subsub" { + code { sstore(2, 3) } + data "str" hex"123456" + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":22:29 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":76:77 */ +// 0x01 +// /* "source":73:74 */ +// 0x00 +// /* "source":66:78 */ +// sstore +// /* "source":62:82 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":140:141 */ +// 0x03 +// /* "source":137:138 */ +// 0x02 +// /* "source":130:142 */ +// sstore +// /* "source":126:146 */ +// stop +// stop +// data_6adf031833174bbe4c85eafe59ddb54e6584648c2c962c6f94791ab49caa0ad4 123456 +// } +// } +// Bytecode: ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP +// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/eof/verbatim_bug.yul b/test/libyul/objectCompiler/eof/verbatim_bug.yul new file mode 100644 index 000000000000..704702a53519 --- /dev/null +++ b/test/libyul/objectCompiler/eof/verbatim_bug.yul @@ -0,0 +1,118 @@ +object "a" { + code { + let dummy := 0xAABBCCDDEEFF + let input := sload(0) + let output + + switch input + case 0x00 { + // Note that due to a bug the following disappeared from the assembly output. + output := verbatim_1i_1o(hex"506000", dummy) + } + case 0x01 { + output := 1 + } + case 0x02 { + output := verbatim_1i_1o(hex"506002", dummy) + } + case 0x03 { + output := 3 + } + + sstore(0, output) + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// optimizationPreset: full +// outputs: Assembly +// ---- +// Assembly: +// /* "source":65:66 */ +// 0x00 +// /* "source":59:67 */ +// sload +// /* "source":94:95 */ +// 0x00 +// /* "source":108:406 */ +// swap1 +// /* "source":133:225 */ +// dup1 +// /* "source":138:142 */ +// 0x00 +// /* "source":133:225 */ +// eq +// rjumpi{tag_1} +// /* "source":108:406 */ +// tag_2: +// /* "source":238:263 */ +// dup1 +// /* "source":243:247 */ +// 0x01 +// /* "source":238:263 */ +// eq +// rjumpi{tag_3} +// /* "source":108:406 */ +// tag_4: +// /* "source":276:368 */ +// dup1 +// /* "source":281:285 */ +// 0x02 +// /* "source":276:368 */ +// eq +// rjumpi{tag_5} +// /* "source":108:406 */ +// tag_6: +// /* "source":386:390 */ +// 0x03 +// /* "source":381:406 */ +// eq +// rjumpi{tag_7} +// /* "source":108:406 */ +// tag_8: +// /* "source":426:427 */ +// 0x00 +// /* "source":419:436 */ +// sstore +// /* "source":108:406 */ +// stop +// /* "source":391:406 */ +// tag_7: +// /* "source":393:404 */ +// pop +// /* "source":403:404 */ +// 0x03 +// /* "source":391:406 */ +// rjump{tag_8} +// /* "source":286:368 */ +// tag_5: +// /* "source":314:354 */ +// pop +// pop +// /* "source":339:353 */ +// 0xaabbccddeeff +// /* "source":314:354 */ +// verbatimbytecode_506002 +// /* "source":286:368 */ +// rjump{tag_8} +// /* "source":248:263 */ +// tag_3: +// /* "source":250:261 */ +// pop +// pop +// /* "source":260:261 */ +// 0x01 +// /* "source":248:263 */ +// rjump{tag_8} +// /* "source":143:225 */ +// tag_1: +// /* "source":171:211 */ +// pop +// pop +// /* "source":196:210 */ +// 0xaabbccddeeff +// /* "source":171:211 */ +// verbatimbytecode_506000 +// /* "source":143:225 */ +// rjump{tag_8} diff --git a/test/libyul/objectCompiler/function_series.yul b/test/libyul/objectCompiler/function_series.yul index 7be2db96b923..fd5a5d6c05f6 100644 --- a/test/libyul/objectCompiler/function_series.yul +++ b/test/libyul/objectCompiler/function_series.yul @@ -11,7 +11,9 @@ object "Contract" { } // ==== +// EVMVersion: >=shanghai // optimizationPreset: none +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":33:48 */ diff --git a/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul b/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul index 5eb079db18d0..4a29c1498d0e 100644 --- a/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul +++ b/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul @@ -64,7 +64,9 @@ object "A" { } } // ==== +// EVMVersion: >=constantinople // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // sstore(calldataload(sub(shl(0xff, 0x01), shl(0x7f, 0x01))), calldataload(0x01)) @@ -102,6 +104,3 @@ object "A" { // sstore(calldataload(sub(shl(0xff, 0x01), shl(0x7f, 0x01))), calldataload(0x01)) // stop // } -// Bytecode: 6001356001607f1b600160ff1b03355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH1 0x1 PUSH1 0x7F SHL PUSH1 0x1 PUSH1 0xFF SHL SUB CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: :::-:0;;;;;;;;;;; diff --git a/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul index 74574be13c3f..9bd6413c9d3b 100644 --- a/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul @@ -64,7 +64,9 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "A.sol":10:20 */ @@ -109,6 +111,3 @@ object "A" { // sstore(calldataload(0x00), calldataload(0x01)) // stop // } -// Bytecode: 6001355f355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 10:10::-:0;-1:-1;10:10;-1:-1;10:10;-1:-1 diff --git a/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul index aa20ac6799b1..0248d61f7bc4 100644 --- a/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul @@ -50,7 +50,9 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":83:84 */ @@ -158,6 +160,3 @@ object "A" { // /* "source":938:1034 */ // stop // } -// Bytecode: 6001355f355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 83:1:0:-:0;70:15;66:1;53:15;46:40;22:80 diff --git a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul index 9b63bdc1b12c..10fcc202ea78 100644 --- a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul @@ -69,7 +69,9 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "A.sol":10:20 */ @@ -146,6 +148,3 @@ object "A" { // /* "source":1674:1770 */ // stop // } -// Bytecode: 6001355f355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 10:10::-:0;-1:-1;10:10;-1:-1;10:10;-1:-1 diff --git a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul index d288503babbf..533abbdd87c0 100644 --- a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul +++ b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul @@ -56,7 +56,9 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":83:84 */ @@ -164,6 +166,3 @@ object "A" { // /* "source":938:1034 */ // stop // } -// Bytecode: 6001355f355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 83:1:0:-:0;70:15;66:1;53:15;46:40;22:80 diff --git a/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul b/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul index e14b010083cb..c1bd855ad52b 100644 --- a/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul +++ b/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul @@ -95,7 +95,10 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // sstore(calldataload(0x00), calldataload(dataOffset(sub_0))) @@ -161,6 +164,3 @@ object "A" { // stop // data_257dd53638d790f0311f866044a2856def338f9a4d22fce0bdeed5b2d53851a9 307862626262 // } -// Bytecode: 6008355f355500fe6008355f355500fe6008355f355500fe6008355f355500fe6008355f355500fe30786262 -// Opcodes: PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID ADDRESS PUSH25 0x62620000000000000000000000000000000000000000000000 -// SourceMappings: :::-:0;;;;; diff --git a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul index c6fd0ac80527..e77506c30fbd 100644 --- a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul +++ b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul @@ -7,6 +7,9 @@ object "a" { ) } } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":143:185 */ diff --git a/test/libyul/objectCompiler/jump_tags.yul b/test/libyul/objectCompiler/jump_tags.yul index 0d1f1ff791ab..9261c7765653 100644 --- a/test/libyul/objectCompiler/jump_tags.yul +++ b/test/libyul/objectCompiler/jump_tags.yul @@ -12,6 +12,7 @@ object "Contract" { // ==== // optimizationPreset: none +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":33:54 */ diff --git a/test/libyul/objectCompiler/leading_and_trailing_dots.yul b/test/libyul/objectCompiler/leading_and_trailing_dots.yul index 13c95235571e..08dd970211ba 100644 --- a/test/libyul/objectCompiler/leading_and_trailing_dots.yul +++ b/test/libyul/objectCompiler/leading_and_trailing_dots.yul @@ -12,6 +12,10 @@ } g(2) } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy +// outputs: Assembly // ---- // Assembly: // /* "source":53:54 */ @@ -23,20 +27,3 @@ // /* "source":134:138 */ // tag_1 // jump // in -// /* "source":149:181 */ -// tag_2: -// /* "source":177:178 */ -// 0x00 -// /* "source":175:179 */ -// tag_2 -// jump // in -// /* "source":190:222 */ -// tag_3: -// /* "source":218:219 */ -// 0x00 -// /* "source":216:220 */ -// tag_3 -// jump // in -// Bytecode: 60025b5f6002565b5f6007565b5f600c56 -// Opcodes: PUSH1 0x2 JUMPDEST PUSH0 PUSH1 0x2 JUMP JUMPDEST PUSH0 PUSH1 0x7 JUMP JUMPDEST PUSH0 PUSH1 0xC JUMP -// SourceMappings: 53:1:0:-:0;108:32;136:1;134:4;:::i;149:32::-;177:1;175:4;:::i;190:32::-;218:1;216:4;:::i diff --git a/test/libyul/objectCompiler/linkersymbol.yul b/test/libyul/objectCompiler/linkersymbol.yul index 91a456461f00..cab45afa745f 100644 --- a/test/libyul/objectCompiler/linkersymbol.yul +++ b/test/libyul/objectCompiler/linkersymbol.yul @@ -2,20 +2,15 @@ object "a" { code { let addr := linkersymbol("contract/test.sol:L") mstore(128, shl(227, 0x18530aaf)) - let success := call(gas(), addr, 0, 128, 4, 128, 0) + sstore(0, balance(addr)) } } +// ==== +// EVMVersion: >=shanghai +// outputs: Assembly // ---- // Assembly: -// /* "source":190:191 */ -// 0x00 -// /* "source":185:188 */ -// 0x80 -// /* "source":182:183 */ -// 0x04 // /* "source":58:93 */ -// dup2 -// dup4 // linkerSymbol("f919ba91ac99f96129544b80b9516b27a80e376b9dc693819d0b18b7e0395612") // /* "source":127:137 */ // 0x18530aaf @@ -23,15 +18,15 @@ object "a" { // 0xe3 // /* "source":118:138 */ // shl +// /* "source":113:116 */ +// 0x80 // /* "source":106:139 */ -// dup4 // mstore -// /* "source":161:166 */ -// gas -// /* "source":156:192 */ -// call -// /* "source":152:193 */ +// /* "source":162:175 */ +// balance +// /* "source":159:160 */ +// 0x00 +// /* "source":152:176 */ +// sstore +// /* "source":22:192 */ // stop -// Bytecode: 5f6080600481837300000000000000000000000000000000000000006318530aaf60e31b83525af100 -// Opcodes: PUSH0 PUSH1 0x80 PUSH1 0x4 DUP2 DUP4 PUSH20 0x0 PUSH4 0x18530AAF PUSH1 0xE3 SHL DUP4 MSTORE GAS CALL STOP -// SourceMappings: 190:1:0:-:0;185:3;182:1;58:35;;;127:10;122:3;118:20;106:33;;161:5;156:36;152:41 diff --git a/test/libyul/objectCompiler/long_object_name.yul b/test/libyul/objectCompiler/long_object_name.yul index f75260224005..a1f1c7a63aea 100644 --- a/test/libyul/objectCompiler/long_object_name.yul +++ b/test/libyul/objectCompiler/long_object_name.yul @@ -7,7 +7,10 @@ object "t" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":56:169 */ @@ -24,6 +27,3 @@ object "t" { // /* "source":317:324 */ // stop // } -// Bytecode: 60015f5500fe -// Opcodes: PUSH1 0x1 PUSH0 SSTORE STOP INVALID -// SourceMappings: 56:113:0:-:0;53:1;46:124;22:164 diff --git a/test/libyul/objectCompiler/manySubObjects.yul b/test/libyul/objectCompiler/manySubObjects.yul index c046b182ff21..c4879f2107ad 100644 --- a/test/libyul/objectCompiler/manySubObjects.yul +++ b/test/libyul/objectCompiler/manySubObjects.yul @@ -134,6 +134,10 @@ object "root" { } } } +// ==== +// EVMVersion: >=shanghai +// outputs: Assembly +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":59:75 */ @@ -470,6 +474,3 @@ object "root" { // stop // } // } -// Bytecode: 61005c5f55600b600155600660025560066003556006600455600660055560066006556006600755600660085560066009556006600a556006600b556006600c556006600d556006600e556006600f556006601055600c60115500fe -// Opcodes: PUSH2 0x5C PUSH0 SSTORE PUSH1 0xB PUSH1 0x1 SSTORE PUSH1 0x6 PUSH1 0x2 SSTORE PUSH1 0x6 PUSH1 0x3 SSTORE PUSH1 0x6 PUSH1 0x4 SSTORE PUSH1 0x6 PUSH1 0x5 SSTORE PUSH1 0x6 PUSH1 0x6 SSTORE PUSH1 0x6 PUSH1 0x7 SSTORE PUSH1 0x6 PUSH1 0x8 SSTORE PUSH1 0x6 PUSH1 0x9 SSTORE PUSH1 0x6 PUSH1 0xA SSTORE PUSH1 0x6 PUSH1 0xB SSTORE PUSH1 0x6 PUSH1 0xC SSTORE PUSH1 0x6 PUSH1 0xD SSTORE PUSH1 0x6 PUSH1 0xE SSTORE PUSH1 0x6 PUSH1 0xF SSTORE PUSH1 0x6 PUSH1 0x10 SSTORE PUSH1 0xC PUSH1 0x11 SSTORE STOP INVALID -// SourceMappings: 59:16:0:-:0;56:1;49:27;99:13;96:1;89:24;136:13;133:1;126:24;173:13;170:1;163:24;210:13;207:1;200:24;247:13;244:1;237:24;284:13;281:1;274:24;321:13;318:1;311:24;358:13;355:1;348:24;395:13;392:1;385:24;433:13;429:2;422:25;471:13;467:2;460:25;509:13;505:2;498:25;547:13;543:2;536:25;585:13;581:2;574:25;623:13;619:2;612:25;661:13;657:2;650:25;699:14;695:2;688:26;25:705 diff --git a/test/libyul/objectCompiler/metadata.yul b/test/libyul/objectCompiler/metadata.yul index 4f8cda7a4c49..3787710e644c 100644 --- a/test/libyul/objectCompiler/metadata.yul +++ b/test/libyul/objectCompiler/metadata.yul @@ -19,6 +19,9 @@ object "A" { data ".metadata" "M2" data "x" "Hello, World2!" } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":55:68 */ diff --git a/test/libyul/objectCompiler/namedObject.yul b/test/libyul/objectCompiler/namedObject.yul index 06539dd89373..d236f9ba0efd 100644 --- a/test/libyul/objectCompiler/namedObject.yul +++ b/test/libyul/objectCompiler/namedObject.yul @@ -1,10 +1,10 @@ object "a" { code {} } +// ==== +// EVMVersion: >=constantinople +// outputs: Assembly // ---- // Assembly: // /* "source":22:29 */ // stop -// Bytecode: 00 -// Opcodes: STOP -// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/namedObjectCode.yul b/test/libyul/objectCompiler/namedObjectCode.yul index f18535d71189..e5d16be3e442 100644 --- a/test/libyul/objectCompiler/namedObjectCode.yul +++ b/test/libyul/objectCompiler/namedObjectCode.yul @@ -1,6 +1,9 @@ object "a" { code { sstore(0, 1) } } +// ==== +// EVMVersion: >=shanghai +// outputs: Assembly // ---- // Assembly: // /* "source":36:37 */ @@ -11,6 +14,3 @@ object "a" { // sstore // /* "source":22:42 */ // stop -// Bytecode: 60015f5500 -// Opcodes: PUSH1 0x1 PUSH0 SSTORE STOP -// SourceMappings: 36:1:0:-:0;33;26:12;22:20 diff --git a/test/libyul/objectCompiler/nested_optimizer.yul b/test/libyul/objectCompiler/nested_optimizer.yul index ae06509429a5..38b78e6dcae6 100644 --- a/test/libyul/objectCompiler/nested_optimizer.yul +++ b/test/libyul/objectCompiler/nested_optimizer.yul @@ -15,7 +15,9 @@ object "a" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":58:59 */ @@ -40,6 +42,3 @@ object "a" { // /* "source":101:155 */ // stop // } -// Bytecode: 5f80355500fe -// Opcodes: PUSH0 DUP1 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 58:1:0:-:0;41:15;;34:26;22:46 diff --git a/test/libyul/objectCompiler/prune_unreachable_function_non_returning.yul b/test/libyul/objectCompiler/prune_unreachable_function_non_returning.yul new file mode 100644 index 000000000000..9c0a0acdc779 --- /dev/null +++ b/test/libyul/objectCompiler/prune_unreachable_function_non_returning.yul @@ -0,0 +1,29 @@ +object "Contract" { + code { + f() + g() + + function f() { revert(0, 0) } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":53:56 */ +// tag_1 +// jump // in +// /* "source":91:128 */ +// tag_1: +// /* "source":124:125 */ +// 0x00 +// /* "source":114:126 */ +// dup1 +// revert +// Bytecode: 6003565b5f80fd +// Opcodes: PUSH1 0x3 JUMP JUMPDEST PUSH0 DUP1 REVERT +// SourceMappings: 53:3:0:-:0;:::i;91:37::-;124:1;114:12; diff --git a/test/libyul/objectCompiler/prune_unreachable_function_recursion.yul b/test/libyul/objectCompiler/prune_unreachable_function_recursion.yul new file mode 100644 index 000000000000..1000cfd31f44 --- /dev/null +++ b/test/libyul/objectCompiler/prune_unreachable_function_recursion.yul @@ -0,0 +1,27 @@ +object "Contract" { + code { + f() + g() + + function f() { f() } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":53:56 */ +// tag_1 +// jump // in +// /* "source":91:119 */ +// tag_1: +// /* "source":114:117 */ +// tag_1 +// jump // in +// Bytecode: 6003565b600356 +// Opcodes: PUSH1 0x3 JUMP JUMPDEST PUSH1 0x3 JUMP +// SourceMappings: 53:3:0:-:0;:::i;91:28::-;114:3;:::i diff --git a/test/libyul/objectCompiler/prune_unreferenced_function.yul b/test/libyul/objectCompiler/prune_unreferenced_function.yul new file mode 100644 index 000000000000..88010bd72555 --- /dev/null +++ b/test/libyul/objectCompiler/prune_unreferenced_function.yul @@ -0,0 +1,35 @@ +object "Contract" { + code { + g() + + function f() { mstore(0, 3) } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":41:44 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "source":29:98 */ +// stop +// /* "source":55:92 */ +// tag_1: +// /* "source":88:89 */ +// 0x02 +// /* "source":85:86 */ +// 0x00 +// /* "source":78:90 */ +// mstore +// /* "source":55:92 */ +// jump // out +// Bytecode: 60056007565b005b60025f5256 +// Opcodes: PUSH1 0x5 PUSH1 0x7 JUMP JUMPDEST STOP JUMPDEST PUSH1 0x2 PUSH0 MSTORE JUMP +// SourceMappings: 41:3:0:-:0;;:::i;:::-;29:69;55:37;88:1;85;78:12;55:37::o diff --git a/test/libyul/objectCompiler/simple.yul b/test/libyul/objectCompiler/simple.yul index fb2339cebb09..3af2c0f6a05d 100644 --- a/test/libyul/objectCompiler/simple.yul +++ b/test/libyul/objectCompiler/simple.yul @@ -1,6 +1,9 @@ { sstore(0, 1) } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":41:42 */ diff --git a/test/libyul/objectCompiler/simple_optimizer.yul b/test/libyul/objectCompiler/simple_optimizer.yul index cc630758957a..db386a1f1318 100644 --- a/test/libyul/objectCompiler/simple_optimizer.yul +++ b/test/libyul/objectCompiler/simple_optimizer.yul @@ -5,7 +5,9 @@ sstore(add(x, 0), z) } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":63:64 */ @@ -17,6 +19,3 @@ // sstore // /* "source":27:73 */ // stop -// Bytecode: 5f80355500 -// Opcodes: PUSH0 DUP1 CALLDATALOAD SSTORE STOP -// SourceMappings: 63:1:0:-:0;46:15;;39:26;27:46 diff --git a/test/libyul/objectCompiler/smoke.yul b/test/libyul/objectCompiler/smoke.yul index 82aea42f5299..06736baa8710 100644 --- a/test/libyul/objectCompiler/smoke.yul +++ b/test/libyul/objectCompiler/smoke.yul @@ -1,5 +1,8 @@ { } +// ==== +// EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":27:34 */ diff --git a/test/libyul/objectCompiler/sourceLocations.yul b/test/libyul/objectCompiler/sourceLocations.yul index d9f1d84fcb4f..756260259b2c 100644 --- a/test/libyul/objectCompiler/sourceLocations.yul +++ b/test/libyul/objectCompiler/sourceLocations.yul @@ -28,6 +28,9 @@ object "a" { data "data1" "Hello, World!" } } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "abc.sol":0:2 */ diff --git a/test/libyul/objectCompiler/subObject.yul b/test/libyul/objectCompiler/subObject.yul index a47c4feda27f..c10cbaac1407 100644 --- a/test/libyul/objectCompiler/subObject.yul +++ b/test/libyul/objectCompiler/subObject.yul @@ -4,6 +4,9 @@ object "a" { data "str" "Hello, World!" object "sub" { code { sstore(0, 1) } } } +// ==== +// EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/subObjectAccess.yul b/test/libyul/objectCompiler/subObjectAccess.yul index b18c902db60f..1ef30838f9a8 100644 --- a/test/libyul/objectCompiler/subObjectAccess.yul +++ b/test/libyul/objectCompiler/subObjectAccess.yul @@ -65,6 +65,9 @@ object "A" { } } } +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":57:72 */ diff --git a/test/libyul/objectCompiler/subSubObject.yul b/test/libyul/objectCompiler/subSubObject.yul index a4511324e901..2aa89592be5a 100644 --- a/test/libyul/objectCompiler/subSubObject.yul +++ b/test/libyul/objectCompiler/subSubObject.yul @@ -10,6 +10,9 @@ object "a" { } } } +// ==== +// EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/verbatim_bug.yul b/test/libyul/objectCompiler/verbatim_bug.yul index 14a1c02b1f33..892ec13fae32 100644 --- a/test/libyul/objectCompiler/verbatim_bug.yul +++ b/test/libyul/objectCompiler/verbatim_bug.yul @@ -23,7 +23,10 @@ object "a" { } } // ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":65:66 */ @@ -119,6 +122,3 @@ object "a" { // sstore // /* "source":108:406 */ // stop -// Bytecode: 5f80548015603e578060011460365780600214602657600314601f575f55005b5060035f55005b505065aabbccddeeff5060025f55005b505060015f55005b505065aabbccddeeff5060005f5500 -// Opcodes: PUSH0 DUP1 SLOAD DUP1 ISZERO PUSH1 0x3E JUMPI DUP1 PUSH1 0x1 EQ PUSH1 0x36 JUMPI DUP1 PUSH1 0x2 EQ PUSH1 0x26 JUMPI PUSH1 0x3 EQ PUSH1 0x1F JUMPI PUSH0 SSTORE STOP JUMPDEST POP PUSH1 0x3 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH6 0xAABBCCDDEEFF POP PUSH1 0x2 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH1 0x1 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH6 0xAABBCCDDEEFF POP PUSH1 0x0 PUSH0 SSTORE STOP -// SourceMappings: 65:1:0:-:0;59:8;;133:92;;;;238:25;243:4;238:25;;;276:92;281:4;276:92;;;386:4;381:25;;;426:1;419:17;108:298;391:15;393:11;403:1;426;419:17;108:298;286:82;314:40;;339:14;314:40;426:1;419:17;108:298;248:15;250:11;;260:1;426;419:17;108:298;143:82;171:40;;196:14;171:40;426:1;419:17;108:298 diff --git a/test/libyul/yulControlFlowGraph/ambiguous_names.yul b/test/libyul/yulControlFlowGraph/ambiguous_names.yul index fabeda45b80f..e7aaeadbba3d 100644 --- a/test/libyul/yulControlFlowGraph/ambiguous_names.yul +++ b/test/libyul/yulControlFlowGraph/ambiguous_names.yul @@ -14,6 +14,8 @@ function b() {} } } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulControlFlowGraph/complex.yul b/test/libyul/yulControlFlowGraph/complex.yul index 4001a93092e1..718ea6770979 100644 --- a/test/libyul/yulControlFlowGraph/complex.yul +++ b/test/libyul/yulControlFlowGraph/complex.yul @@ -43,6 +43,8 @@ } pop(f(1,2)) } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulControlFlowGraph/eof/function.yul b/test/libyul/yulControlFlowGraph/eof/function.yul new file mode 100644 index 000000000000..5f5ef934bd94 --- /dev/null +++ b/test/libyul/yulControlFlowGraph/eof/function.yul @@ -0,0 +1,67 @@ +{ + function f(a, b) -> r { + let x := add(a,b) + r := sub(x,a) + } + function g() { + sstore(0x01, 0x0101) + } + function h(x) { + h(f(x, 0)) + g() + } + function i() -> v, w { + v := 0x0202 + w := 0x0303 + } + let x, y := i() + h(x) + h(y) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// digraph CFG { +// nodesep=0.7; +// node[shape=box]; +// +// Entry [label="Entry"]; +// Entry -> Block0; +// Block0 [label="\ +// i: [ ] => [ TMP[i, 0] TMP[i, 1] ]\l\ +// Assignment(x, y): [ TMP[i, 0] TMP[i, 1] ] => [ x y ]\l\ +// h: [ x ] => [ ]\l\ +// "]; +// Block0Exit [label="Terminated"]; +// Block0 -> Block0Exit; +// +// FunctionEntry_f_1 [label="function f(a, b) -> r"]; +// FunctionEntry_f_1 -> Block1; +// Block1 [label="\ +// add: [ b a ] => [ TMP[add, 0] ]\l\ +// Assignment(x): [ TMP[add, 0] ] => [ x ]\l\ +// sub: [ a x ] => [ TMP[sub, 0] ]\l\ +// Assignment(r): [ TMP[sub, 0] ] => [ r ]\l\ +// "]; +// Block1Exit [label="FunctionReturn[f]"]; +// Block1 -> Block1Exit; +// +// FunctionEntry_h_2 [label="function h(x)"]; +// FunctionEntry_h_2 -> Block2; +// Block2 [label="\ +// f: [ 0x00 x ] => [ TMP[f, 0] ]\l\ +// h: [ TMP[f, 0] ] => [ ]\l\ +// "]; +// Block2Exit [label="Terminated"]; +// Block2 -> Block2Exit; +// +// FunctionEntry_i_3 [label="function i() -> v, w"]; +// FunctionEntry_i_3 -> Block3; +// Block3 [label="\ +// Assignment(v): [ 0x0202 ] => [ v ]\l\ +// Assignment(w): [ 0x0303 ] => [ w ]\l\ +// "]; +// Block3Exit [label="FunctionReturn[i]"]; +// Block3 -> Block3Exit; +// +// } diff --git a/test/libyul/yulControlFlowGraph/function.yul b/test/libyul/yulControlFlowGraph/function.yul index 90c4b380e48c..0e3691a426cd 100644 --- a/test/libyul/yulControlFlowGraph/function.yul +++ b/test/libyul/yulControlFlowGraph/function.yul @@ -18,6 +18,8 @@ h(x) h(y) } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; @@ -44,30 +46,22 @@ // Block1Exit [label="FunctionReturn[f]"]; // Block1 -> Block1Exit; // -// FunctionEntry_g_2 [label="function g()"]; -// FunctionEntry_g_2 -> Block2; +// FunctionEntry_h_2 [label="function h(x)"]; +// FunctionEntry_h_2 -> Block2; // Block2 [label="\ -// sstore: [ 0x0101 0x01 ] => [ ]\l\ -// "]; -// Block2Exit [label="FunctionReturn[g]"]; -// Block2 -> Block2Exit; -// -// FunctionEntry_h_3 [label="function h(x)"]; -// FunctionEntry_h_3 -> Block3; -// Block3 [label="\ // f: [ RET[f] 0x00 x ] => [ TMP[f, 0] ]\l\ // h: [ TMP[f, 0] ] => [ ]\l\ // "]; -// Block3Exit [label="Terminated"]; -// Block3 -> Block3Exit; +// Block2Exit [label="Terminated"]; +// Block2 -> Block2Exit; // -// FunctionEntry_i_4 [label="function i() -> v, w"]; -// FunctionEntry_i_4 -> Block4; -// Block4 [label="\ +// FunctionEntry_i_3 [label="function i() -> v, w"]; +// FunctionEntry_i_3 -> Block3; +// Block3 [label="\ // Assignment(v): [ 0x0202 ] => [ v ]\l\ // Assignment(w): [ 0x0303 ] => [ w ]\l\ // "]; -// Block4Exit [label="FunctionReturn[i]"]; -// Block4 -> Block4Exit; +// Block3Exit [label="FunctionReturn[i]"]; +// Block3 -> Block3Exit; // // } diff --git a/test/libyul/yulControlFlowGraph/leave.yul b/test/libyul/yulControlFlowGraph/leave.yul index 4d0a63af4805..d6f475513b4d 100644 --- a/test/libyul/yulControlFlowGraph/leave.yul +++ b/test/libyul/yulControlFlowGraph/leave.yul @@ -11,6 +11,8 @@ pop(f(0,1)) } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulInterpreterTests/and_create.yul b/test/libyul/yulInterpreterTests/and_create.yul index da962c3c0b04..5d8cd6cfde8d 100644 --- a/test/libyul/yulInterpreterTests/and_create.yul +++ b/test/libyul/yulInterpreterTests/and_create.yul @@ -4,6 +4,8 @@ let b := and(u160max, create(0, u160max, 0)) mstore(0, eq(a, b)) } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // CREATE(0, 0, 0) diff --git a/test/libyul/yulInterpreterTests/and_create2.yul b/test/libyul/yulInterpreterTests/and_create2.yul index 0b83d818f087..c076c1203e11 100644 --- a/test/libyul/yulInterpreterTests/and_create2.yul +++ b/test/libyul/yulInterpreterTests/and_create2.yul @@ -6,6 +6,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // CREATE2(0, 0, 0, 0) diff --git a/test/libyul/yulInterpreterTests/create2.yul b/test/libyul/yulInterpreterTests/create2.yul index b7484f5db8de..ad6eb5383796 100644 --- a/test/libyul/yulInterpreterTests/create2.yul +++ b/test/libyul/yulInterpreterTests/create2.yul @@ -5,6 +5,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // CREATE2(0, 0, 32, 32) diff --git a/test/libyul/yulInterpreterTests/datacopy.yul b/test/libyul/yulInterpreterTests/datacopy.yul index ce5b6ce5c53a..61a3259a7c96 100644 --- a/test/libyul/yulInterpreterTests/datacopy.yul +++ b/test/libyul/yulInterpreterTests/datacopy.yul @@ -8,6 +8,8 @@ object "main" } object "sub" { code { sstore(0, 1) } } } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/dataoffset.yul b/test/libyul/yulInterpreterTests/dataoffset.yul index f5a9aeb12f34..366ceb4bd273 100644 --- a/test/libyul/yulInterpreterTests/dataoffset.yul +++ b/test/libyul/yulInterpreterTests/dataoffset.yul @@ -6,6 +6,8 @@ object "main" } object "sub" { code { sstore(0, 1) } } } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/datasize.yul b/test/libyul/yulInterpreterTests/datasize.yul index ff80edee7c94..f03d7083699f 100644 --- a/test/libyul/yulInterpreterTests/datasize.yul +++ b/test/libyul/yulInterpreterTests/datasize.yul @@ -6,6 +6,8 @@ object "main" } object "sub" { code { sstore(0, 1) } } } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/external_call_to_self.yul b/test/libyul/yulInterpreterTests/external_call_to_self.yul index 3f5c887b4aeb..b2d69086a54f 100644 --- a/test/libyul/yulInterpreterTests/external_call_to_self.yul +++ b/test/libyul/yulInterpreterTests/external_call_to_self.yul @@ -11,6 +11,7 @@ } // ==== // simulateExternalCall: true +// bytecodeFormat: legacy // ---- // Trace: // CALL(153, 0x11111111, 0, 64, 32, 256, 32) diff --git a/test/libyul/yulInterpreterTests/external_call_unexecuted.yul b/test/libyul/yulInterpreterTests/external_call_unexecuted.yul index 0a5458b47e2f..93bb9ec03d7b 100644 --- a/test/libyul/yulInterpreterTests/external_call_unexecuted.yul +++ b/test/libyul/yulInterpreterTests/external_call_unexecuted.yul @@ -2,6 +2,8 @@ let x := call(gas(), 0x45, 0x5, 0, 0x20, 0x30, 0x20) sstore(0x64, x) } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // CALL(153, 69, 5, 0, 32, 48, 32) diff --git a/test/libyul/yulInterpreterTests/external_callcode_unexecuted.yul b/test/libyul/yulInterpreterTests/external_callcode_unexecuted.yul index 5245d7443a93..5d0da5c0633e 100644 --- a/test/libyul/yulInterpreterTests/external_callcode_unexecuted.yul +++ b/test/libyul/yulInterpreterTests/external_callcode_unexecuted.yul @@ -2,6 +2,8 @@ let x := callcode(gas(), 0x45, 0x5, 0, 0x20, 0x30, 0x20) sstore(100, x) } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // CALLCODE(153, 69, 5, 0, 32, 48, 32) diff --git a/test/libyul/yulInterpreterTests/external_delegatecall_unexecuted.yul b/test/libyul/yulInterpreterTests/external_delegatecall_unexecuted.yul index a827181fca2c..3e84df570931 100644 --- a/test/libyul/yulInterpreterTests/external_delegatecall_unexecuted.yul +++ b/test/libyul/yulInterpreterTests/external_delegatecall_unexecuted.yul @@ -2,6 +2,8 @@ let x := delegatecall(gas(), 0x45, 0, 0x20, 0x30, 0x20) sstore(100, x) } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // DELEGATECALL(153, 69, 0, 32, 48, 32) diff --git a/test/libyul/yulInterpreterTests/external_staticcall_unexecuted.yul b/test/libyul/yulInterpreterTests/external_staticcall_unexecuted.yul index 66ea146a06ab..664692bad565 100644 --- a/test/libyul/yulInterpreterTests/external_staticcall_unexecuted.yul +++ b/test/libyul/yulInterpreterTests/external_staticcall_unexecuted.yul @@ -4,6 +4,7 @@ } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // Trace: // STATICCALL(153, 69, 0, 32, 48, 32) diff --git a/test/libyul/yulInterpreterTests/long_obect_name.yul b/test/libyul/yulInterpreterTests/long_object_name.yul similarity index 89% rename from test/libyul/yulInterpreterTests/long_obect_name.yul rename to test/libyul/yulInterpreterTests/long_object_name.yul index ede304029997..69b7acbb2bf9 100644 --- a/test/libyul/yulInterpreterTests/long_obect_name.yul +++ b/test/libyul/yulInterpreterTests/long_object_name.yul @@ -13,6 +13,8 @@ object "t" { } } } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul b/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul index ec9ca2fe6437..4386711a1c26 100644 --- a/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul +++ b/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul @@ -3,6 +3,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // CALL(0, 0, 0, 0, 0, 0, 0) diff --git a/test/libyul/yulInterpreterTests/side_effect_free.yul b/test/libyul/yulInterpreterTests/side_effect_free.yul index adedd299f579..d68d57364b2b 100644 --- a/test/libyul/yulInterpreterTests/side_effect_free.yul +++ b/test/libyul/yulInterpreterTests/side_effect_free.yul @@ -14,6 +14,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/zero_length_reads.yul b/test/libyul/yulInterpreterTests/zero_length_reads.yul index 661db49ffbb6..68cae1b92129 100644 --- a/test/libyul/yulInterpreterTests/zero_length_reads.yul +++ b/test/libyul/yulInterpreterTests/zero_length_reads.yul @@ -18,6 +18,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // RETURNDATACOPY(0, 1, 0) diff --git a/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul b/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul index 0d0f92420e30..c9143d7918f5 100644 --- a/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul +++ b/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul @@ -18,6 +18,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // RETURNDATACOPY(0, 1, 0) diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul index ac4ed1b0545e..9c569811e795 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul @@ -1,17 +1,17 @@ { let a := 1 - let b := codesize() - for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) } { - mstore(1, codesize()) + let b := calldataload(0) + for { } lt(1, calldataload(0)) { mstore(1, calldataload(0)) a := add(a, calldataload(0)) } { + mstore(1, calldataload(0)) } - mstore(1, codesize()) + mstore(1, calldataload(0)) } // ---- // step: commonSubexpressionEliminator // // { // let a := 1 -// let b := codesize() +// let b := calldataload(0) // for { } // lt(1, b) // { diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul index f480bec9e1ae..e4ad176e846f 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul @@ -10,6 +10,8 @@ object "AccessControlDefaultAdminRules4233_14" { data "AccessControlDefaultAdminRules4233_14_deployed" "AccessControlDefaultAdminRules4233_14_deployed" } +// ==== +// bytecodeFormat: legacy // ---- // step: commonSubexpressionEliminator // diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul index ed8916e63723..210b697f46a4 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul @@ -2,6 +2,8 @@ let a := gas() let b := gas() } +// ==== +// bytecodeFormat: legacy // ---- // step: commonSubexpressionEliminator // diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul index c8c4e4e1388a..98645c653739 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul @@ -14,6 +14,8 @@ object "main" { } data "abc" "Hello, World!" } +// ==== +// bytecodeFormat: legacy // ---- // step: commonSubexpressionEliminator // diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul index c64fc93f9833..ad0168027011 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul @@ -1,11 +1,11 @@ { - let a := mul(1, codesize()) - let b := mul(1, codesize()) + let a := mul(1, calldataload(0)) + let b := mul(1, calldataload(0)) } // ---- // step: commonSubexpressionEliminator // // { -// let a := mul(1, codesize()) +// let a := mul(1, calldataload(0)) // let b := a // } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul index 35891b459939..d26901c230cc 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul @@ -1,11 +1,11 @@ { function f() -> x { - // can re-use x + // can reuse x let y := 0 mstore(y, 7) } let a - // can re-use a + // can reuse a let b := 0 sstore(a, b) } diff --git a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul b/test/libyul/yulOptimizerTests/disambiguator/function_call.yul similarity index 100% rename from test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul rename to test/libyul/yulOptimizerTests/disambiguator/function_call.yul diff --git a/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul b/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul index f0db2af1b220..e2612756e7a5 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul @@ -4,6 +4,8 @@ object "A" { } data 'abc' "1234" } +// ==== +// bytecodeFormat: legacy // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/equalStoreEliminator/branching.yul b/test/libyul/yulOptimizerTests/equalStoreEliminator/branching.yul index 63f0d38e43fe..2f382cab0726 100644 --- a/test/libyul/yulOptimizerTests/equalStoreEliminator/branching.yul +++ b/test/libyul/yulOptimizerTests/equalStoreEliminator/branching.yul @@ -4,7 +4,7 @@ sstore(a, b) if calldataload(32) { sstore(a, b) - pop(staticcall(0, 0, 0, 0, 0, 0)) + pop(sload(a)) sstore(a, b) } sstore(a, b) @@ -18,8 +18,5 @@ // let a := calldataload(0) // let b := 20 // sstore(a, b) -// if calldataload(32) -// { -// pop(staticcall(0, 0, 0, 0, 0, 0)) -// } +// if calldataload(32) { pop(sload(a)) } // } diff --git a/test/libyul/yulOptimizerTests/equalStoreEliminator/functionbody.yul b/test/libyul/yulOptimizerTests/equalStoreEliminator/functionbody.yul index 68839721cd76..cc376652ee7b 100644 --- a/test/libyul/yulOptimizerTests/equalStoreEliminator/functionbody.yul +++ b/test/libyul/yulOptimizerTests/equalStoreEliminator/functionbody.yul @@ -10,7 +10,7 @@ } function g() { - pop(staticcall(0, 0, 0, 0, 0, 0)) + pop(sload(calldataload(0))) } function h(a_, b_) { @@ -21,7 +21,7 @@ } function i() { - pop(delegatecall(0, 0, 0, 0, 0, 0)) + sstore(calldataload(64), 42) } @@ -40,9 +40,7 @@ // g() // } // function g() -// { -// pop(staticcall(0, 0, 0, 0, 0, 0)) -// } +// { pop(sload(calldataload(0))) } // function h(a_, b_) // { // sstore(a_, b_) @@ -50,7 +48,5 @@ // sstore(a_, b_) // } // function i() -// { -// pop(delegatecall(0, 0, 0, 0, 0, 0)) -// } +// { sstore(calldataload(64), 42) } // } diff --git a/test/libyul/yulOptimizerTests/equalStoreEliminator/verbatim.yul b/test/libyul/yulOptimizerTests/equalStoreEliminator/verbatim.yul index fcaddd12134d..112d704e2711 100644 --- a/test/libyul/yulOptimizerTests/equalStoreEliminator/verbatim.yul +++ b/test/libyul/yulOptimizerTests/equalStoreEliminator/verbatim.yul @@ -4,7 +4,7 @@ sstore(a, b) if calldataload(32) { sstore(a, b) - pop(staticcall(0, 0, 0, 0, 0, 0)) + pop(sload(a)) verbatim_0i_0o("xyz") } sstore(a, b) @@ -20,7 +20,7 @@ // sstore(a, b) // if calldataload(32) // { -// pop(staticcall(0, 0, 0, 0, 0, 0)) +// pop(sload(a)) // verbatim_0i_0o("xyz") // } // sstore(a, b) diff --git a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul index 301f50c6ea27..4d3be77e8239 100644 --- a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul +++ b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul @@ -26,6 +26,8 @@ object "test" data 'A' "A" } +// ==== +// bytecodeFormat: legacy // ---- // step: equivalentFunctionCombiner // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul index a431c57a6c6c..e635ad5d4824 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul @@ -8,6 +8,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul index 3710cbebdf48..1f10c90adb7c 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul @@ -7,6 +7,8 @@ let b := and(0xffffffffffffffffffffffffffffffffffffffff, create(0, 0, 0x20)) sstore(a, b) } +// ==== +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul index 19d65dca4152..c73fea65c6e0 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul @@ -9,6 +9,8 @@ sstore(9, c) sstore(10, d) } +// ==== +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol b/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.yul similarity index 100% rename from test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol rename to test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.yul diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.sol b/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.yul similarity index 100% rename from test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.sol rename to test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.yul diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul index abd1b1743d32..d1e00802ffab 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul @@ -3,6 +3,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul index 9c3a5c8ba29e..6dc67840697d 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul @@ -5,6 +5,7 @@ } // ==== // EVMVersion: >byzantium +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read.yul index ee7464932d3a..3bc52009e5cc 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read.yul @@ -1,9 +1,7 @@ { revert(calldataload(0), 0) - revert(call(0,0,0,0,0,0,0), 0) calldatacopy(calldataload(1), calldataload(2), 0) return(calldataload(3), 0) - codecopy(calldataload(4), calldataload(5), sub(42,42)) } // ---- // step: expressionSimplifier @@ -12,10 +10,7 @@ // { // let _1 := 0 // revert(0, _1) -// pop(call(_1, _1, _1, _1, _1, _1, _1)) -// revert(0, _1) // calldatacopy(0, calldataload(2), _1) // return(0, _1) -// codecopy(0, calldataload(5), 0) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_call.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_call.yul new file mode 100644 index 000000000000..4764c6d5795d --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_call.yul @@ -0,0 +1,15 @@ +{ + revert(call(0,0,0,0,0,0,0), 0) +} +// ==== +// bytecodeFormat: legacy +// ---- +// step: expressionSimplifier +// +// { +// { +// let _1 := 0 +// pop(call(_1, _1, _1, _1, _1, _1, _1)) +// revert(0, _1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_codecopy.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_codecopy.yul new file mode 100644 index 000000000000..e3f1085e065c --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_codecopy.yul @@ -0,0 +1,13 @@ +{ + codecopy(calldataload(4), calldataload(5), sub(42,42)) +} +// ==== +// bytecodeFormat: legacy +// ---- +// step: expressionSimplifier +// +// { +// { +// codecopy(0, calldataload(5), 0) +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul b/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul index bcd6d0f7bba5..b362f1568c4a 100644 --- a/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul +++ b/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul @@ -9,6 +9,8 @@ object "main" { } data "abc" "Hello, World!" } +// ==== +// bytecodeFormat: legacy // ---- // step: expressionSplitter // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul index 99e92c183edc..cc2cae6f652e 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul @@ -20,6 +20,8 @@ sstore(0, f()) let x, y := g() } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul index 0e5aa9e130f5..1accb5cef647 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul @@ -7,6 +7,8 @@ } sstore(1, h(32)) } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul index 5650b580da5f..02a974784140 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul @@ -7,6 +7,8 @@ let z, $w } } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/outer_block.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/outer_block.yul index 023100cddee6..46c3cabb948a 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/outer_block.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/outer_block.yul @@ -3,6 +3,8 @@ let $x := 42 sstore(42, $x) } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul index 3b43bd534309..a510c65e96b1 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul @@ -14,6 +14,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one.yul index 50a9d64869f5..5566f97130af 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one.yul @@ -12,6 +12,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul index 706a46c6280c..42084c16efc4 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul @@ -12,6 +12,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/same_variable_in_lhs_and_rhs.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/same_variable_in_lhs_and_rhs.yul index e6a9379dfde2..95ede59faa94 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/same_variable_in_lhs_and_rhs.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/same_variable_in_lhs_and_rhs.yul @@ -5,6 +5,8 @@ let $z := 42 $z := f($z) } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul index e86619e464b2..39db59956535 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul @@ -23,6 +23,8 @@ g(0) h(1, 2, 3, 4) } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol b/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol rename to test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.yul diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul index 0e366e6d4090..af609eb60b61 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul @@ -3,6 +3,8 @@ let a := div(create(0, 0, 0), 0) mstore(0, a) } +// ==== +// bytecodeFormat: legacy // ---- // step: fullSimplify // diff --git a/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul b/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul index 38e5ab2108d7..1820f363c52f 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul @@ -6,6 +6,8 @@ } f(call(2, 0, 1, mod(x, 8), 1, 1, 1)) } +// ==== +// bytecodeFormat: legacy // ---- // step: fullSimplify // diff --git a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul index 8b26a7ba3723..94d4b14fffcf 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul @@ -1,3 +1,4 @@ +// TODO: Add EOF version of this contract and compare with legacy to see which optimizations are missed. /** * @title Library to validate AZTEC zero-knowledge proofs * @author Zachary Williamson, AZTEC @@ -230,6 +231,7 @@ } // ==== // EVMVersion: >=istanbul +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul b/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul index 6ebca20f5bbb..f0c54556a423 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul @@ -8,6 +8,7 @@ } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul b/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul index 078616bb3b7e..984d9a458d8c 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul @@ -8,6 +8,7 @@ } // ==== // EVMVersion: >=istanbul +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul b/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul index dd6cdc0e44c4..772ec67cfec8 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul @@ -18,6 +18,7 @@ } // ==== // EVMVersion: >byzantium +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/fullSuite/mcopy.sol b/test/libyul/yulOptimizerTests/fullSuite/mcopy.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullSuite/mcopy.sol rename to test/libyul/yulOptimizerTests/fullSuite/mcopy.yul diff --git a/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.sol b/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.sol rename to test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.yul diff --git a/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.sol b/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.sol rename to test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.yul diff --git a/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.sol b/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.sol rename to test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.yul diff --git a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul index 5fbe8d22e615..c7eb0a405b80 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul @@ -22,7 +22,7 @@ function foo_singlereturn_1(in_1, in_2) -> out { - extcodecopy(1,msize(),1,1) + mstore8(msize(), 42) } a := foo_singlereturn_0() @@ -60,5 +60,5 @@ // default { out := gcd(_b, mod(_a, _b)) } // } // function foo_singlereturn() -// { extcodecopy(1, msize(), 1, 1) } +// { mstore8(msize(), 42) } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul index 6f82ab27a6d8..9d893a7d3c5c 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul @@ -9,7 +9,7 @@ out1 := mload(32) out1 := sload(out1) out2 := add(out1, 1) - extcodecopy(out1, out2, 1, b) + calldatacopy(out2, out1, b) // to prevent foo from getting inlined if iszero(out1) { leave } } @@ -27,7 +27,7 @@ // { // out1 := sload(mload(32)) // out2 := add(out1, 1) -// extcodecopy(out1, out2, 1, b) +// calldatacopy(out2, out1, b) // if iszero(out1) { leave } // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul index b066d998bafe..f95e6f30dcc3 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul @@ -16,6 +16,8 @@ if iszero(out1) { leave } } } +// ==== +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/loadResolver/extstaticcall.yul b/test/libyul/yulOptimizerTests/loadResolver/extstaticcall.yul new file mode 100644 index 000000000000..b7b4de23b017 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/extstaticcall.yul @@ -0,0 +1,29 @@ +{ + let a := 0 + let b := 1 + let c := 2 + sstore(a, b) + mstore(900, 7) + let d := extstaticcall(10, 0, 200) + sstore(add(a, 1), mload(900)) + // Main test objective: replace this sload. + mstore(0, sload(a)) +} +// ==== +// EVMVersion: >=byzantium +// bytecodeFormat: >=EOFv1 +// ---- +// step: loadResolver +// +// { +// { +// let a := 0 +// let b := 1 +// sstore(a, b) +// let _1 := 7 +// mstore(900, _1) +// pop(extstaticcall(10, a, 200)) +// sstore(1, _1) +// mstore(a, b) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul index 18c818d15ec6..c67a0f875545 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul @@ -2,6 +2,8 @@ { for {} addmod(keccak256(0x0,create(0x0, 0x0, 0x0)), 0x0, 0x0) {} {} } +// ==== +// bytecodeFormat: legacy // ---- // step: loadResolver // diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_call_invalidation.yul similarity index 54% rename from test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul rename to test/libyul/yulOptimizerTests/loadResolver/memory_with_call_invalidation.yul index 840f19005b06..88d0ba64db73 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_call_invalidation.yul @@ -3,17 +3,9 @@ sstore(0, mload(2)) pop(call(0, 0, 0, 0, 0, 0, 0)) sstore(0, mload(2)) - - mstore(2, 10) - mstore8(calldataload(0), 4) - sstore(0, mload(2)) - - mstore(2, 10) - g() - sstore(0, mload(2)) - - function g() {} } +// ==== +// bytecodeFormat: legacy // ---- // step: loadResolver // @@ -27,11 +19,5 @@ // sstore(_5, _4) // pop(call(_5, _5, _5, _5, _5, _5, _5)) // sstore(_5, mload(_2)) -// let _17 := 10 -// mstore(_2, _17) -// mstore8(calldataload(_5), 4) -// sstore(_5, mload(_2)) -// mstore(_2, _17) -// sstore(_5, _17) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_extcall_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_extcall_invalidation.yul new file mode 100644 index 000000000000..55c131677f5a --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_extcall_invalidation.yul @@ -0,0 +1,22 @@ +{ + mstore(2, 9) + sstore(0, mload(2)) + pop(extcall(0, 0, 0, 0)) + sstore(0, mload(2)) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 9 +// mstore(2, _1) +// let _4 := _1 +// let _5 := 0 +// sstore(_5, _4) +// pop(extcall(_5, _5, _5, _5)) +// sstore(_5, _1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_function_call_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_function_call_invalidation.yul new file mode 100644 index 000000000000..7181d553ada7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_function_call_invalidation.yul @@ -0,0 +1,17 @@ +{ + mstore(2, 10) + g() + sstore(0, mload(2)) + + function g() {} +} +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 10 +// mstore(2, _1) +// sstore(0, _1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_mstore_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_mstore_invalidation.yul new file mode 100644 index 000000000000..3179ef3916ea --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_mstore_invalidation.yul @@ -0,0 +1,19 @@ +{ + mstore(2, 10) + mstore8(calldataload(0), 4) + sstore(0, mload(2)) +} +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 10 +// let _2 := 2 +// mstore(_2, _1) +// let _3 := 4 +// let _4 := 0 +// mstore8(calldataload(_4), _3) +// sstore(_4, mload(_2)) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul b/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul index 2a72eee3e215..ede5dc3e8273 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul @@ -11,6 +11,7 @@ } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // step: loadResolver // diff --git a/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul index 418221a93824..8035d17729bd 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul @@ -18,6 +18,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // step: loadResolver // diff --git a/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads_eof.yul b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads_eof.yul new file mode 100644 index 000000000000..42e6d11c7b2f --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads_eof.yul @@ -0,0 +1,39 @@ +{ + // TODO: The current implementation of YulOptimizerTests ignores subobjects that are not Data. It's impossbile to test + // eofcreate and returncontract now. + returndatacopy(1, 1, 0) + calldatacopy(1, 1, 0) + log0(1, 0) + log1(1, 0, 1) + log2(1, 0, 1, 1) + log3(1, 0, 1, 1, 1) + log4(1, 0, 1, 1, 1, 1) + //pop(eofcreate("a", 1, 1, 1, 0)) + //returncontract("b", 1, 0) + pop(extcall(1, 1, 1, 0)) + pop(extdelegatecall(1, 1, 0)) + pop(extstaticcall(1, 1, 0)) + return(1, 0) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 0 +// let _2 := 1 +// returndatacopy(0, _2, _1) +// calldatacopy(0, _2, _1) +// log0(0, _1) +// log1(0, _1, _2) +// log2(0, _1, _2, _2) +// log3(0, _1, _2, _2, _2) +// log4(0, _1, _2, _2, _2, _2) +// pop(extcall(_2, _2, _2, _1)) +// pop(extdelegatecall(_2, 0, _1)) +// pop(extstaticcall(_2, 0, _1)) +// return(0, _1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/complex_move.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/complex_move.yul index 3c11ca65f0db..cfa38e05ab08 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/complex_move.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/complex_move.yul @@ -2,7 +2,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { let inv := add(b, 42) - let x := extcodesize(keccak256(mul(mload(inv), 3), 32)) + let x := balance(keccak256(mul(mload(inv), 3), 32)) a := add(x, 1) sstore(a, inv) } @@ -14,7 +14,7 @@ // let b := 1 // let a := 1 // let inv := add(b, 42) -// let x := extcodesize(keccak256(mul(mload(inv), 3), 32)) +// let x := balance(keccak256(mul(mload(inv), 3), 32)) // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { // a := add(x, 1) diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul index 41289503791a..fa6619d05e30 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul @@ -11,6 +11,8 @@ let z := f() } } +// ==== +// bytecodeFormat: legacy // ---- // step: loopInvariantCodeMotion // diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul index 1d1a1491558f..a6ccbb39f83c 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul @@ -4,7 +4,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let t := extcodesize(f()) + let t := balance(f()) let q := g() } } @@ -14,7 +14,7 @@ // { // let b := 1 // let a := 1 -// let t := extcodesize(f()) +// let t := balance(f()) // let q := g() // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_gas.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_gas.yul new file mode 100644 index 000000000000..ae69ae3f7a45 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_gas.yul @@ -0,0 +1,15 @@ +{ + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + let c := gas() + } +} +// ==== +// bytecodeFormat: legacy +// ---- +// step: loopInvariantCodeMotion +// +// { +// let a := 1 +// for { } iszero(eq(a, 10)) { a := add(a, 1) } +// { let c := gas() } +// } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul index 8881fdc84887..0c7d68fc7641 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul @@ -1,24 +1,20 @@ { - let a := 1 - function f() -> x {invalid()} - function g() -> y {return(0, 0)} - for { let i := 1 } iszero(eq(i, 10)) { a := add(i, 1) } { - let b := f() - let c := gas() - let d := g() - let e := sload(g()) - } + function f() -> x {invalid()} + function g() -> y {return(0, 0)} + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + let b := f() + let d := g() + let e := sload(g()) + } } // ---- // step: loopInvariantCodeMotion // // { // let a := 1 -// let i := 1 -// for { } iszero(eq(i, 10)) { a := add(i, 1) } +// for { } iszero(eq(a, 10)) { a := add(a, 1) } // { // let b := f() -// let c := gas() // let d := g() // let e := sload(g()) // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul index 942a3c5802cb..486921ae6304 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul @@ -9,7 +9,7 @@ for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { let inv := add(b, 42) // mload prevents moving of extcodesize - let x := extcodesize(mload(mul(inv, 3))) + let x := balance(mload(mul(inv, 3))) a := add(x, 1) mstore(a, inv) } @@ -31,7 +31,7 @@ // let inv_2 := add(b, 42) // for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } // { -// let x_3 := extcodesize(mload(mul(inv_2, 3))) +// let x_3 := balance(mload(mul(inv_2, 3))) // a_1 := add(x_3, 1) // mstore(a_1, inv_2) // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul index 2033a9be91a4..95f968d89195 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul @@ -8,7 +8,7 @@ } for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { let inv := add(b, 42) - let x := extcodesize(mload(mul(inv, 3))) + let x := balance(mload(mul(inv, 3))) a := add(x, 1) } } @@ -29,7 +29,7 @@ // let inv_2 := add(b, 42) // for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } // { -// let x_3 := extcodesize(mload(mul(inv_2, 3))) +// let x_3 := balance(mload(mul(inv_2, 3))) // a_1 := add(x_3, 1) // } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul index fa6c985b4f8a..c2ea86bc82f0 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul @@ -25,6 +25,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: loopInvariantCodeMotion // diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul index d3dce8d781b6..c50d1b6c21d4 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul @@ -7,7 +7,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let t := extcodesize(f()) + let t := balance(f()) let q := sload(g()) } } @@ -19,7 +19,7 @@ // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { -// let t := extcodesize(f()) +// let t := balance(f()) // let q := sload(g()) // } // function f() -> x diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul index 8de9147d8aed..9745dbe4760f 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul @@ -4,7 +4,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let t := extcodesize(f()) + let t := balance(f()) let q := g() } } @@ -16,7 +16,7 @@ // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { -// let t := extcodesize(f()) +// let t := balance(f()) // let q := g() // } // function f() -> x diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul index 1eb0ccd6dd96..b8d4044c50d2 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul @@ -4,7 +4,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let t := extcodesize(f()) + let t := balance(f()) let q := sload(g()) } } @@ -16,7 +16,7 @@ // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { -// let t := extcodesize(f()) +// let t := balance(f()) // let q := sload(g()) // } // function f() -> x diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_staticall_returndatasize.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_staticall_returndatasize.yul index ae20f4904f88..a5f2125a0300 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_staticall_returndatasize.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_staticall_returndatasize.yul @@ -10,6 +10,8 @@ } } // ==== +// bytecodeFormat: legacy +// ==== // EVMVersion: >=byzantium // ---- // step: loopInvariantCodeMotion diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul index 0ef2fd78ad40..410f07663dbf 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul @@ -1,30 +1,15 @@ { - let b := 1 - // invalidates storage in post - for { let a := 1 } iszero(eq(a, 10)) { sstore(0x00, 0x01)} { - let inv := add(b, 42) - let x := sload(mul(inv, 3)) - a := add(x, 1) - mstore(a, inv) - } - - // invalidates storage in body - for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let inv := add(b, 42) - let x := sload(mul(inv, 3)) - a := add(x, 1) - sstore(a, inv) - } - - // invalidates state in body - for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let inv := add(b, 42) - pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) - let x := sload(mul(inv, 3)) - a := add(x, 1) - } - + let b := 1 + // invalidates state in body + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + let inv := add(b, 42) + pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) + let x := sload(mul(inv, 3)) + a := add(x, 1) + } } +// ==== +// bytecodeFormat: legacy // ---- // step: loopInvariantCodeMotion // @@ -32,26 +17,10 @@ // let b := 1 // let a := 1 // let inv := add(b, 42) -// for { } iszero(eq(a, 10)) { sstore(0x00, 0x01) } +// for { } iszero(eq(a, 10)) { a := add(a, 1) } // { +// pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) // let x := sload(mul(inv, 3)) // a := add(x, 1) -// mstore(a, inv) -// } -// let a_1 := 1 -// let inv_2 := add(b, 42) -// for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } -// { -// let x_3 := sload(mul(inv_2, 3)) -// a_1 := add(x_3, 1) -// sstore(a_1, inv_2) -// } -// let a_4 := 1 -// let inv_5 := add(b, 42) -// for { } iszero(eq(a_4, 10)) { a_4 := add(a_4, 1) } -// { -// pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) -// let x_6 := sload(mul(inv_5, 3)) -// a_4 := add(x_6, 1) // } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_body.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_body.yul new file mode 100644 index 000000000000..66a21130bbb8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_body.yul @@ -0,0 +1,24 @@ +{ + let b := 1 + // invalidates storage in body + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + let inv := add(b, 42) + let x := sload(mul(inv, 3)) + a := add(x, 1) + sstore(a, inv) + } +} +// ---- +// step: loopInvariantCodeMotion +// +// { +// let b := 1 +// let a := 1 +// let inv := add(b, 42) +// for { } iszero(eq(a, 10)) { a := add(a, 1) } +// { +// let x := sload(mul(inv, 3)) +// a := add(x, 1) +// sstore(a, inv) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_post.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_post.yul new file mode 100644 index 000000000000..6859f028bd34 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_post.yul @@ -0,0 +1,24 @@ +{ + let b := 1 + // invalidates storage in post + for { let a := 1 } iszero(eq(a, 10)) { sstore(0x00, 0x01)} { + let inv := add(b, 42) + let x := sload(mul(inv, 3)) + a := add(x, 1) + mstore(a, inv) + } +} +// ---- +// step: loopInvariantCodeMotion +// +// { +// let b := 1 +// let a := 1 +// let inv := add(b, 42) +// for { } iszero(eq(a, 10)) { sstore(0x00, 0x01) } +// { +// let x := sload(mul(inv, 3)) +// a := add(x, 1) +// mstore(a, inv) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/simple_state.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/simple_state.yul index f8b5a3d53725..b087802ef566 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/simple_state.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/simple_state.yul @@ -2,7 +2,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { let inv := add(b, 42) - let x := extcodesize(mul(inv, 3)) + let x := balance(mul(inv, 3)) a := add(x, 1) mstore(a, inv) } @@ -14,7 +14,7 @@ // let b := 1 // let a := 1 // let inv := add(b, 42) -// let x := extcodesize(mul(inv, 3)) +// let x := balance(mul(inv, 3)) // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { // a := add(x, 1) diff --git a/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul b/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul index ef6e12ab6ec2..57886d56380b 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul @@ -1,5 +1,5 @@ { - let a := extcodesize(0) + let a := balance(0) let b := a let c := b a := 2 @@ -10,7 +10,7 @@ // step: rematerialiser // // { -// let a := extcodesize(0) +// let a := balance(0) // let b := a // let c := a // a := 2 diff --git a/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul b/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul index bb5f029803fa..d168b1886c94 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul @@ -1,6 +1,6 @@ // We cannot substitute `a` in `let b := a` { - let a := extcodesize(0) + let a := balance(0) a := mul(a, 2) let b := a } @@ -8,7 +8,7 @@ // step: rematerialiser // // { -// let a := extcodesize(0) +// let a := balance(0) // a := mul(a, 2) // let b := a // } diff --git a/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul b/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul index 1a178abf0958..a7e9166577a9 100644 --- a/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul +++ b/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul @@ -2,6 +2,8 @@ let x := 8 function f() { let y := 9 } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackCompressor // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle.yul index 37da7f9b83d6..1f87ba5b8be2 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle.yul @@ -44,6 +44,8 @@ sstore(23, g(sload(42))) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after.yul index 4480d012e69d..5b3aba01fcaa 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after.yul @@ -44,6 +44,8 @@ v := h() } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after_2.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after_2.yul index 4468165f1e55..c33eea9b3535 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after_2.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after_2.yul @@ -47,6 +47,8 @@ v := h() } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before.yul index e6819ea903e7..0715f494522e 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before.yul @@ -49,6 +49,8 @@ sstore(mul(1,4), a1) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul index a0259b1800ef..59872e4a75f2 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul @@ -52,6 +52,8 @@ sstore(mul(1,4), a1) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_after.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_after.yul index f5c068d5e382..ad9366322b18 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_after.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_after.yul @@ -53,6 +53,8 @@ v := h() } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/function_arg.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/function_arg.yul index 27f0705157c4..8501a8d028b8 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/function_arg.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/function_arg.yul @@ -40,6 +40,8 @@ sstore(mul(1,4), a1) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/stub.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/stub.yul index 9f5001c87686..338c8e983ec5 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/stub.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/stub.yul @@ -45,6 +45,8 @@ sstore(mul(1,4), a1) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_14.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_14.yul index 02614c492db8..f6779917e321 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_14.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_14.yul @@ -15,6 +15,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_15.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_15.yul index 9ce9be70ab88..1ad539b3024f 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_15.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_15.yul @@ -17,6 +17,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_16.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_16.yul index 5a3b3454c591..c94c18ac486b 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_16.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_16.yul @@ -17,6 +17,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_15.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_15.yul index b9d1a5571a9a..a47d38fd037b 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_15.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_15.yul @@ -13,6 +13,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_16.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_16.yul index 40553083ffaa..aa144950f9c8 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_16.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_16.yul @@ -13,6 +13,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul index 8407df5d0497..e97e458da0e2 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul @@ -164,6 +164,8 @@ v := sload(mul(42,8)) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments.yul index bde030f68ec3..8a2c52a9ad98 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments.yul @@ -24,6 +24,8 @@ verbatim_20i_0o("test", a_1, a_2, a_3, a_4, a_5, a_6, a_7, a_8, a_9, a_10, a_11, a_12, a_13, a_14, a_15, a_16, a_17, a_18, a_19, a_20) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul index 46435dd210dc..e7170a10defd 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul @@ -45,6 +45,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul index 47db17e21198..e06dd8d8b0a9 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul @@ -7,6 +7,8 @@ sstore(a18, 20) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/call_does_not_need_to_write.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/call_does_not_need_to_write.yul index eeff779f85e0..2a65462e86bf 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/call_does_not_need_to_write.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/call_does_not_need_to_write.yul @@ -12,6 +12,8 @@ sstore(0, mload(0)) } +// ==== +// bytecodeFormat: legacy // ---- // step: unusedStoreEliminator // diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/create.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/create.yul index c3183d9ec83b..dc339466f864 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/create.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/create.yul @@ -4,6 +4,8 @@ pop(create(0, 0, 0)) sstore(x, 20) } +// ==== +// bytecodeFormat: legacy // ---- // step: unusedStoreEliminator // diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/create_inside_function.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/create_inside_function.yul index 782c68663b08..788e7be21ddd 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/create_inside_function.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/create_inside_function.yul @@ -7,6 +7,8 @@ f() sstore(x, 20) } +// ==== +// bytecodeFormat: legacy // ---- // step: unusedStoreEliminator // diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/store_before_terminating_verbatim_revert.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/store_before_terminating_verbatim_revert.yul new file mode 100644 index 000000000000..cbc76b1dea17 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/store_before_terminating_verbatim_revert.yul @@ -0,0 +1,20 @@ +{ + let x := 0 + let y := 1 + sstore(x, y) + // opcodes: PUSH1 0x00 DUP1 RETURN + // SSTORE is not redundant due to the RETURN hidden in the verbatim block. It must not be removed. + verbatim_0i_0o(hex"600080F3") + revert(0,0) +} +// ---- +// step: unusedStoreEliminator +// +// { +// { +// let x := 0 +// sstore(x, 1) +// verbatim_0i_0o("`\x00\x80\xf3") +// revert(0, 0) +// } +// } diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index eef0b29fa3c0..6fb0453c186b 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -52,7 +52,8 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nv2 := f(2, 1)\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nv2 := f(2, 1)\l\ // pop(v2)\l\ // "]; // Block0_0Exit [label="MainExit"]; @@ -61,119 +62,137 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 17)\nLiveIn: v0,v1\l\ +// LiveOut: v0,v1\l\n"]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; -// Block1_0Exit -> Block1_1; +// Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1\nv5 := φ(\l\ +// Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ // v6 := lt(v0, v5)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v6| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_1Exit:0 -> Block1_4; -// Block1_1Exit:1 -> Block1_2; +// Block1_1Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit:0 -> Block1_4 [style="solid"]; +// Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2\nv7 := mload(v5)\l\ +// Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v8| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_2Exit:0 -> Block1_7; -// Block1_2Exit:1 -> Block1_6; +// Block1_2Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit:0 -> Block1_7 [style="solid"]; +// Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ -// Block 4\nsstore(3084, 12)\l\ +// Block 4; (4, max 4)\nLiveIn: \l\ +// LiveOut: \l\nsstore(3084, 12)\l\ // "]; // Block1_4Exit [label="FunctionReturn[0]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ -// Block 6\nsstore(514, 2)\l\ +// Block 6; (3, max 4)\nLiveIn: \l\ +// LiveOut: \l\nsstore(514, 2)\l\ // "]; // Block1_6 -> Block1_6Exit [arrowhead=none]; // Block1_6Exit [label="Jump" shape=oval]; -// Block1_6Exit -> Block1_4; +// Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7\nv13 := eq(1, v7)\l\ +// Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_7Exit:0 -> Block1_10; -// Block1_7Exit:1 -> Block1_9; +// Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit:0 -> Block1_10 [style="solid"]; +// Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ -// Block 9\nsstore(1028, 4)\l\ +// Block 9; (6, max 6)\nLiveIn: \l\ +// LiveOut: \l\nsstore(1028, 4)\l\ // "]; // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10\nv20 := eq(2, v7)\l\ +// Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_10Exit:0 -> Block1_13; -// Block1_10Exit:1 -> Block1_12; +// Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit:0 -> Block1_13 [style="solid"]; +// Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [label="\ -// Block 12\nsstore(1542, 6)\l\ +// Block 12; (8, max 8)\nLiveIn: \l\ +// LiveOut: \l\nsstore(1542, 6)\l\ // revert(0, 0)\l\ // "]; // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13\nv25 := eq(3, v7)\l\ +// Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_13Exit:0 -> Block1_16; -// Block1_13Exit:1 -> Block1_15; +// Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit:0 -> Block1_16 [style="solid"]; +// Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15\nsstore(2056, 8)\l\ +// Block 15; (10, max 14)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; -// Block1_15Exit -> Block1_5; +// Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16\nv29 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v29| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_16Exit:0 -> Block1_18; -// Block1_16Exit:1 -> Block1_17; +// Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit:0 -> Block1_18 [style="solid"]; +// Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5\nsstore(2827, 11)\l\ +// Block 5; (11, max 14)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; -// Block1_5Exit -> Block1_3; +// Block1_5Exit -> Block1_3 [style="solid"]; // Block1_17 [label="\ -// Block 17\nreturn(0, 0)\l\ +// Block 17; (16, max 16)\nLiveIn: \l\ +// LiveOut: \l\nreturn(0, 0)\l\ // "]; // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18\nsstore(2570, 10)\l\ +// Block 18; (17, max 17)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; -// Block1_18Exit -> Block1_5; +// Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3\nv43 := add(1, v5)\l\ +// Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v44| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_3Exit:0 -> Block1_21; -// Block1_3Exit:1 -> Block1_20; +// Block1_3Exit [label="{ If v44 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit:0 -> Block1_21 [style="solid"]; +// Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20\nsstore(v43, 0)\l\ +// Block 20; (13, max 13)\nLiveIn: v43\l\ +// LiveOut: \l\nsstore(v43, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21\nsstore(65535, 255)\l\ +// Block 21; (14, max 14)\nLiveIn: v0,v1,v43\l\ +// LiveOut: v0,v1,v43\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; -// Block1_21Exit -> Block1_1; +// Block1_21Exit -> Block1_1 [style="dashed"]; // } diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index 743b0513cc56..c3ea8b94f8aa 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -59,7 +59,8 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nsstore(1, 1)\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nsstore(1, 1)\l\ // v2 := f(2, 1)\l\ // pop(v2)\l\ // v4 := sload(0)\l\ @@ -77,119 +78,137 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 17)\nLiveIn: v0,v1\l\ +// LiveOut: v0,v1\l\n"]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; -// Block1_0Exit -> Block1_1; +// Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1\nv5 := φ(\l\ +// Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ // v6 := lt(v0, v5)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v6| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_1Exit:0 -> Block1_4; -// Block1_1Exit:1 -> Block1_2; +// Block1_1Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit:0 -> Block1_4 [style="solid"]; +// Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2\nv7 := mload(v5)\l\ +// Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v8| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_2Exit:0 -> Block1_7; -// Block1_2Exit:1 -> Block1_6; +// Block1_2Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit:0 -> Block1_7 [style="solid"]; +// Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ -// Block 4\nsstore(3084, 12)\l\ +// Block 4; (4, max 4)\nLiveIn: \l\ +// LiveOut: \l\nsstore(3084, 12)\l\ // "]; // Block1_4Exit [label="FunctionReturn[27]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ -// Block 6\nsstore(514, 2)\l\ +// Block 6; (3, max 4)\nLiveIn: \l\ +// LiveOut: \l\nsstore(514, 2)\l\ // "]; // Block1_6 -> Block1_6Exit [arrowhead=none]; // Block1_6Exit [label="Jump" shape=oval]; -// Block1_6Exit -> Block1_4; +// Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7\nv13 := eq(1, v7)\l\ +// Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_7Exit:0 -> Block1_10; -// Block1_7Exit:1 -> Block1_9; +// Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit:0 -> Block1_10 [style="solid"]; +// Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ -// Block 9\nsstore(1028, 4)\l\ +// Block 9; (6, max 6)\nLiveIn: \l\ +// LiveOut: \l\nsstore(1028, 4)\l\ // "]; // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10\nv20 := eq(2, v7)\l\ +// Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_10Exit:0 -> Block1_13; -// Block1_10Exit:1 -> Block1_12; +// Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit:0 -> Block1_13 [style="solid"]; +// Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [label="\ -// Block 12\nsstore(1542, 6)\l\ +// Block 12; (8, max 8)\nLiveIn: \l\ +// LiveOut: \l\nsstore(1542, 6)\l\ // revert(0, 0)\l\ // "]; // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13\nv25 := eq(3, v7)\l\ +// Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_13Exit:0 -> Block1_16; -// Block1_13Exit:1 -> Block1_15; +// Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit:0 -> Block1_16 [style="solid"]; +// Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15\nsstore(2056, 8)\l\ +// Block 15; (10, max 14)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; -// Block1_15Exit -> Block1_5; +// Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16\nv29 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v29| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_16Exit:0 -> Block1_18; -// Block1_16Exit:1 -> Block1_17; +// Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit:0 -> Block1_18 [style="solid"]; +// Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5\nsstore(2827, 11)\l\ +// Block 5; (11, max 14)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; -// Block1_5Exit -> Block1_3; +// Block1_5Exit -> Block1_3 [style="solid"]; // Block1_17 [label="\ -// Block 17\nreturn(0, 0)\l\ +// Block 17; (16, max 16)\nLiveIn: \l\ +// LiveOut: \l\nreturn(0, 0)\l\ // "]; // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18\nsstore(2570, 10)\l\ +// Block 18; (17, max 17)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; -// Block1_18Exit -> Block1_5; +// Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3\nv43 := add(1, v5)\l\ +// Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v44| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_3Exit:0 -> Block1_21; -// Block1_3Exit:1 -> Block1_20; +// Block1_3Exit [label="{ If v44 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit:0 -> Block1_21 [style="solid"]; +// Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20\nsstore(v43, 0)\l\ +// Block 20; (13, max 13)\nLiveIn: v43\l\ +// LiveOut: \l\nsstore(v43, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21\nsstore(65535, 255)\l\ +// Block 21; (14, max 14)\nLiveIn: v0,v1,v43\l\ +// LiveOut: v0,v1,v43\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; -// Block1_21Exit -> Block1_1; +// Block1_21Exit -> Block1_1 [style="dashed"]; // } diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index 20a536b5e556..acf1a37aa43f 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -27,7 +27,8 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nv0, v1 := i()\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nv0, v1 := i()\l\ // h(v0)\l\ // "]; // Block0_0Exit [label="Terminated"]; @@ -36,7 +37,8 @@ // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\nv3 := add(v1, v0)\l\ +// Block 0; (0, max 0)\nLiveIn: v0,v1\l\ +// LiveOut: v4\l\nv3 := add(v1, v0)\l\ // v4 := sub(v0, v3)\l\ // "]; // Block1_0Exit [label="FunctionReturn[v4]"]; @@ -45,7 +47,8 @@ // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ -// Block 0\nsstore(257, 1)\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nsstore(257, 1)\l\ // "]; // Block2_0Exit [label="FunctionReturn[]"]; // Block2_0 -> Block2_0Exit; @@ -53,7 +56,8 @@ // h(v0)"]; // FunctionEntry_h_0 -> Block3_0; // Block3_0 [label="\ -// Block 0\nv2 := f(0, v0)\l\ +// Block 0; (0, max 0)\nLiveIn: v0\l\ +// LiveOut: \l\nv2 := f(0, v0)\l\ // h(v2)\l\ // "]; // Block3_0Exit [label="Terminated"]; @@ -62,7 +66,8 @@ // v, w := i()"]; // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block4_0Exit [label="FunctionReturn[514, 771]"]; // Block4_0 -> Block4_0Exit; // } diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul index 9045d8034003..e2a66ab74fba 100644 --- a/test/libyul/yulSSAControlFlowGraph/if.yul +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -15,20 +15,23 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nv1 := calldataload(3)\l\ +// Block 0; (0, max 2)\nLiveIn: \l\ +// LiveOut: v1\l\nv1 := calldataload(3)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If 0| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_0Exit:0 -> Block0_2; -// Block0_0Exit:1 -> Block0_1; +// Block0_0Exit [label="{ If 0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_2 [style="solid"]; +// Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// Block 1\nv4 := calldataload(77)\l\ +// Block 1; (1, max 2)\nLiveIn: \l\ +// LiveOut: v4\l\nv4 := calldataload(77)\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; -// Block0_1Exit -> Block0_2; +// Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2\nv5 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: v5\l\ +// LiveOut: \l\nv5 := φ(\l\ // Block 0 => v1,\l\ // Block 1 => v4\l\ // )\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index 0ed17c870a1f..b088e3b55ed8 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -26,170 +26,195 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 24)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block0_0 -> Block0_0Exit [arrowhead=none]; // Block0_0Exit [label="Jump" shape=oval]; -// Block0_0Exit -> Block0_1; +// Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// Block 1\nv2 := φ(\l\ +// Block 1; (1, max 24)\nLiveIn: v2\l\ +// LiveOut: v2\l\nv2 := φ(\l\ // Block 0 => 0,\l\ // Block 3 => v36\l\ // )\l\ // v3 := lt(3, v2)\l\ // "]; // Block0_1 -> Block0_1Exit; -// Block0_1Exit [label="{ If v3| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_1Exit:0 -> Block0_4; -// Block0_1Exit:1 -> Block0_2; +// Block0_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit:0 -> Block0_4 [style="solid"]; +// Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2\n"]; +// Block 2; (2, max 23)\nLiveIn: v2\l\ +// LiveOut: v2\l\n"]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; -// Block0_2Exit -> Block0_5; +// Block0_2Exit -> Block0_5 [style="solid"]; // Block0_4 [label="\ -// Block 4\n"]; +// Block 4; (24, max 24)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// Block 5\nv4 := φ(\l\ +// Block 5; (3, max 23)\nLiveIn: v2,v4\l\ +// LiveOut: v2,v4\l\nv4 := φ(\l\ // Block 2 => 0,\l\ // Block 7 => v35\l\ // )\l\ // v5 := lt(3, v4)\l\ // "]; // Block0_5 -> Block0_5Exit; -// Block0_5Exit [label="{ If v5| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_5Exit:0 -> Block0_8; -// Block0_5Exit:1 -> Block0_6; +// Block0_5Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit:0 -> Block0_8 [style="solid"]; +// Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// Block 6\n"]; +// Block 6; (4, max 21)\nLiveIn: v2,v4\l\ +// LiveOut: v2,v4\l\n"]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; -// Block0_6Exit -> Block0_9; +// Block0_6Exit -> Block0_9 [style="solid"]; // Block0_8 [label="\ -// Block 8\n"]; +// Block 8; (22, max 23)\nLiveIn: v2\l\ +// LiveOut: v2\l\n"]; // Block0_8 -> Block0_8Exit [arrowhead=none]; // Block0_8Exit [label="Jump" shape=oval]; -// Block0_8Exit -> Block0_3; +// Block0_8Exit -> Block0_3 [style="solid"]; // Block0_9 [label="\ -// Block 9\nv6 := φ(\l\ +// Block 9; (5, max 21)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\nv6 := φ(\l\ // Block 6 => 0,\l\ // Block 11 => v31\l\ // )\l\ // v7 := lt(3, v6)\l\ // "]; // Block0_9 -> Block0_9Exit; -// Block0_9Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_9Exit:0 -> Block0_12; -// Block0_9Exit:1 -> Block0_10; +// Block0_9Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_9Exit:0 -> Block0_12 [style="solid"]; +// Block0_9Exit:1 -> Block0_10 [style="solid"]; // Block0_3 [label="\ -// Block 3\nv36 := add(1, v2)\l\ +// Block 3; (23, max 23)\nLiveIn: v2\l\ +// LiveOut: v36\l\nv36 := add(1, v2)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; -// Block0_3Exit -> Block0_1; +// Block0_3Exit -> Block0_1 [style="dashed"]; // Block0_10 [label="\ -// Block 10\n"]; +// Block 10; (6, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_10 -> Block0_10Exit; -// Block0_10Exit [label="{ If 0| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_10Exit:0 -> Block0_14; -// Block0_10Exit:1 -> Block0_13; +// Block0_10Exit [label="{ If 0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_10Exit:0 -> Block0_14 [style="solid"]; +// Block0_10Exit:1 -> Block0_13 [style="solid"]; // Block0_12 [label="\ -// Block 12\n"]; +// Block 12; (20, max 21)\nLiveIn: v2,v4\l\ +// LiveOut: v2,v4\l\n"]; // Block0_12 -> Block0_12Exit [arrowhead=none]; // Block0_12Exit [label="Jump" shape=oval]; -// Block0_12Exit -> Block0_7; +// Block0_12Exit -> Block0_7 [style="solid"]; // Block0_13 [label="\ -// Block 13\n"]; +// Block 13; (7, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_13 -> Block0_13Exit [arrowhead=none]; // Block0_13Exit [label="Jump" shape=oval]; -// Block0_13Exit -> Block0_15; +// Block0_13Exit -> Block0_15 [style="solid"]; // Block0_14 [label="\ -// Block 14\n"]; +// Block 14; (12, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_14 -> Block0_14Exit; -// Block0_14Exit [label="{ If 1| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_14Exit:0 -> Block0_20; -// Block0_14Exit:1 -> Block0_19; +// Block0_14Exit [label="{ If 1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_14Exit:0 -> Block0_20 [style="solid"]; +// Block0_14Exit:1 -> Block0_19 [style="solid"]; // Block0_7 [label="\ -// Block 7\nv35 := add(1, v4)\l\ +// Block 7; (21, max 21)\nLiveIn: v2,v4\l\ +// LiveOut: v2,v35\l\nv35 := add(1, v4)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; -// Block0_7Exit -> Block0_5; +// Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ -// Block 15\nv8 := φ(\l\ +// Block 15; (8, max 19)\nLiveIn: v2,v4,v6,v8\l\ +// LiveOut: v2,v4,v6,v8\l\nv8 := φ(\l\ // Block 13 => 0,\l\ // Block 17 => v16\l\ // )\l\ // v9 := lt(3, v8)\l\ // "]; // Block0_15 -> Block0_15Exit; -// Block0_15Exit [label="{ If v9| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_15Exit:0 -> Block0_18; -// Block0_15Exit:1 -> Block0_16; +// Block0_15Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_15Exit:0 -> Block0_18 [style="solid"]; +// Block0_15Exit:1 -> Block0_16 [style="solid"]; // Block0_19 [label="\ -// Block 19\n"]; +// Block 19; (13, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_19 -> Block0_19Exit [arrowhead=none]; // Block0_19Exit [label="Jump" shape=oval]; -// Block0_19Exit -> Block0_21; +// Block0_19Exit -> Block0_21 [style="solid"]; // Block0_20 [label="\ -// Block 20\n"]; +// Block 20; (18, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_20 -> Block0_20Exit [arrowhead=none]; // Block0_20Exit [label="Jump" shape=oval]; -// Block0_20Exit -> Block0_11; +// Block0_20Exit -> Block0_11 [style="solid"]; // Block0_16 [label="\ -// Block 16\nv13 := add(v4, v2)\l\ +// Block 16; (9, max 10)\nLiveIn: v2,v4,v6,v8\l\ +// LiveOut: v2,v4,v6,v8\l\nv13 := add(v4, v2)\l\ // v14 := add(v6, v13)\l\ // sstore(v14, v8)\l\ // "]; // Block0_16 -> Block0_16Exit [arrowhead=none]; // Block0_16Exit [label="Jump" shape=oval]; -// Block0_16Exit -> Block0_17; +// Block0_16Exit -> Block0_17 [style="solid"]; // Block0_18 [label="\ -// Block 18\n"]; +// Block 18; (11, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_18 -> Block0_18Exit [arrowhead=none]; // Block0_18Exit [label="Jump" shape=oval]; -// Block0_18Exit -> Block0_14; +// Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ -// Block 21\nv19 := φ(\l\ +// Block 21; (14, max 19)\nLiveIn: v2,v4,v6,v19\l\ +// LiveOut: v2,v4,v6,v19\l\nv19 := φ(\l\ // Block 19 => 0,\l\ // Block 23 => v26\l\ // )\l\ // v20 := lt(3, v19)\l\ // "]; // Block0_21 -> Block0_21Exit; -// Block0_21Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_21Exit:0 -> Block0_24; -// Block0_21Exit:1 -> Block0_22; +// Block0_21Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_21Exit:0 -> Block0_24 [style="solid"]; +// Block0_21Exit:1 -> Block0_22 [style="solid"]; // Block0_11 [label="\ -// Block 11\nv31 := add(1, v6)\l\ +// Block 11; (19, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v31\l\nv31 := add(1, v6)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; -// Block0_11Exit -> Block0_9; +// Block0_11Exit -> Block0_9 [style="dashed"]; // Block0_17 [label="\ -// Block 17\nv16 := add(1, v8)\l\ +// Block 17; (10, max 10)\nLiveIn: v2,v4,v6,v8\l\ +// LiveOut: v2,v4,v6,v16\l\nv16 := add(1, v8)\l\ // "]; // Block0_17 -> Block0_17Exit [arrowhead=none]; // Block0_17Exit [label="Jump" shape=oval]; -// Block0_17Exit -> Block0_15; +// Block0_17Exit -> Block0_15 [style="dashed"]; // Block0_22 [label="\ -// Block 22\nv24 := add(v4, v2)\l\ +// Block 22; (15, max 16)\nLiveIn: v2,v4,v6,v19\l\ +// LiveOut: v2,v4,v6,v19\l\nv24 := add(v4, v2)\l\ // v25 := add(v6, v24)\l\ // sstore(v25, v19)\l\ // "]; // Block0_22 -> Block0_22Exit [arrowhead=none]; // Block0_22Exit [label="Jump" shape=oval]; -// Block0_22Exit -> Block0_23; +// Block0_22Exit -> Block0_23 [style="solid"]; // Block0_24 [label="\ -// Block 24\n"]; +// Block 24; (17, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_24 -> Block0_24Exit [arrowhead=none]; // Block0_24Exit [label="Jump" shape=oval]; -// Block0_24Exit -> Block0_20; +// Block0_24Exit -> Block0_20 [style="solid"]; // Block0_23 [label="\ -// Block 23\nv26 := add(1, v19)\l\ +// Block 23; (16, max 16)\nLiveIn: v2,v4,v6,v19\l\ +// LiveOut: v2,v4,v6,v26\l\nv26 := add(1, v19)\l\ // "]; // Block0_23 -> Block0_23Exit [arrowhead=none]; // Block0_23Exit [label="Jump" shape=oval]; -// Block0_23Exit -> Block0_21; +// Block0_23Exit -> Block0_21 [style="dashed"]; // } diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul index 859b24151592..acda15ce81a5 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_function.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -38,14 +38,16 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\nv3 := add(v1, v0)\l\ +// Block 0; (0, max 0)\nLiveIn: v0,v1\l\ +// LiveOut: v4\l\nv3 := add(v1, v0)\l\ // v4 := sub(v0, v3)\l\ // "]; // Block1_0Exit [label="FunctionReturn[v4]"]; @@ -54,7 +56,8 @@ // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ -// Block 0\nv1 := v()\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nv1 := v()\l\ // v2 := f(2, v1)\l\ // v3 := z()\l\ // sstore(v2, v3)\l\ @@ -65,7 +68,8 @@ // r := z()"]; // FunctionEntry_z_0 -> Block3_0; // Block3_0 [label="\ -// Block 0\nv1 := w()\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: v1\l\nv1 := w()\l\ // "]; // Block3_0Exit [label="FunctionReturn[v1]"]; // Block3_0 -> Block3_0Exit; @@ -73,14 +77,16 @@ // rw1 := w()"]; // FunctionEntry_w_0 -> Block4_0; // Block4_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block4_0Exit [label="FunctionReturn[1]"]; // Block4_0 -> Block4_0Exit; // FunctionEntry_v_0 [label="function v: // r := v()"]; // FunctionEntry_v_0 -> Block5_0; // Block5_0 [label="\ -// Block 0\nv1 := w()\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: v1\l\nv1 := w()\l\ // "]; // Block5_0Exit [label="FunctionReturn[v1]"]; // Block5_0 -> Block5_0Exit; @@ -88,27 +94,31 @@ // rw2 := w()"]; // FunctionEntry_w_0 -> Block6_0; // Block6_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block6_0Exit [label="FunctionReturn[17]"]; // Block6_0 -> Block6_0Exit; // FunctionEntry_cycle1_0 [label="function cycle1: // r := cycle1()"]; // FunctionEntry_cycle1_0 -> Block7_0; // Block7_0 [label="\ -// Block 0\nv2 := mload(3)\l\ +// Block 0; (0, max 2)\nLiveIn: \l\ +// LiveOut: \l\nv2 := mload(3)\l\ // "]; // Block7_0 -> Block7_0Exit; -// Block7_0Exit [label="{ If v2| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block7_0Exit:0 -> Block7_2; -// Block7_0Exit:1 -> Block7_1; +// Block7_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block7_0Exit:0 -> Block7_2 [style="solid"]; +// Block7_0Exit:1 -> Block7_1 [style="solid"]; // Block7_1 [label="\ -// Block 1\nv3 := cycle2()\l\ +// Block 1; (1, max 2)\nLiveIn: \l\ +// LiveOut: v3\l\nv3 := cycle2()\l\ // "]; // Block7_1 -> Block7_1Exit [arrowhead=none]; // Block7_1Exit [label="Jump" shape=oval]; -// Block7_1Exit -> Block7_2; +// Block7_1Exit -> Block7_2 [style="solid"]; // Block7_2 [label="\ -// Block 2\nv4 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: v4\l\ +// LiveOut: v4\l\nv4 := φ(\l\ // Block 0 => 0,\l\ // Block 1 => v3\l\ // )\l\ @@ -119,20 +129,23 @@ // r := cycle2()"]; // FunctionEntry_cycle2_0 -> Block8_0; // Block8_0 [label="\ -// Block 0\nv2 := mload(4)\l\ +// Block 0; (0, max 2)\nLiveIn: \l\ +// LiveOut: \l\nv2 := mload(4)\l\ // "]; // Block8_0 -> Block8_0Exit; -// Block8_0Exit [label="{ If v2| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block8_0Exit:0 -> Block8_2; -// Block8_0Exit:1 -> Block8_1; +// Block8_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block8_0Exit:0 -> Block8_2 [style="solid"]; +// Block8_0Exit:1 -> Block8_1 [style="solid"]; // Block8_1 [label="\ -// Block 1\nv3 := cycle1()\l\ +// Block 1; (1, max 2)\nLiveIn: \l\ +// LiveOut: v3\l\nv3 := cycle1()\l\ // "]; // Block8_1 -> Block8_1Exit [arrowhead=none]; // Block8_1Exit [label="Jump" shape=oval]; -// Block8_1Exit -> Block8_2; +// Block8_1Exit -> Block8_2 [style="solid"]; // Block8_2 [label="\ -// Block 2\nv4 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: v4\l\ +// LiveOut: v4\l\nv4 := φ(\l\ // Block 0 => 0,\l\ // Block 1 => v3\l\ // )\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index f6c084b001a7..10573b012298 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -22,29 +22,33 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nv1 := calldataload(3)\l\ +// Block 0; (0, max 5)\nLiveIn: \l\ +// LiveOut: v3\l\nv1 := calldataload(3)\l\ // v3 := sload(0)\l\ // v4 := eq(0, v3)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v4| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_0Exit:0 -> Block0_3; -// Block0_0Exit:1 -> Block0_2; +// Block0_0Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_3 [style="solid"]; +// Block0_0Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2\nv6 := calldataload(77)\l\ +// Block 2; (1, max 2)\nLiveIn: \l\ +// LiveOut: v6\l\nv6 := calldataload(77)\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; -// Block0_2Exit -> Block0_1; +// Block0_2Exit -> Block0_1 [style="solid"]; // Block0_3 [label="\ -// Block 3\nv7 := eq(1, v3)\l\ +// Block 3; (3, max 5)\nLiveIn: v3\l\ +// LiveOut: \l\nv7 := eq(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit; -// Block0_3Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_3Exit:0 -> Block0_5; -// Block0_3Exit:1 -> Block0_4; +// Block0_3Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_3Exit:0 -> Block0_5 [style="solid"]; +// Block0_3Exit:1 -> Block0_4 [style="solid"]; // Block0_1 [label="\ -// Block 1\nv13 := φ(\l\ +// Block 1; (2, max 2)\nLiveIn: v13\l\ +// LiveOut: \l\nv13 := φ(\l\ // Block 2 => v6,\l\ // Block 4 => v10,\l\ // Block 5 => v12\l\ @@ -54,15 +58,17 @@ // Block0_1Exit [label="MainExit"]; // Block0_1 -> Block0_1Exit; // Block0_4 [label="\ -// Block 4\nv10 := calldataload(88)\l\ +// Block 4; (4, max 4)\nLiveIn: \l\ +// LiveOut: v10\l\nv10 := calldataload(88)\l\ // "]; // Block0_4 -> Block0_4Exit [arrowhead=none]; // Block0_4Exit [label="Jump" shape=oval]; -// Block0_4Exit -> Block0_1; +// Block0_4Exit -> Block0_1 [style="solid"]; // Block0_5 [label="\ -// Block 5\nv12 := calldataload(99)\l\ +// Block 5; (5, max 5)\nLiveIn: \l\ +// LiveOut: v12\l\nv12 := calldataload(99)\l\ // "]; // Block0_5 -> Block0_5Exit [arrowhead=none]; // Block0_5Exit [label="Jump" shape=oval]; -// Block0_5Exit -> Block0_1; +// Block0_5Exit -> Block0_1 [style="solid"]; // } diff --git a/test/libyul/yulStackLayout/complex.yul b/test/libyul/yulStackLayout/complex.yul index 604dca1f46e2..66390f7d4741 100644 --- a/test/libyul/yulStackLayout/complex.yul +++ b/test/libyul/yulStackLayout/complex.yul @@ -48,6 +48,8 @@ } pop(f(1,2)) } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulStackLayout/eof/function.yul b/test/libyul/yulStackLayout/eof/function.yul new file mode 100644 index 000000000000..a196e46e887d --- /dev/null +++ b/test/libyul/yulStackLayout/eof/function.yul @@ -0,0 +1,102 @@ +{ + function f(a, b) -> r { + let x := add(a,b) + r := sub(x,a) + } + function g() { + sstore(0x01, 0x0101) + } + function h(x) { + h(f(x, 0)) + g() + } + function i() -> v, w { + v := 0x0202 + w := 0x0303 + } + let x, y := i() + h(x) + h(y) + // This call of g() is unreachable too as the one in h() but we wanna cover both cases. + g() +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// digraph CFG { +// nodesep=0.7; +// node[shape=box]; +// +// Entry [label="Entry"]; +// Entry -> Block0; +// Block0 [label="\ +// [ ]\l\ +// [ ]\l\ +// i\l\ +// [ TMP[i, 0] TMP[i, 1] ]\l\ +// [ TMP[i, 0] TMP[i, 1] ]\l\ +// Assignment(x, y)\l\ +// [ x y ]\l\ +// [ x ]\l\ +// h\l\ +// [ ]\l\ +// [ ]\l\ +// "]; +// Block0Exit [label="Terminated"]; +// Block0 -> Block0Exit; +// +// FunctionEntry_f [label="function f(a, b) -> r\l\ +// [ RET b a ]"]; +// FunctionEntry_f -> Block1; +// Block1 [label="\ +// [ a b ]\l\ +// [ a b a ]\l\ +// add\l\ +// [ a TMP[add, 0] ]\l\ +// [ a TMP[add, 0] ]\l\ +// Assignment(x)\l\ +// [ a x ]\l\ +// [ a x ]\l\ +// sub\l\ +// [ TMP[sub, 0] ]\l\ +// [ TMP[sub, 0] ]\l\ +// Assignment(r)\l\ +// [ r ]\l\ +// [ r ]\l\ +// "]; +// Block1Exit [label="FunctionReturn[f]"]; +// Block1 -> Block1Exit; +// +// FunctionEntry_h [label="function h(x)\l\ +// [ RET x ]"]; +// FunctionEntry_h -> Block2; +// Block2 [label="\ +// [ 0x00 x ]\l\ +// [ 0x00 x ]\l\ +// f\l\ +// [ TMP[f, 0] ]\l\ +// [ TMP[f, 0] ]\l\ +// h\l\ +// [ ]\l\ +// [ ]\l\ +// "]; +// Block2Exit [label="Terminated"]; +// Block2 -> Block2Exit; +// +// FunctionEntry_i [label="function i() -> v, w\l\ +// [ RET ]"]; +// FunctionEntry_i -> Block3; +// Block3 [label="\ +// [ ]\l\ +// [ 0x0202 ]\l\ +// Assignment(v)\l\ +// [ v ]\l\ +// [ v 0x0303 ]\l\ +// Assignment(w)\l\ +// [ v w ]\l\ +// [ v w ]\l\ +// "]; +// Block3Exit [label="FunctionReturn[i]"]; +// Block3 -> Block3Exit; +// +// } diff --git a/test/libyul/yulStackLayout/function.yul b/test/libyul/yulStackLayout/function.yul index ccf97422f44f..13f83505d48e 100644 --- a/test/libyul/yulStackLayout/function.yul +++ b/test/libyul/yulStackLayout/function.yul @@ -17,7 +17,11 @@ let x, y := i() h(x) h(y) + // This call of g() is unreachable too as the one in h() but we wanna cover both cases. + g() } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; @@ -63,23 +67,10 @@ // Block1Exit [label="FunctionReturn[f]"]; // Block1 -> Block1Exit; // -// FunctionEntry_g [label="function g()\l\ -// [ RET ]"]; -// FunctionEntry_g -> Block2; -// Block2 [label="\ -// [ RET ]\l\ -// [ RET 0x0101 0x01 ]\l\ -// sstore\l\ -// [ RET ]\l\ -// [ RET ]\l\ -// "]; -// Block2Exit [label="FunctionReturn[g]"]; -// Block2 -> Block2Exit; -// // FunctionEntry_h [label="function h(x)\l\ // [ RET x ]"]; -// FunctionEntry_h -> Block3; -// Block3 [label="\ +// FunctionEntry_h -> Block2; +// Block2 [label="\ // [ RET[f] 0x00 x ]\l\ // [ RET[f] 0x00 x ]\l\ // f\l\ @@ -89,13 +80,13 @@ // [ ]\l\ // [ ]\l\ // "]; -// Block3Exit [label="Terminated"]; -// Block3 -> Block3Exit; +// Block2Exit [label="Terminated"]; +// Block2 -> Block2Exit; // // FunctionEntry_i [label="function i() -> v, w\l\ // [ RET ]"]; -// FunctionEntry_i -> Block4; -// Block4 [label="\ +// FunctionEntry_i -> Block3; +// Block3 [label="\ // [ RET ]\l\ // [ RET 0x0202 ]\l\ // Assignment(v)\l\ @@ -105,7 +96,7 @@ // [ v RET w ]\l\ // [ v w RET ]\l\ // "]; -// Block4Exit [label="FunctionReturn[i]"]; -// Block4 -> Block4Exit; +// Block3Exit [label="FunctionReturn[i]"]; +// Block3 -> Block3Exit; // // } diff --git a/test/libyul/yulStackLayout/literal_loop.yul b/test/libyul/yulStackLayout/literal_loop.yul index 841c4106262d..fee5f7b5673a 100644 --- a/test/libyul/yulStackLayout/literal_loop.yul +++ b/test/libyul/yulStackLayout/literal_loop.yul @@ -4,6 +4,8 @@ {} {} } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulStackShuffling/pop_early_to_avoid_swap17.stack b/test/libyul/yulStackShuffling/pop_early_to_avoid_swap17.stack new file mode 100644 index 000000000000..6ec0cbb0b4ea --- /dev/null +++ b/test/libyul/yulStackShuffling/pop_early_to_avoid_swap17.stack @@ -0,0 +1,12 @@ +// We avoid a SWAP17 here by first removing duplicates on stack. +[ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk deep ] +[ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk ] +// ---- +// [ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk deep ] +// SWAP1 +// [ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 deep junk ] +// POP +// [ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 deep ] +// SWAP16 +// [ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk ] +// 3 operations diff --git a/test/libyul/yulStackShuffling/swap17.stack b/test/libyul/yulStackShuffling/swap17.stack new file mode 100644 index 000000000000..6e62854a9492 --- /dev/null +++ b/test/libyul/yulStackShuffling/swap17.stack @@ -0,0 +1,13 @@ +// With a SWAP17 at our disposal, we do not need to first remove duplicates from stack +// as seen in pop_early_to_avoid_swap17.stack. +[ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk deep ] +[ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk ] +// ==== +// maximumStackDepth: 256 +// ---- +// [ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk deep ] +// SWAP17 +// [ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk junk ] +// POP +// [ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk ] +// 2 operations diff --git a/test/libyul/yulStackShuffling/swap_cycle.stack b/test/libyul/yulStackShuffling/swap_cycle.stack index fbda89ebfd2a..fd99cea6ec15 100644 --- a/test/libyul/yulStackShuffling/swap_cycle.stack +++ b/test/libyul/yulStackShuffling/swap_cycle.stack @@ -20,3 +20,4 @@ // [ v1 v0 v2 v3 v4 v5 v6 v7 v9 v10 v11 v12 v13 v14 v15 v16 RET JUNK ] // PUSH JUNK // [ v1 v0 v2 v3 v4 v5 v6 v7 v9 v10 v11 v12 v13 v14 v15 v16 RET JUNK JUNK ] +// 9 operations diff --git a/test/libyul/yulSyntaxTests/assignment_to_builtin.yul b/test/libyul/yulSyntaxTests/assignment_to_builtin.yul new file mode 100644 index 000000000000..80f84c1349c5 --- /dev/null +++ b/test/libyul/yulSyntaxTests/assignment_to_builtin.yul @@ -0,0 +1,6 @@ +{ + function f() -> x {} + add := f() +} +// ---- +// ParserError 6272: (35-37): Cannot assign to builtin function "add". diff --git a/test/libyul/yulSyntaxTests/assignment_to_number.yul b/test/libyul/yulSyntaxTests/assignment_to_number.yul new file mode 100644 index 000000000000..3c4517fdde0c --- /dev/null +++ b/test/libyul/yulSyntaxTests/assignment_to_number.yul @@ -0,0 +1,6 @@ +{ + function f() -> x {} + let 123 := f() +} +// ---- +// ParserError 2314: (35-38): Expected identifier but got 'Number' diff --git a/test/libyul/yulSyntaxTests/blobhash.yul b/test/libyul/yulSyntaxTests/blobhash.yul index 6337f22c1b29..272ec13d7bb0 100644 --- a/test/libyul/yulSyntaxTests/blobhash.yul +++ b/test/libyul/yulSyntaxTests/blobhash.yul @@ -13,3 +13,4 @@ // EVMVersion: >=cancun // ---- // ParserError 5568: (20-28): Cannot use builtin function name "blobhash" as identifier name. +// ParserError 5568: (64-72): Cannot use builtin function name "blobhash" as identifier name. diff --git a/test/libyul/yulSyntaxTests/builtin_function_literal.yul b/test/libyul/yulSyntaxTests/builtin_function_literal.yul index 22f7216146a6..c975648ae2df 100644 --- a/test/libyul/yulSyntaxTests/builtin_function_literal.yul +++ b/test/libyul/yulSyntaxTests/builtin_function_literal.yul @@ -1,6 +1,8 @@ { datasize(x,1) } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 7000: (4-12): Function "datasize" expects 1 arguments but got 2. // TypeError 9114: (4-12): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/datacopy_shadowing.yul b/test/libyul/yulSyntaxTests/datacopy_shadowing.yul index 3f14f47226a9..7466af6c3863 100644 --- a/test/libyul/yulSyntaxTests/datacopy_shadowing.yul +++ b/test/libyul/yulSyntaxTests/datacopy_shadowing.yul @@ -1,5 +1,7 @@ { function datacopy(a, b, c) {} } +// ==== +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-23): Cannot use builtin function name "datacopy" as identifier name. diff --git a/test/libyul/yulSyntaxTests/dataoffset_shadowing.yul b/test/libyul/yulSyntaxTests/dataoffset_shadowing.yul index fb32fb61c17a..db02e90e4881 100644 --- a/test/libyul/yulSyntaxTests/dataoffset_shadowing.yul +++ b/test/libyul/yulSyntaxTests/dataoffset_shadowing.yul @@ -1,5 +1,7 @@ { function dataoffset(a) -> b {} } +// ==== +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-25): Cannot use builtin function name "dataoffset" as identifier name. diff --git a/test/libyul/yulSyntaxTests/datasize_shadowing.yul b/test/libyul/yulSyntaxTests/datasize_shadowing.yul index 379401754cac..79e500949e8b 100644 --- a/test/libyul/yulSyntaxTests/datasize_shadowing.yul +++ b/test/libyul/yulSyntaxTests/datasize_shadowing.yul @@ -1,5 +1,7 @@ { function datasize(a) -> b {} } +// ==== +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-23): Cannot use builtin function name "datasize" as identifier name. diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof.yul new file mode 100644 index 000000000000..552620a72a0e --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof.yul @@ -0,0 +1,12 @@ +object "a" { + code { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + + data "data1" "Hello, World!" +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul new file mode 100644 index 000000000000..3622a39648e1 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul @@ -0,0 +1,13 @@ +object "a" { + code { + mstore(0, auxdataloadn("0")) + return(0, 32) + } + + data "data1" "Hello, World!" + } + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 5859: (55-58): Function expects number literal. \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_value.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_value.yul new file mode 100644 index 000000000000..08e8037842ed --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_value.yul @@ -0,0 +1,14 @@ +object "a" { + code { + mstore(0, auxdataloadn(0x01FFFF)) + return(0, 32) + } + + data "data1" "Hello, World!" +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 5202: (55-63): Invalid auxdataloadn argument value. Offset must be in range 0...0xFFFF diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_offset_too_high.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_offset_too_high.yul new file mode 100644 index 000000000000..1d163c232ca6 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_offset_too_high.yul @@ -0,0 +1,13 @@ +object "a" { + code { + { + mstore(0, auxdataloadn(0xffe0)) + return(0, 32) + } + } + data "data1" hex"48656c6c6f2c20576f726c6421" +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// CodeGenerationError 3965: The highest accessed data offset exceeds the maximum possible size of the static auxdata section. diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul new file mode 100644 index 000000000000..f6af43217faf --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul @@ -0,0 +1,14 @@ +object "a" { + code { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + + data "data1" "Hello, World!" +} + +// ==== +// bytecodeFormat: legacy +// ---- +// DeclarationError 7223: (42-54): Builtin function "auxdataloadn" is only available in EOF. +// TypeError 3950: (42-57): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libyul/yulSyntaxTests/eof/builtin_function_literal.yul b/test/libyul/yulSyntaxTests/eof/builtin_function_literal.yul new file mode 100644 index 000000000000..d70f5a7bf006 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/builtin_function_literal.yul @@ -0,0 +1,9 @@ +{ + auxdataloadn(x,1) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 7000: (6-18): Function "auxdataloadn" expects 1 arguments but got 2. +// TypeError 9114: (6-18): Function expects direct literals as arguments. +// DeclarationError 8198: (19-20): Identifier "x" not found. diff --git a/test/libyul/yulSyntaxTests/eof/call_instruction_in_eof.yul b/test/libyul/yulSyntaxTests/eof/call_instruction_in_eof.yul new file mode 100644 index 000000000000..d26af22a70dc --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/call_instruction_in_eof.yul @@ -0,0 +1,13 @@ +object "a" { + code { + let success := call(gas(), 0x1, 0, 128, 4, 128, 0) + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (47-51): The "call" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 9132: (52-55): The "gas" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (52-57): Expected expression to evaluate to one value, but got 0 values instead. +// DeclarationError 3812: (32-82): Variable count mismatch for declaration of "success": 1 variables and 0 values. diff --git a/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul b/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul new file mode 100644 index 000000000000..1d8ae6ddc588 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul @@ -0,0 +1,13 @@ +object "a" { + code { + callf() + jumpf() + retf() + } +} +// ==== +// bytecodeFormat: legacy,>=EOFv1 +// ---- +// DeclarationError 4619: (32-37): Function "callf" not found. +// DeclarationError 4619: (48-53): Function "jumpf" not found. +// DeclarationError 4619: (64-68): Function "retf" not found. diff --git a/test/libyul/yulSyntaxTests/eof/create2_in_eof.yul b/test/libyul/yulSyntaxTests/eof/create2_in_eof.yul new file mode 100644 index 000000000000..77c10694749b --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/create2_in_eof.yul @@ -0,0 +1,11 @@ +object "a" { + code { + pop(create2(0, 0, 0, 0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (36-43): The "create2" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (36-55): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libyul/yulSyntaxTests/eof/datacopy_shadowing.yul b/test/libyul/yulSyntaxTests/eof/datacopy_shadowing.yul new file mode 100644 index 000000000000..b44c2ba0d19f --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/datacopy_shadowing.yul @@ -0,0 +1,7 @@ +{ + function datacopy(a, b, c) {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 5017: (6-35): The identifier "datacopy" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/dataoffset_shadowing.yul b/test/libyul/yulSyntaxTests/eof/dataoffset_shadowing.yul new file mode 100644 index 000000000000..7c525bcc45e5 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/dataoffset_shadowing.yul @@ -0,0 +1,7 @@ +{ + function dataoffset(a) -> b {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 5017: (6-36): The identifier "dataoffset" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/datasize_shadowing.yul b/test/libyul/yulSyntaxTests/eof/datasize_shadowing.yul new file mode 100644 index 000000000000..57345184256c --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/datasize_shadowing.yul @@ -0,0 +1,7 @@ +{ + function datasize(a) -> b {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 5017: (6-34): The identifier "datasize" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul new file mode 100644 index 000000000000..71137488f293 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul @@ -0,0 +1,33 @@ +{ + auxdataloadn(0) + dataloadn(0) + eofcreate("name", 0, 0, 0, 0) + returncontract("name", 0, 0) + rjump() + rjumpi() + callf(0) + jumpf(0) + retf() + extcall(0, 1, 2, 3) + extstaticcall(0, 1, 2) + extdelegatecall(0, 1, 2) + swapn() + dupn() +} +// ==== +// bytecodeFormat: legacy +// ---- +// DeclarationError 7223: (6-18): Builtin function "auxdataloadn" is only available in EOF. +// DeclarationError 4619: (26-35): Function "dataloadn" not found. +// DeclarationError 7223: (43-52): Builtin function "eofcreate" is only available in EOF. +// DeclarationError 7223: (77-91): Builtin function "returncontract" is only available in EOF. +// DeclarationError 4619: (110-115): Function "rjump" not found. +// DeclarationError 4619: (122-128): Function "rjumpi" not found. +// DeclarationError 4619: (135-140): Function "callf" not found. +// DeclarationError 4619: (148-153): Function "jumpf" not found. +// DeclarationError 4619: (161-165): Function "retf" not found. +// TypeError 4328: (172-179): The "extcall" instruction is only available in EOF. +// TypeError 4328: (196-209): The "extstaticcall" instruction is only available in EOF. +// TypeError 4328: (223-238): The "extdelegatecall" instruction is only available in EOF. +// DeclarationError 4619: (252-257): Function "swapn" not found. +// DeclarationError 4619: (264-268): Function "dupn" not found. diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul new file mode 100644 index 000000000000..313e17884ee5 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul @@ -0,0 +1,18 @@ +{ + function auxdataloadn() {} + function dataloadn() {} + function eofcreate() {} + function returncontract() {} + function rjump() {} + function rjumpi() {} + function callf() {} + function jumpf() {} + function retf() {} + function extcall() {} + function extstaticcall() {} + function extdelegatecall() {} + function swapn() {} + function dupn() {} +} +// ==== +// bytecodeFormat: legacy \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/eof_names_reserved_in_eof.yul b/test/libyul/yulSyntaxTests/eof/eof_names_reserved_in_eof.yul new file mode 100644 index 000000000000..063f8f4a835a --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_names_reserved_in_eof.yul @@ -0,0 +1,17 @@ +{ + function auxdataloadn() {} + function eofcreate() {} + function returncontract() {} + function extcall() {} + function extdelegatecall() {} + function extstaticcall() {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (15-27): Cannot use builtin function name "auxdataloadn" as identifier name. +// ParserError 5568: (46-55): Cannot use builtin function name "eofcreate" as identifier name. +// ParserError 5568: (74-88): Cannot use builtin function name "returncontract" as identifier name. +// ParserError 5568: (107-114): Cannot use builtin function name "extcall" as identifier name. +// ParserError 5568: (133-148): Cannot use builtin function name "extdelegatecall" as identifier name. +// ParserError 5568: (167-180): Cannot use builtin function name "extstaticcall" as identifier name. diff --git a/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul b/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul new file mode 100644 index 000000000000..6992e4003fb8 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul @@ -0,0 +1,21 @@ +{ + function dataloadn() {} + function rjump() {} + function rjumpi() {} + function callf() {} + function jumpf() {} + function retf() {} + function swapn() {} + function dupn() {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 5017: (6-29): The identifier "dataloadn" is reserved and can not be used. +// DeclarationError 5017: (34-53): The identifier "rjump" is reserved and can not be used. +// DeclarationError 5017: (58-78): The identifier "rjumpi" is reserved and can not be used. +// DeclarationError 5017: (83-102): The identifier "callf" is reserved and can not be used. +// DeclarationError 5017: (107-126): The identifier "jumpf" is reserved and can not be used. +// DeclarationError 5017: (131-149): The identifier "retf" is reserved and can not be used. +// DeclarationError 5017: (154-173): The identifier "swapn" is reserved and can not be used. +// DeclarationError 5017: (178-196): The identifier "dupn" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate.yul b/test/libyul/yulSyntaxTests/eof/eofcreate.yul new file mode 100644 index 000000000000..4169d52ab3b8 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eofcreate.yul @@ -0,0 +1,13 @@ +object "a" { + code { + let addr := eofcreate("b", 0, 0, 0, 0) + return(0, 0) + } + + object "b" { + code {} + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object.yul b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object.yul new file mode 100644 index 000000000000..f3acc8277511 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object.yul @@ -0,0 +1,11 @@ +object "a" { + code { + mstore(0, eofcreate("b", 0, 0, 0, 0)) + return(0, 32) + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 8970: (52-55): Unknown object "b". diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul new file mode 100644 index 000000000000..1e9fad7d0244 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul @@ -0,0 +1,13 @@ +object "a" { + code { + mstore(0, eofcreate("data1", 0, 0, 0, 0)) + return(0, 32) + } + + data "data1" "Hello, World!" +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 7575: (52-59): Data name "data1" cannot be used as an argument of eofcreate/returncontract. An object name is only acceptable. diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_path.yul b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_path.yul new file mode 100644 index 000000000000..7efaada8bcd4 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_path.yul @@ -0,0 +1,18 @@ +object "a" { + code { + mstore(0, eofcreate("a.b", 0, 0, 0, 0)) + mstore(0, eofcreate("a", 0, 0, 0, 0)) + return(0, 32) + } + + object "b" { + code {} + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 2186: (52-57): Name required but path given as "eofcreate" argument. +// TypeError 8970: (52-57): Unknown object "a.b". +// TypeError 8970: (100-103): Unknown object "a". diff --git a/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul new file mode 100644 index 000000000000..021c98dd3c6f --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul @@ -0,0 +1,10 @@ +object "a" { + code { + function extcall() {} + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (41-48): Cannot use builtin function name "extcall" as identifier name. diff --git a/test/libyul/yulSyntaxTests/eof/extcalls.yul b/test/libyul/yulSyntaxTests/eof/extcalls.yul new file mode 100644 index 000000000000..a8352c254d8e --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extcalls.yul @@ -0,0 +1,11 @@ +object "a" { + code { + pop(extcall(address(), 0, 0, 0)) + pop(extdelegatecall(address(), 0, 0)) + pop(extstaticcall(address(), 0, 0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul new file mode 100644 index 000000000000..1a67818025d4 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul @@ -0,0 +1,14 @@ +{ + pop(extcall(address(), 0, 0, 0)) + pop(extdelegatecall(address(), 0, 0)) + pop(extstaticcall(address(), 0, 0)) +} +// ==== +// bytecodeFormat: legacy +// ---- +// TypeError 4328: (10-17): The "extcall" instruction is only available in EOF. +// TypeError 3950: (10-37): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 4328: (47-62): The "extdelegatecall" instruction is only available in EOF. +// TypeError 3950: (47-79): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 4328: (89-102): The "extstaticcall" instruction is only available in EOF. +// TypeError 3950: (89-119): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libyul/yulSyntaxTests/eof/extcodehash_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extcodehash_in_eof.yul new file mode 100644 index 000000000000..79bfb4499386 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extcodehash_in_eof.yul @@ -0,0 +1,11 @@ +object "a" { + code { + pop(extcodehash(0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (36-47): The "extcodehash" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (36-50): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul new file mode 100644 index 000000000000..e352f1b3a650 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul @@ -0,0 +1,10 @@ +object "a" { + code { + function extdelegatecall() {} + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (41-56): Cannot use builtin function name "extdelegatecall" as identifier name. diff --git a/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul new file mode 100644 index 000000000000..0db2313a034a --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul @@ -0,0 +1,10 @@ +object "a" { + code { + function extstaticcall() {} + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (41-54): Cannot use builtin function name "extstaticcall" as identifier name. diff --git a/test/libyul/yulSyntaxTests/eof/legacy_calls_in_eof.yul b/test/libyul/yulSyntaxTests/eof/legacy_calls_in_eof.yul new file mode 100644 index 000000000000..4ed95e6c3f5a --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/legacy_calls_in_eof.yul @@ -0,0 +1,17 @@ +object "a" { + code { + pop(call(address(), 0, 0, 10)) + pop(staticcall(address(), 0, 0)) + pop(delegatecall(address(), 0, 0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (36-40): The "call" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (36-61): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 9132: (75-85): The "staticcall" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (75-102): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 9132: (116-128): The "delegatecall" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (116-145): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libyul/yulSyntaxTests/eof/loadimmutable_shadowing.yul b/test/libyul/yulSyntaxTests/eof/loadimmutable_shadowing.yul new file mode 100644 index 000000000000..a9fc2606752f --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/loadimmutable_shadowing.yul @@ -0,0 +1,8 @@ +{ + function loadimmutable(a) {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// dialect: evm +// ---- +// DeclarationError 5017: (6-34): The identifier "loadimmutable" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/object_name_in_eof.yul b/test/libyul/yulSyntaxTests/eof/object_name_in_eof.yul new file mode 100644 index 000000000000..bcbbca624cef --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/object_name_in_eof.yul @@ -0,0 +1,9 @@ +object "a.b" { + code {} +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// SyntaxError 9822: (24-26): The object name "a.b" is invalid in EOF context. Object names must not contain 'dot' character. diff --git a/test/libyul/yulSyntaxTests/eof/passing_builtin_with_literal_argument_into_literal_argument.yul b/test/libyul/yulSyntaxTests/eof/passing_builtin_with_literal_argument_into_literal_argument.yul new file mode 100644 index 000000000000..d46c1671b6bf --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/passing_builtin_with_literal_argument_into_literal_argument.yul @@ -0,0 +1,8 @@ +{ + auxdataloadn(auxdataloadn(0)) +} +// ==== +// bytecodeFormat: >=EOFv1 +// dialect: evm +// ---- +// TypeError 9114: (6-18): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/eof/returncontract.yul b/test/libyul/yulSyntaxTests/eof/returncontract.yul new file mode 100644 index 000000000000..2d193a800d17 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/returncontract.yul @@ -0,0 +1,12 @@ +object "b" { + code { + returncontract("c", 0, 0) + } + + object "c" { + code {} + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 diff --git a/test/libyul/yulSyntaxTests/eof/returncontract_invalid_object.yul b/test/libyul/yulSyntaxTests/eof/returncontract_invalid_object.yul new file mode 100644 index 000000000000..be345ff0a925 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/returncontract_invalid_object.yul @@ -0,0 +1,10 @@ +object "a" { + code { + returncontract("b", 0, 0) + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 8970: (47-50): Unknown object "b". diff --git a/test/libyul/yulSyntaxTests/eof/rjump_rjumpi.yul b/test/libyul/yulSyntaxTests/eof/rjump_rjumpi.yul new file mode 100644 index 000000000000..00042ae65076 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/rjump_rjumpi.yul @@ -0,0 +1,11 @@ +object "a" { + code { + rjump() + rjumpi() + } +} +// ==== +// bytecodeFormat: legacy,>=EOFv1 +// ---- +// DeclarationError 4619: (32-37): Function "rjump" not found. +// DeclarationError 4619: (48-54): Function "rjumpi" not found. diff --git a/test/libyul/yulSyntaxTests/eof/selfdestruct.yul b/test/libyul/yulSyntaxTests/eof/selfdestruct.yul new file mode 100644 index 000000000000..7920511eb0c4 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/selfdestruct.yul @@ -0,0 +1,7 @@ +{ + selfdestruct(0x02) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (3-15): The "selfdestruct" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). diff --git a/test/libyul/yulSyntaxTests/eof/setimmutable_shadowing.yul b/test/libyul/yulSyntaxTests/eof/setimmutable_shadowing.yul new file mode 100644 index 000000000000..83d9a33f6821 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/setimmutable_shadowing.yul @@ -0,0 +1,8 @@ +{ + function setimmutable(a, b) {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// dialect: evm +// ---- +// DeclarationError 5017: (6-36): The identifier "setimmutable" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/too_large_code_section.yul b/test/libyul/yulSyntaxTests/eof/too_large_code_section.yul new file mode 100644 index 000000000000..ce69a69a51c5 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/too_large_code_section.yul @@ -0,0 +1,1880 @@ +{ + sstore("112233445566778899aabbccddee0000", "112233445566778899aabbccddee0000") + sstore("112233445566778899aabbccddee0001", "112233445566778899aabbccddee0001") + sstore("112233445566778899aabbccddee0002", "112233445566778899aabbccddee0002") + sstore("112233445566778899aabbccddee0003", "112233445566778899aabbccddee0003") + sstore("112233445566778899aabbccddee0004", "112233445566778899aabbccddee0004") + sstore("112233445566778899aabbccddee0005", "112233445566778899aabbccddee0005") + sstore("112233445566778899aabbccddee0006", "112233445566778899aabbccddee0006") + sstore("112233445566778899aabbccddee0007", "112233445566778899aabbccddee0007") + sstore("112233445566778899aabbccddee0008", "112233445566778899aabbccddee0008") + sstore("112233445566778899aabbccddee0009", "112233445566778899aabbccddee0009") + sstore("112233445566778899aabbccddee000a", "112233445566778899aabbccddee000a") + sstore("112233445566778899aabbccddee000b", "112233445566778899aabbccddee000b") + sstore("112233445566778899aabbccddee000c", "112233445566778899aabbccddee000c") + sstore("112233445566778899aabbccddee000d", "112233445566778899aabbccddee000d") + sstore("112233445566778899aabbccddee000e", "112233445566778899aabbccddee000e") + sstore("112233445566778899aabbccddee000f", "112233445566778899aabbccddee000f") + sstore("112233445566778899aabbccddee0010", "112233445566778899aabbccddee0010") + sstore("112233445566778899aabbccddee0011", "112233445566778899aabbccddee0011") + sstore("112233445566778899aabbccddee0012", "112233445566778899aabbccddee0012") + sstore("112233445566778899aabbccddee0013", "112233445566778899aabbccddee0013") + sstore("112233445566778899aabbccddee0014", "112233445566778899aabbccddee0014") + sstore("112233445566778899aabbccddee0015", "112233445566778899aabbccddee0015") + sstore("112233445566778899aabbccddee0016", "112233445566778899aabbccddee0016") + sstore("112233445566778899aabbccddee0017", "112233445566778899aabbccddee0017") + sstore("112233445566778899aabbccddee0018", "112233445566778899aabbccddee0018") + sstore("112233445566778899aabbccddee0019", "112233445566778899aabbccddee0019") + sstore("112233445566778899aabbccddee001a", "112233445566778899aabbccddee001a") + sstore("112233445566778899aabbccddee001b", "112233445566778899aabbccddee001b") + sstore("112233445566778899aabbccddee001c", "112233445566778899aabbccddee001c") + sstore("112233445566778899aabbccddee001d", "112233445566778899aabbccddee001d") + sstore("112233445566778899aabbccddee001e", "112233445566778899aabbccddee001e") + sstore("112233445566778899aabbccddee001f", "112233445566778899aabbccddee001f") + sstore("112233445566778899aabbccddee0020", "112233445566778899aabbccddee0020") + sstore("112233445566778899aabbccddee0021", "112233445566778899aabbccddee0021") + sstore("112233445566778899aabbccddee0022", "112233445566778899aabbccddee0022") + sstore("112233445566778899aabbccddee0023", "112233445566778899aabbccddee0023") + sstore("112233445566778899aabbccddee0024", "112233445566778899aabbccddee0024") + sstore("112233445566778899aabbccddee0025", "112233445566778899aabbccddee0025") + sstore("112233445566778899aabbccddee0026", "112233445566778899aabbccddee0026") + sstore("112233445566778899aabbccddee0027", "112233445566778899aabbccddee0027") + sstore("112233445566778899aabbccddee0028", "112233445566778899aabbccddee0028") + sstore("112233445566778899aabbccddee0029", "112233445566778899aabbccddee0029") + sstore("112233445566778899aabbccddee002a", "112233445566778899aabbccddee002a") + sstore("112233445566778899aabbccddee002b", "112233445566778899aabbccddee002b") + sstore("112233445566778899aabbccddee002c", "112233445566778899aabbccddee002c") + sstore("112233445566778899aabbccddee002d", "112233445566778899aabbccddee002d") + sstore("112233445566778899aabbccddee002e", "112233445566778899aabbccddee002e") + sstore("112233445566778899aabbccddee002f", "112233445566778899aabbccddee002f") + sstore("112233445566778899aabbccddee0030", "112233445566778899aabbccddee0030") + sstore("112233445566778899aabbccddee0031", "112233445566778899aabbccddee0031") + sstore("112233445566778899aabbccddee0032", "112233445566778899aabbccddee0032") + sstore("112233445566778899aabbccddee0033", "112233445566778899aabbccddee0033") + sstore("112233445566778899aabbccddee0034", "112233445566778899aabbccddee0034") + sstore("112233445566778899aabbccddee0035", "112233445566778899aabbccddee0035") + sstore("112233445566778899aabbccddee0036", "112233445566778899aabbccddee0036") + sstore("112233445566778899aabbccddee0037", "112233445566778899aabbccddee0037") + sstore("112233445566778899aabbccddee0038", "112233445566778899aabbccddee0038") + sstore("112233445566778899aabbccddee0039", "112233445566778899aabbccddee0039") + sstore("112233445566778899aabbccddee003a", "112233445566778899aabbccddee003a") + sstore("112233445566778899aabbccddee003b", "112233445566778899aabbccddee003b") + sstore("112233445566778899aabbccddee003c", "112233445566778899aabbccddee003c") + sstore("112233445566778899aabbccddee003d", "112233445566778899aabbccddee003d") + sstore("112233445566778899aabbccddee003e", "112233445566778899aabbccddee003e") + sstore("112233445566778899aabbccddee003f", "112233445566778899aabbccddee003f") + sstore("112233445566778899aabbccddee0040", "112233445566778899aabbccddee0040") + sstore("112233445566778899aabbccddee0041", "112233445566778899aabbccddee0041") + sstore("112233445566778899aabbccddee0042", "112233445566778899aabbccddee0042") + sstore("112233445566778899aabbccddee0043", "112233445566778899aabbccddee0043") + sstore("112233445566778899aabbccddee0044", "112233445566778899aabbccddee0044") + sstore("112233445566778899aabbccddee0045", "112233445566778899aabbccddee0045") + sstore("112233445566778899aabbccddee0046", "112233445566778899aabbccddee0046") + sstore("112233445566778899aabbccddee0047", "112233445566778899aabbccddee0047") + sstore("112233445566778899aabbccddee0048", "112233445566778899aabbccddee0048") + sstore("112233445566778899aabbccddee0049", "112233445566778899aabbccddee0049") + sstore("112233445566778899aabbccddee004a", "112233445566778899aabbccddee004a") + sstore("112233445566778899aabbccddee004b", "112233445566778899aabbccddee004b") + sstore("112233445566778899aabbccddee004c", "112233445566778899aabbccddee004c") + sstore("112233445566778899aabbccddee004d", "112233445566778899aabbccddee004d") + sstore("112233445566778899aabbccddee004e", "112233445566778899aabbccddee004e") + sstore("112233445566778899aabbccddee004f", "112233445566778899aabbccddee004f") + sstore("112233445566778899aabbccddee0050", "112233445566778899aabbccddee0050") + sstore("112233445566778899aabbccddee0051", "112233445566778899aabbccddee0051") + sstore("112233445566778899aabbccddee0052", "112233445566778899aabbccddee0052") + sstore("112233445566778899aabbccddee0053", "112233445566778899aabbccddee0053") + sstore("112233445566778899aabbccddee0054", "112233445566778899aabbccddee0054") + sstore("112233445566778899aabbccddee0055", "112233445566778899aabbccddee0055") + sstore("112233445566778899aabbccddee0056", "112233445566778899aabbccddee0056") + sstore("112233445566778899aabbccddee0057", "112233445566778899aabbccddee0057") + sstore("112233445566778899aabbccddee0058", "112233445566778899aabbccddee0058") + sstore("112233445566778899aabbccddee0059", "112233445566778899aabbccddee0059") + sstore("112233445566778899aabbccddee005a", "112233445566778899aabbccddee005a") + sstore("112233445566778899aabbccddee005b", "112233445566778899aabbccddee005b") + sstore("112233445566778899aabbccddee005c", "112233445566778899aabbccddee005c") + sstore("112233445566778899aabbccddee005d", "112233445566778899aabbccddee005d") + sstore("112233445566778899aabbccddee005e", "112233445566778899aabbccddee005e") + sstore("112233445566778899aabbccddee005f", "112233445566778899aabbccddee005f") + sstore("112233445566778899aabbccddee0060", "112233445566778899aabbccddee0060") + sstore("112233445566778899aabbccddee0061", "112233445566778899aabbccddee0061") + sstore("112233445566778899aabbccddee0062", "112233445566778899aabbccddee0062") + sstore("112233445566778899aabbccddee0063", "112233445566778899aabbccddee0063") + sstore("112233445566778899aabbccddee0064", "112233445566778899aabbccddee0064") + sstore("112233445566778899aabbccddee0065", "112233445566778899aabbccddee0065") + sstore("112233445566778899aabbccddee0066", "112233445566778899aabbccddee0066") + sstore("112233445566778899aabbccddee0067", "112233445566778899aabbccddee0067") + sstore("112233445566778899aabbccddee0068", "112233445566778899aabbccddee0068") + sstore("112233445566778899aabbccddee0069", "112233445566778899aabbccddee0069") + sstore("112233445566778899aabbccddee006a", "112233445566778899aabbccddee006a") + sstore("112233445566778899aabbccddee006b", "112233445566778899aabbccddee006b") + sstore("112233445566778899aabbccddee006c", "112233445566778899aabbccddee006c") + sstore("112233445566778899aabbccddee006d", "112233445566778899aabbccddee006d") + sstore("112233445566778899aabbccddee006e", "112233445566778899aabbccddee006e") + sstore("112233445566778899aabbccddee006f", "112233445566778899aabbccddee006f") + sstore("112233445566778899aabbccddee0070", "112233445566778899aabbccddee0070") + sstore("112233445566778899aabbccddee0071", "112233445566778899aabbccddee0071") + sstore("112233445566778899aabbccddee0072", "112233445566778899aabbccddee0072") + sstore("112233445566778899aabbccddee0073", "112233445566778899aabbccddee0073") + sstore("112233445566778899aabbccddee0074", "112233445566778899aabbccddee0074") + sstore("112233445566778899aabbccddee0075", "112233445566778899aabbccddee0075") + sstore("112233445566778899aabbccddee0076", "112233445566778899aabbccddee0076") + sstore("112233445566778899aabbccddee0077", "112233445566778899aabbccddee0077") + sstore("112233445566778899aabbccddee0078", "112233445566778899aabbccddee0078") + sstore("112233445566778899aabbccddee0079", "112233445566778899aabbccddee0079") + sstore("112233445566778899aabbccddee007a", "112233445566778899aabbccddee007a") + sstore("112233445566778899aabbccddee007b", "112233445566778899aabbccddee007b") + sstore("112233445566778899aabbccddee007c", "112233445566778899aabbccddee007c") + sstore("112233445566778899aabbccddee007d", "112233445566778899aabbccddee007d") + sstore("112233445566778899aabbccddee007e", "112233445566778899aabbccddee007e") + sstore("112233445566778899aabbccddee007f", "112233445566778899aabbccddee007f") + sstore("112233445566778899aabbccddee0080", "112233445566778899aabbccddee0080") + sstore("112233445566778899aabbccddee0081", "112233445566778899aabbccddee0081") + sstore("112233445566778899aabbccddee0082", "112233445566778899aabbccddee0082") + sstore("112233445566778899aabbccddee0083", "112233445566778899aabbccddee0083") + sstore("112233445566778899aabbccddee0084", "112233445566778899aabbccddee0084") + sstore("112233445566778899aabbccddee0085", "112233445566778899aabbccddee0085") + sstore("112233445566778899aabbccddee0086", "112233445566778899aabbccddee0086") + sstore("112233445566778899aabbccddee0087", "112233445566778899aabbccddee0087") + sstore("112233445566778899aabbccddee0088", "112233445566778899aabbccddee0088") + sstore("112233445566778899aabbccddee0089", "112233445566778899aabbccddee0089") + sstore("112233445566778899aabbccddee008a", "112233445566778899aabbccddee008a") + sstore("112233445566778899aabbccddee008b", "112233445566778899aabbccddee008b") + sstore("112233445566778899aabbccddee008c", "112233445566778899aabbccddee008c") + sstore("112233445566778899aabbccddee008d", "112233445566778899aabbccddee008d") + sstore("112233445566778899aabbccddee008e", "112233445566778899aabbccddee008e") + sstore("112233445566778899aabbccddee008f", "112233445566778899aabbccddee008f") + sstore("112233445566778899aabbccddee0090", "112233445566778899aabbccddee0090") + sstore("112233445566778899aabbccddee0091", "112233445566778899aabbccddee0091") + sstore("112233445566778899aabbccddee0092", "112233445566778899aabbccddee0092") + sstore("112233445566778899aabbccddee0093", "112233445566778899aabbccddee0093") + sstore("112233445566778899aabbccddee0094", "112233445566778899aabbccddee0094") + sstore("112233445566778899aabbccddee0095", "112233445566778899aabbccddee0095") + sstore("112233445566778899aabbccddee0096", "112233445566778899aabbccddee0096") + sstore("112233445566778899aabbccddee0097", "112233445566778899aabbccddee0097") + sstore("112233445566778899aabbccddee0098", "112233445566778899aabbccddee0098") + sstore("112233445566778899aabbccddee0099", "112233445566778899aabbccddee0099") + sstore("112233445566778899aabbccddee009a", "112233445566778899aabbccddee009a") + sstore("112233445566778899aabbccddee009b", "112233445566778899aabbccddee009b") + sstore("112233445566778899aabbccddee009c", "112233445566778899aabbccddee009c") + sstore("112233445566778899aabbccddee009d", "112233445566778899aabbccddee009d") + sstore("112233445566778899aabbccddee009e", "112233445566778899aabbccddee009e") + sstore("112233445566778899aabbccddee009f", "112233445566778899aabbccddee009f") + sstore("112233445566778899aabbccddee00a0", "112233445566778899aabbccddee00a0") + sstore("112233445566778899aabbccddee00a1", "112233445566778899aabbccddee00a1") + sstore("112233445566778899aabbccddee00a2", "112233445566778899aabbccddee00a2") + sstore("112233445566778899aabbccddee00a3", "112233445566778899aabbccddee00a3") + sstore("112233445566778899aabbccddee00a4", "112233445566778899aabbccddee00a4") + sstore("112233445566778899aabbccddee00a5", "112233445566778899aabbccddee00a5") + sstore("112233445566778899aabbccddee00a6", "112233445566778899aabbccddee00a6") + sstore("112233445566778899aabbccddee00a7", "112233445566778899aabbccddee00a7") + sstore("112233445566778899aabbccddee00a8", "112233445566778899aabbccddee00a8") + sstore("112233445566778899aabbccddee00a9", "112233445566778899aabbccddee00a9") + sstore("112233445566778899aabbccddee00aa", "112233445566778899aabbccddee00aa") + sstore("112233445566778899aabbccddee00ab", "112233445566778899aabbccddee00ab") + sstore("112233445566778899aabbccddee00ac", "112233445566778899aabbccddee00ac") + sstore("112233445566778899aabbccddee00ad", "112233445566778899aabbccddee00ad") + sstore("112233445566778899aabbccddee00ae", "112233445566778899aabbccddee00ae") + sstore("112233445566778899aabbccddee00af", "112233445566778899aabbccddee00af") + sstore("112233445566778899aabbccddee00b0", "112233445566778899aabbccddee00b0") + sstore("112233445566778899aabbccddee00b1", "112233445566778899aabbccddee00b1") + sstore("112233445566778899aabbccddee00b2", "112233445566778899aabbccddee00b2") + sstore("112233445566778899aabbccddee00b3", "112233445566778899aabbccddee00b3") + sstore("112233445566778899aabbccddee00b4", "112233445566778899aabbccddee00b4") + sstore("112233445566778899aabbccddee00b5", "112233445566778899aabbccddee00b5") + sstore("112233445566778899aabbccddee00b6", "112233445566778899aabbccddee00b6") + sstore("112233445566778899aabbccddee00b7", "112233445566778899aabbccddee00b7") + sstore("112233445566778899aabbccddee00b8", "112233445566778899aabbccddee00b8") + sstore("112233445566778899aabbccddee00b9", "112233445566778899aabbccddee00b9") + sstore("112233445566778899aabbccddee00ba", "112233445566778899aabbccddee00ba") + sstore("112233445566778899aabbccddee00bb", "112233445566778899aabbccddee00bb") + sstore("112233445566778899aabbccddee00bc", "112233445566778899aabbccddee00bc") + sstore("112233445566778899aabbccddee00bd", "112233445566778899aabbccddee00bd") + sstore("112233445566778899aabbccddee00be", "112233445566778899aabbccddee00be") + sstore("112233445566778899aabbccddee00bf", "112233445566778899aabbccddee00bf") + sstore("112233445566778899aabbccddee00c0", "112233445566778899aabbccddee00c0") + sstore("112233445566778899aabbccddee00c1", "112233445566778899aabbccddee00c1") + sstore("112233445566778899aabbccddee00c2", "112233445566778899aabbccddee00c2") + sstore("112233445566778899aabbccddee00c3", "112233445566778899aabbccddee00c3") + sstore("112233445566778899aabbccddee00c4", "112233445566778899aabbccddee00c4") + sstore("112233445566778899aabbccddee00c5", "112233445566778899aabbccddee00c5") + sstore("112233445566778899aabbccddee00c6", "112233445566778899aabbccddee00c6") + sstore("112233445566778899aabbccddee00c7", "112233445566778899aabbccddee00c7") + sstore("112233445566778899aabbccddee00c8", "112233445566778899aabbccddee00c8") + sstore("112233445566778899aabbccddee00c9", "112233445566778899aabbccddee00c9") + sstore("112233445566778899aabbccddee00ca", "112233445566778899aabbccddee00ca") + sstore("112233445566778899aabbccddee00cb", "112233445566778899aabbccddee00cb") + sstore("112233445566778899aabbccddee00cc", "112233445566778899aabbccddee00cc") + sstore("112233445566778899aabbccddee00cd", "112233445566778899aabbccddee00cd") + sstore("112233445566778899aabbccddee00ce", "112233445566778899aabbccddee00ce") + sstore("112233445566778899aabbccddee00cf", "112233445566778899aabbccddee00cf") + sstore("112233445566778899aabbccddee00d0", "112233445566778899aabbccddee00d0") + sstore("112233445566778899aabbccddee00d1", "112233445566778899aabbccddee00d1") + sstore("112233445566778899aabbccddee00d2", "112233445566778899aabbccddee00d2") + sstore("112233445566778899aabbccddee00d3", "112233445566778899aabbccddee00d3") + sstore("112233445566778899aabbccddee00d4", "112233445566778899aabbccddee00d4") + sstore("112233445566778899aabbccddee00d5", "112233445566778899aabbccddee00d5") + sstore("112233445566778899aabbccddee00d6", "112233445566778899aabbccddee00d6") + sstore("112233445566778899aabbccddee00d7", "112233445566778899aabbccddee00d7") + sstore("112233445566778899aabbccddee00d8", "112233445566778899aabbccddee00d8") + sstore("112233445566778899aabbccddee00d9", "112233445566778899aabbccddee00d9") + sstore("112233445566778899aabbccddee00da", "112233445566778899aabbccddee00da") + sstore("112233445566778899aabbccddee00db", "112233445566778899aabbccddee00db") + sstore("112233445566778899aabbccddee00dc", "112233445566778899aabbccddee00dc") + sstore("112233445566778899aabbccddee00dd", "112233445566778899aabbccddee00dd") + sstore("112233445566778899aabbccddee00de", "112233445566778899aabbccddee00de") + sstore("112233445566778899aabbccddee00df", "112233445566778899aabbccddee00df") + sstore("112233445566778899aabbccddee00e0", "112233445566778899aabbccddee00e0") + sstore("112233445566778899aabbccddee00e1", "112233445566778899aabbccddee00e1") + sstore("112233445566778899aabbccddee00e2", "112233445566778899aabbccddee00e2") + sstore("112233445566778899aabbccddee00e3", "112233445566778899aabbccddee00e3") + sstore("112233445566778899aabbccddee00e4", "112233445566778899aabbccddee00e4") + sstore("112233445566778899aabbccddee00e5", "112233445566778899aabbccddee00e5") + sstore("112233445566778899aabbccddee00e6", "112233445566778899aabbccddee00e6") + sstore("112233445566778899aabbccddee00e7", "112233445566778899aabbccddee00e7") + sstore("112233445566778899aabbccddee00e8", "112233445566778899aabbccddee00e8") + sstore("112233445566778899aabbccddee00e9", "112233445566778899aabbccddee00e9") + sstore("112233445566778899aabbccddee00ea", "112233445566778899aabbccddee00ea") + sstore("112233445566778899aabbccddee00eb", "112233445566778899aabbccddee00eb") + sstore("112233445566778899aabbccddee00ec", "112233445566778899aabbccddee00ec") + sstore("112233445566778899aabbccddee00ed", "112233445566778899aabbccddee00ed") + sstore("112233445566778899aabbccddee00ee", "112233445566778899aabbccddee00ee") + sstore("112233445566778899aabbccddee00ef", "112233445566778899aabbccddee00ef") + sstore("112233445566778899aabbccddee00f0", "112233445566778899aabbccddee00f0") + sstore("112233445566778899aabbccddee00f1", "112233445566778899aabbccddee00f1") + sstore("112233445566778899aabbccddee00f2", "112233445566778899aabbccddee00f2") + sstore("112233445566778899aabbccddee00f3", "112233445566778899aabbccddee00f3") + sstore("112233445566778899aabbccddee00f4", "112233445566778899aabbccddee00f4") + sstore("112233445566778899aabbccddee00f5", "112233445566778899aabbccddee00f5") + sstore("112233445566778899aabbccddee00f6", "112233445566778899aabbccddee00f6") + sstore("112233445566778899aabbccddee00f7", "112233445566778899aabbccddee00f7") + sstore("112233445566778899aabbccddee00f8", "112233445566778899aabbccddee00f8") + sstore("112233445566778899aabbccddee00f9", "112233445566778899aabbccddee00f9") + sstore("112233445566778899aabbccddee00fa", "112233445566778899aabbccddee00fa") + sstore("112233445566778899aabbccddee00fb", "112233445566778899aabbccddee00fb") + sstore("112233445566778899aabbccddee00fc", "112233445566778899aabbccddee00fc") + sstore("112233445566778899aabbccddee00fd", "112233445566778899aabbccddee00fd") + sstore("112233445566778899aabbccddee00fe", "112233445566778899aabbccddee00fe") + sstore("112233445566778899aabbccddee00ff", "112233445566778899aabbccddee00ff") + sstore("112233445566778899aabbccddee0100", "112233445566778899aabbccddee0100") + sstore("112233445566778899aabbccddee0101", "112233445566778899aabbccddee0101") + sstore("112233445566778899aabbccddee0102", "112233445566778899aabbccddee0102") + sstore("112233445566778899aabbccddee0103", "112233445566778899aabbccddee0103") + sstore("112233445566778899aabbccddee0104", "112233445566778899aabbccddee0104") + sstore("112233445566778899aabbccddee0105", "112233445566778899aabbccddee0105") + sstore("112233445566778899aabbccddee0106", "112233445566778899aabbccddee0106") + sstore("112233445566778899aabbccddee0107", "112233445566778899aabbccddee0107") + sstore("112233445566778899aabbccddee0108", "112233445566778899aabbccddee0108") + sstore("112233445566778899aabbccddee0109", "112233445566778899aabbccddee0109") + sstore("112233445566778899aabbccddee010a", "112233445566778899aabbccddee010a") + sstore("112233445566778899aabbccddee010b", "112233445566778899aabbccddee010b") + sstore("112233445566778899aabbccddee010c", "112233445566778899aabbccddee010c") + sstore("112233445566778899aabbccddee010d", "112233445566778899aabbccddee010d") + sstore("112233445566778899aabbccddee010e", "112233445566778899aabbccddee010e") + sstore("112233445566778899aabbccddee010f", "112233445566778899aabbccddee010f") + sstore("112233445566778899aabbccddee0110", "112233445566778899aabbccddee0110") + sstore("112233445566778899aabbccddee0111", "112233445566778899aabbccddee0111") + sstore("112233445566778899aabbccddee0112", "112233445566778899aabbccddee0112") + sstore("112233445566778899aabbccddee0113", "112233445566778899aabbccddee0113") + sstore("112233445566778899aabbccddee0114", "112233445566778899aabbccddee0114") + sstore("112233445566778899aabbccddee0115", "112233445566778899aabbccddee0115") + sstore("112233445566778899aabbccddee0116", "112233445566778899aabbccddee0116") + sstore("112233445566778899aabbccddee0117", "112233445566778899aabbccddee0117") + sstore("112233445566778899aabbccddee0118", "112233445566778899aabbccddee0118") + sstore("112233445566778899aabbccddee0119", "112233445566778899aabbccddee0119") + sstore("112233445566778899aabbccddee011a", "112233445566778899aabbccddee011a") + sstore("112233445566778899aabbccddee011b", "112233445566778899aabbccddee011b") + sstore("112233445566778899aabbccddee011c", "112233445566778899aabbccddee011c") + sstore("112233445566778899aabbccddee011d", "112233445566778899aabbccddee011d") + sstore("112233445566778899aabbccddee011e", "112233445566778899aabbccddee011e") + sstore("112233445566778899aabbccddee011f", "112233445566778899aabbccddee011f") + sstore("112233445566778899aabbccddee0120", "112233445566778899aabbccddee0120") + sstore("112233445566778899aabbccddee0121", "112233445566778899aabbccddee0121") + sstore("112233445566778899aabbccddee0122", "112233445566778899aabbccddee0122") + sstore("112233445566778899aabbccddee0123", "112233445566778899aabbccddee0123") + sstore("112233445566778899aabbccddee0124", "112233445566778899aabbccddee0124") + sstore("112233445566778899aabbccddee0125", "112233445566778899aabbccddee0125") + sstore("112233445566778899aabbccddee0126", "112233445566778899aabbccddee0126") + sstore("112233445566778899aabbccddee0127", "112233445566778899aabbccddee0127") + sstore("112233445566778899aabbccddee0128", "112233445566778899aabbccddee0128") + sstore("112233445566778899aabbccddee0129", "112233445566778899aabbccddee0129") + sstore("112233445566778899aabbccddee012a", "112233445566778899aabbccddee012a") + sstore("112233445566778899aabbccddee012b", "112233445566778899aabbccddee012b") + sstore("112233445566778899aabbccddee012c", "112233445566778899aabbccddee012c") + sstore("112233445566778899aabbccddee012d", "112233445566778899aabbccddee012d") + sstore("112233445566778899aabbccddee012e", "112233445566778899aabbccddee012e") + sstore("112233445566778899aabbccddee012f", "112233445566778899aabbccddee012f") + sstore("112233445566778899aabbccddee0130", "112233445566778899aabbccddee0130") + sstore("112233445566778899aabbccddee0131", "112233445566778899aabbccddee0131") + sstore("112233445566778899aabbccddee0132", "112233445566778899aabbccddee0132") + sstore("112233445566778899aabbccddee0133", "112233445566778899aabbccddee0133") + sstore("112233445566778899aabbccddee0134", "112233445566778899aabbccddee0134") + sstore("112233445566778899aabbccddee0135", "112233445566778899aabbccddee0135") + sstore("112233445566778899aabbccddee0136", "112233445566778899aabbccddee0136") + sstore("112233445566778899aabbccddee0137", "112233445566778899aabbccddee0137") + sstore("112233445566778899aabbccddee0138", "112233445566778899aabbccddee0138") + sstore("112233445566778899aabbccddee0139", "112233445566778899aabbccddee0139") + sstore("112233445566778899aabbccddee013a", "112233445566778899aabbccddee013a") + sstore("112233445566778899aabbccddee013b", "112233445566778899aabbccddee013b") + sstore("112233445566778899aabbccddee013c", "112233445566778899aabbccddee013c") + sstore("112233445566778899aabbccddee013d", "112233445566778899aabbccddee013d") + sstore("112233445566778899aabbccddee013e", "112233445566778899aabbccddee013e") + sstore("112233445566778899aabbccddee013f", "112233445566778899aabbccddee013f") + sstore("112233445566778899aabbccddee0140", "112233445566778899aabbccddee0140") + sstore("112233445566778899aabbccddee0141", "112233445566778899aabbccddee0141") + sstore("112233445566778899aabbccddee0142", "112233445566778899aabbccddee0142") + sstore("112233445566778899aabbccddee0143", "112233445566778899aabbccddee0143") + sstore("112233445566778899aabbccddee0144", "112233445566778899aabbccddee0144") + sstore("112233445566778899aabbccddee0145", "112233445566778899aabbccddee0145") + sstore("112233445566778899aabbccddee0146", "112233445566778899aabbccddee0146") + sstore("112233445566778899aabbccddee0147", "112233445566778899aabbccddee0147") + sstore("112233445566778899aabbccddee0148", "112233445566778899aabbccddee0148") + sstore("112233445566778899aabbccddee0149", "112233445566778899aabbccddee0149") + sstore("112233445566778899aabbccddee014a", "112233445566778899aabbccddee014a") + sstore("112233445566778899aabbccddee014b", "112233445566778899aabbccddee014b") + sstore("112233445566778899aabbccddee014c", "112233445566778899aabbccddee014c") + sstore("112233445566778899aabbccddee014d", "112233445566778899aabbccddee014d") + sstore("112233445566778899aabbccddee014e", "112233445566778899aabbccddee014e") + sstore("112233445566778899aabbccddee014f", "112233445566778899aabbccddee014f") + sstore("112233445566778899aabbccddee0150", "112233445566778899aabbccddee0150") + sstore("112233445566778899aabbccddee0151", "112233445566778899aabbccddee0151") + sstore("112233445566778899aabbccddee0152", "112233445566778899aabbccddee0152") + sstore("112233445566778899aabbccddee0153", "112233445566778899aabbccddee0153") + sstore("112233445566778899aabbccddee0154", "112233445566778899aabbccddee0154") + sstore("112233445566778899aabbccddee0155", "112233445566778899aabbccddee0155") + sstore("112233445566778899aabbccddee0156", "112233445566778899aabbccddee0156") + sstore("112233445566778899aabbccddee0157", "112233445566778899aabbccddee0157") + sstore("112233445566778899aabbccddee0158", "112233445566778899aabbccddee0158") + sstore("112233445566778899aabbccddee0159", "112233445566778899aabbccddee0159") + sstore("112233445566778899aabbccddee015a", "112233445566778899aabbccddee015a") + sstore("112233445566778899aabbccddee015b", "112233445566778899aabbccddee015b") + sstore("112233445566778899aabbccddee015c", "112233445566778899aabbccddee015c") + sstore("112233445566778899aabbccddee015d", "112233445566778899aabbccddee015d") + sstore("112233445566778899aabbccddee015e", "112233445566778899aabbccddee015e") + sstore("112233445566778899aabbccddee015f", "112233445566778899aabbccddee015f") + sstore("112233445566778899aabbccddee0160", "112233445566778899aabbccddee0160") + sstore("112233445566778899aabbccddee0161", "112233445566778899aabbccddee0161") + sstore("112233445566778899aabbccddee0162", "112233445566778899aabbccddee0162") + sstore("112233445566778899aabbccddee0163", "112233445566778899aabbccddee0163") + sstore("112233445566778899aabbccddee0164", "112233445566778899aabbccddee0164") + sstore("112233445566778899aabbccddee0165", "112233445566778899aabbccddee0165") + sstore("112233445566778899aabbccddee0166", "112233445566778899aabbccddee0166") + sstore("112233445566778899aabbccddee0167", "112233445566778899aabbccddee0167") + sstore("112233445566778899aabbccddee0168", "112233445566778899aabbccddee0168") + sstore("112233445566778899aabbccddee0169", "112233445566778899aabbccddee0169") + sstore("112233445566778899aabbccddee016a", "112233445566778899aabbccddee016a") + sstore("112233445566778899aabbccddee016b", "112233445566778899aabbccddee016b") + sstore("112233445566778899aabbccddee016c", "112233445566778899aabbccddee016c") + sstore("112233445566778899aabbccddee016d", "112233445566778899aabbccddee016d") + sstore("112233445566778899aabbccddee016e", "112233445566778899aabbccddee016e") + sstore("112233445566778899aabbccddee016f", "112233445566778899aabbccddee016f") + sstore("112233445566778899aabbccddee0170", "112233445566778899aabbccddee0170") + sstore("112233445566778899aabbccddee0171", "112233445566778899aabbccddee0171") + sstore("112233445566778899aabbccddee0172", "112233445566778899aabbccddee0172") + sstore("112233445566778899aabbccddee0173", "112233445566778899aabbccddee0173") + sstore("112233445566778899aabbccddee0174", "112233445566778899aabbccddee0174") + sstore("112233445566778899aabbccddee0175", "112233445566778899aabbccddee0175") + sstore("112233445566778899aabbccddee0176", "112233445566778899aabbccddee0176") + sstore("112233445566778899aabbccddee0177", "112233445566778899aabbccddee0177") + sstore("112233445566778899aabbccddee0178", "112233445566778899aabbccddee0178") + sstore("112233445566778899aabbccddee0179", "112233445566778899aabbccddee0179") + sstore("112233445566778899aabbccddee017a", "112233445566778899aabbccddee017a") + sstore("112233445566778899aabbccddee017b", "112233445566778899aabbccddee017b") + sstore("112233445566778899aabbccddee017c", "112233445566778899aabbccddee017c") + sstore("112233445566778899aabbccddee017d", "112233445566778899aabbccddee017d") + sstore("112233445566778899aabbccddee017e", "112233445566778899aabbccddee017e") + sstore("112233445566778899aabbccddee017f", "112233445566778899aabbccddee017f") + sstore("112233445566778899aabbccddee0180", "112233445566778899aabbccddee0180") + sstore("112233445566778899aabbccddee0181", "112233445566778899aabbccddee0181") + sstore("112233445566778899aabbccddee0182", "112233445566778899aabbccddee0182") + sstore("112233445566778899aabbccddee0183", "112233445566778899aabbccddee0183") + sstore("112233445566778899aabbccddee0184", "112233445566778899aabbccddee0184") + sstore("112233445566778899aabbccddee0185", "112233445566778899aabbccddee0185") + sstore("112233445566778899aabbccddee0186", "112233445566778899aabbccddee0186") + sstore("112233445566778899aabbccddee0187", "112233445566778899aabbccddee0187") + sstore("112233445566778899aabbccddee0188", "112233445566778899aabbccddee0188") + sstore("112233445566778899aabbccddee0189", "112233445566778899aabbccddee0189") + sstore("112233445566778899aabbccddee018a", "112233445566778899aabbccddee018a") + sstore("112233445566778899aabbccddee018b", "112233445566778899aabbccddee018b") + sstore("112233445566778899aabbccddee018c", "112233445566778899aabbccddee018c") + sstore("112233445566778899aabbccddee018d", "112233445566778899aabbccddee018d") + sstore("112233445566778899aabbccddee018e", "112233445566778899aabbccddee018e") + sstore("112233445566778899aabbccddee018f", "112233445566778899aabbccddee018f") + sstore("112233445566778899aabbccddee0190", "112233445566778899aabbccddee0190") + sstore("112233445566778899aabbccddee0191", "112233445566778899aabbccddee0191") + sstore("112233445566778899aabbccddee0192", "112233445566778899aabbccddee0192") + sstore("112233445566778899aabbccddee0193", "112233445566778899aabbccddee0193") + sstore("112233445566778899aabbccddee0194", "112233445566778899aabbccddee0194") + sstore("112233445566778899aabbccddee0195", "112233445566778899aabbccddee0195") + sstore("112233445566778899aabbccddee0196", "112233445566778899aabbccddee0196") + sstore("112233445566778899aabbccddee0197", "112233445566778899aabbccddee0197") + sstore("112233445566778899aabbccddee0198", "112233445566778899aabbccddee0198") + sstore("112233445566778899aabbccddee0199", "112233445566778899aabbccddee0199") + sstore("112233445566778899aabbccddee019a", "112233445566778899aabbccddee019a") + sstore("112233445566778899aabbccddee019b", "112233445566778899aabbccddee019b") + sstore("112233445566778899aabbccddee019c", "112233445566778899aabbccddee019c") + sstore("112233445566778899aabbccddee019d", "112233445566778899aabbccddee019d") + sstore("112233445566778899aabbccddee019e", "112233445566778899aabbccddee019e") + sstore("112233445566778899aabbccddee019f", "112233445566778899aabbccddee019f") + sstore("112233445566778899aabbccddee01a0", "112233445566778899aabbccddee01a0") + sstore("112233445566778899aabbccddee01a1", "112233445566778899aabbccddee01a1") + sstore("112233445566778899aabbccddee01a2", "112233445566778899aabbccddee01a2") + sstore("112233445566778899aabbccddee01a3", "112233445566778899aabbccddee01a3") + sstore("112233445566778899aabbccddee01a4", "112233445566778899aabbccddee01a4") + sstore("112233445566778899aabbccddee01a5", "112233445566778899aabbccddee01a5") + sstore("112233445566778899aabbccddee01a6", "112233445566778899aabbccddee01a6") + sstore("112233445566778899aabbccddee01a7", "112233445566778899aabbccddee01a7") + sstore("112233445566778899aabbccddee01a8", "112233445566778899aabbccddee01a8") + sstore("112233445566778899aabbccddee01a9", "112233445566778899aabbccddee01a9") + sstore("112233445566778899aabbccddee01aa", "112233445566778899aabbccddee01aa") + sstore("112233445566778899aabbccddee01ab", "112233445566778899aabbccddee01ab") + sstore("112233445566778899aabbccddee01ac", "112233445566778899aabbccddee01ac") + sstore("112233445566778899aabbccddee01ad", "112233445566778899aabbccddee01ad") + sstore("112233445566778899aabbccddee01ae", "112233445566778899aabbccddee01ae") + sstore("112233445566778899aabbccddee01af", "112233445566778899aabbccddee01af") + sstore("112233445566778899aabbccddee01b0", "112233445566778899aabbccddee01b0") + sstore("112233445566778899aabbccddee01b1", "112233445566778899aabbccddee01b1") + sstore("112233445566778899aabbccddee01b2", "112233445566778899aabbccddee01b2") + sstore("112233445566778899aabbccddee01b3", "112233445566778899aabbccddee01b3") + sstore("112233445566778899aabbccddee01b4", "112233445566778899aabbccddee01b4") + sstore("112233445566778899aabbccddee01b5", "112233445566778899aabbccddee01b5") + sstore("112233445566778899aabbccddee01b6", "112233445566778899aabbccddee01b6") + sstore("112233445566778899aabbccddee01b7", "112233445566778899aabbccddee01b7") + sstore("112233445566778899aabbccddee01b8", "112233445566778899aabbccddee01b8") + sstore("112233445566778899aabbccddee01b9", "112233445566778899aabbccddee01b9") + sstore("112233445566778899aabbccddee01ba", "112233445566778899aabbccddee01ba") + sstore("112233445566778899aabbccddee01bb", "112233445566778899aabbccddee01bb") + sstore("112233445566778899aabbccddee01bc", "112233445566778899aabbccddee01bc") + sstore("112233445566778899aabbccddee01bd", "112233445566778899aabbccddee01bd") + sstore("112233445566778899aabbccddee01be", "112233445566778899aabbccddee01be") + sstore("112233445566778899aabbccddee01bf", "112233445566778899aabbccddee01bf") + sstore("112233445566778899aabbccddee01c0", "112233445566778899aabbccddee01c0") + sstore("112233445566778899aabbccddee01c1", "112233445566778899aabbccddee01c1") + sstore("112233445566778899aabbccddee01c2", "112233445566778899aabbccddee01c2") + sstore("112233445566778899aabbccddee01c3", "112233445566778899aabbccddee01c3") + sstore("112233445566778899aabbccddee01c4", "112233445566778899aabbccddee01c4") + sstore("112233445566778899aabbccddee01c5", "112233445566778899aabbccddee01c5") + sstore("112233445566778899aabbccddee01c6", "112233445566778899aabbccddee01c6") + sstore("112233445566778899aabbccddee01c7", "112233445566778899aabbccddee01c7") + sstore("112233445566778899aabbccddee01c8", "112233445566778899aabbccddee01c8") + sstore("112233445566778899aabbccddee01c9", "112233445566778899aabbccddee01c9") + sstore("112233445566778899aabbccddee01ca", "112233445566778899aabbccddee01ca") + sstore("112233445566778899aabbccddee01cb", "112233445566778899aabbccddee01cb") + sstore("112233445566778899aabbccddee01cc", "112233445566778899aabbccddee01cc") + sstore("112233445566778899aabbccddee01cd", "112233445566778899aabbccddee01cd") + sstore("112233445566778899aabbccddee01ce", "112233445566778899aabbccddee01ce") + sstore("112233445566778899aabbccddee01cf", "112233445566778899aabbccddee01cf") + sstore("112233445566778899aabbccddee01d0", "112233445566778899aabbccddee01d0") + sstore("112233445566778899aabbccddee01d1", "112233445566778899aabbccddee01d1") + sstore("112233445566778899aabbccddee01d2", "112233445566778899aabbccddee01d2") + sstore("112233445566778899aabbccddee01d3", "112233445566778899aabbccddee01d3") + sstore("112233445566778899aabbccddee01d4", "112233445566778899aabbccddee01d4") + sstore("112233445566778899aabbccddee01d5", "112233445566778899aabbccddee01d5") + sstore("112233445566778899aabbccddee01d6", "112233445566778899aabbccddee01d6") + sstore("112233445566778899aabbccddee01d7", "112233445566778899aabbccddee01d7") + sstore("112233445566778899aabbccddee01d8", "112233445566778899aabbccddee01d8") + sstore("112233445566778899aabbccddee01d9", "112233445566778899aabbccddee01d9") + sstore("112233445566778899aabbccddee01da", "112233445566778899aabbccddee01da") + sstore("112233445566778899aabbccddee01db", "112233445566778899aabbccddee01db") + sstore("112233445566778899aabbccddee01dc", "112233445566778899aabbccddee01dc") + sstore("112233445566778899aabbccddee01dd", "112233445566778899aabbccddee01dd") + sstore("112233445566778899aabbccddee01de", "112233445566778899aabbccddee01de") + sstore("112233445566778899aabbccddee01df", "112233445566778899aabbccddee01df") + sstore("112233445566778899aabbccddee01e0", "112233445566778899aabbccddee01e0") + sstore("112233445566778899aabbccddee01e1", "112233445566778899aabbccddee01e1") + sstore("112233445566778899aabbccddee01e2", "112233445566778899aabbccddee01e2") + sstore("112233445566778899aabbccddee01e3", "112233445566778899aabbccddee01e3") + sstore("112233445566778899aabbccddee01e4", "112233445566778899aabbccddee01e4") + sstore("112233445566778899aabbccddee01e5", "112233445566778899aabbccddee01e5") + sstore("112233445566778899aabbccddee01e6", "112233445566778899aabbccddee01e6") + sstore("112233445566778899aabbccddee01e7", "112233445566778899aabbccddee01e7") + sstore("112233445566778899aabbccddee01e8", "112233445566778899aabbccddee01e8") + sstore("112233445566778899aabbccddee01e9", "112233445566778899aabbccddee01e9") + sstore("112233445566778899aabbccddee01ea", "112233445566778899aabbccddee01ea") + sstore("112233445566778899aabbccddee01eb", "112233445566778899aabbccddee01eb") + sstore("112233445566778899aabbccddee01ec", "112233445566778899aabbccddee01ec") + sstore("112233445566778899aabbccddee01ed", "112233445566778899aabbccddee01ed") + sstore("112233445566778899aabbccddee01ee", "112233445566778899aabbccddee01ee") + sstore("112233445566778899aabbccddee01ef", "112233445566778899aabbccddee01ef") + sstore("112233445566778899aabbccddee01f0", "112233445566778899aabbccddee01f0") + sstore("112233445566778899aabbccddee01f1", "112233445566778899aabbccddee01f1") + sstore("112233445566778899aabbccddee01f2", "112233445566778899aabbccddee01f2") + sstore("112233445566778899aabbccddee01f3", "112233445566778899aabbccddee01f3") + sstore("112233445566778899aabbccddee01f4", "112233445566778899aabbccddee01f4") + sstore("112233445566778899aabbccddee01f5", "112233445566778899aabbccddee01f5") + sstore("112233445566778899aabbccddee01f6", "112233445566778899aabbccddee01f6") + sstore("112233445566778899aabbccddee01f7", "112233445566778899aabbccddee01f7") + sstore("112233445566778899aabbccddee01f8", "112233445566778899aabbccddee01f8") + sstore("112233445566778899aabbccddee01f9", "112233445566778899aabbccddee01f9") + sstore("112233445566778899aabbccddee01fa", "112233445566778899aabbccddee01fa") + sstore("112233445566778899aabbccddee01fb", "112233445566778899aabbccddee01fb") + sstore("112233445566778899aabbccddee01fc", "112233445566778899aabbccddee01fc") + sstore("112233445566778899aabbccddee01fd", "112233445566778899aabbccddee01fd") + sstore("112233445566778899aabbccddee01fe", "112233445566778899aabbccddee01fe") + sstore("112233445566778899aabbccddee01ff", "112233445566778899aabbccddee01ff") + sstore("112233445566778899aabbccddee0200", "112233445566778899aabbccddee0200") + sstore("112233445566778899aabbccddee0201", "112233445566778899aabbccddee0201") + sstore("112233445566778899aabbccddee0202", "112233445566778899aabbccddee0202") + sstore("112233445566778899aabbccddee0203", "112233445566778899aabbccddee0203") + sstore("112233445566778899aabbccddee0204", "112233445566778899aabbccddee0204") + sstore("112233445566778899aabbccddee0205", "112233445566778899aabbccddee0205") + sstore("112233445566778899aabbccddee0206", "112233445566778899aabbccddee0206") + sstore("112233445566778899aabbccddee0207", "112233445566778899aabbccddee0207") + sstore("112233445566778899aabbccddee0208", "112233445566778899aabbccddee0208") + sstore("112233445566778899aabbccddee0209", "112233445566778899aabbccddee0209") + sstore("112233445566778899aabbccddee020a", "112233445566778899aabbccddee020a") + sstore("112233445566778899aabbccddee020b", "112233445566778899aabbccddee020b") + sstore("112233445566778899aabbccddee020c", "112233445566778899aabbccddee020c") + sstore("112233445566778899aabbccddee020d", "112233445566778899aabbccddee020d") + sstore("112233445566778899aabbccddee020e", "112233445566778899aabbccddee020e") + sstore("112233445566778899aabbccddee020f", "112233445566778899aabbccddee020f") + sstore("112233445566778899aabbccddee0210", "112233445566778899aabbccddee0210") + sstore("112233445566778899aabbccddee0211", "112233445566778899aabbccddee0211") + sstore("112233445566778899aabbccddee0212", "112233445566778899aabbccddee0212") + sstore("112233445566778899aabbccddee0213", "112233445566778899aabbccddee0213") + sstore("112233445566778899aabbccddee0214", "112233445566778899aabbccddee0214") + sstore("112233445566778899aabbccddee0215", "112233445566778899aabbccddee0215") + sstore("112233445566778899aabbccddee0216", "112233445566778899aabbccddee0216") + sstore("112233445566778899aabbccddee0217", "112233445566778899aabbccddee0217") + sstore("112233445566778899aabbccddee0218", "112233445566778899aabbccddee0218") + sstore("112233445566778899aabbccddee0219", "112233445566778899aabbccddee0219") + sstore("112233445566778899aabbccddee021a", "112233445566778899aabbccddee021a") + sstore("112233445566778899aabbccddee021b", "112233445566778899aabbccddee021b") + sstore("112233445566778899aabbccddee021c", "112233445566778899aabbccddee021c") + sstore("112233445566778899aabbccddee021d", "112233445566778899aabbccddee021d") + sstore("112233445566778899aabbccddee021e", "112233445566778899aabbccddee021e") + sstore("112233445566778899aabbccddee021f", "112233445566778899aabbccddee021f") + sstore("112233445566778899aabbccddee0220", "112233445566778899aabbccddee0220") + sstore("112233445566778899aabbccddee0221", "112233445566778899aabbccddee0221") + sstore("112233445566778899aabbccddee0222", "112233445566778899aabbccddee0222") + sstore("112233445566778899aabbccddee0223", "112233445566778899aabbccddee0223") + sstore("112233445566778899aabbccddee0224", "112233445566778899aabbccddee0224") + sstore("112233445566778899aabbccddee0225", "112233445566778899aabbccddee0225") + sstore("112233445566778899aabbccddee0226", "112233445566778899aabbccddee0226") + sstore("112233445566778899aabbccddee0227", "112233445566778899aabbccddee0227") + sstore("112233445566778899aabbccddee0228", "112233445566778899aabbccddee0228") + sstore("112233445566778899aabbccddee0229", "112233445566778899aabbccddee0229") + sstore("112233445566778899aabbccddee022a", "112233445566778899aabbccddee022a") + sstore("112233445566778899aabbccddee022b", "112233445566778899aabbccddee022b") + sstore("112233445566778899aabbccddee022c", "112233445566778899aabbccddee022c") + sstore("112233445566778899aabbccddee022d", "112233445566778899aabbccddee022d") + sstore("112233445566778899aabbccddee022e", "112233445566778899aabbccddee022e") + sstore("112233445566778899aabbccddee022f", "112233445566778899aabbccddee022f") + sstore("112233445566778899aabbccddee0230", "112233445566778899aabbccddee0230") + sstore("112233445566778899aabbccddee0231", "112233445566778899aabbccddee0231") + sstore("112233445566778899aabbccddee0232", "112233445566778899aabbccddee0232") + sstore("112233445566778899aabbccddee0233", "112233445566778899aabbccddee0233") + sstore("112233445566778899aabbccddee0234", "112233445566778899aabbccddee0234") + sstore("112233445566778899aabbccddee0235", "112233445566778899aabbccddee0235") + sstore("112233445566778899aabbccddee0236", "112233445566778899aabbccddee0236") + sstore("112233445566778899aabbccddee0237", "112233445566778899aabbccddee0237") + sstore("112233445566778899aabbccddee0238", "112233445566778899aabbccddee0238") + sstore("112233445566778899aabbccddee0239", "112233445566778899aabbccddee0239") + sstore("112233445566778899aabbccddee023a", "112233445566778899aabbccddee023a") + sstore("112233445566778899aabbccddee023b", "112233445566778899aabbccddee023b") + sstore("112233445566778899aabbccddee023c", "112233445566778899aabbccddee023c") + sstore("112233445566778899aabbccddee023d", "112233445566778899aabbccddee023d") + sstore("112233445566778899aabbccddee023e", "112233445566778899aabbccddee023e") + sstore("112233445566778899aabbccddee023f", "112233445566778899aabbccddee023f") + sstore("112233445566778899aabbccddee0240", "112233445566778899aabbccddee0240") + sstore("112233445566778899aabbccddee0241", "112233445566778899aabbccddee0241") + sstore("112233445566778899aabbccddee0242", "112233445566778899aabbccddee0242") + sstore("112233445566778899aabbccddee0243", "112233445566778899aabbccddee0243") + sstore("112233445566778899aabbccddee0244", "112233445566778899aabbccddee0244") + sstore("112233445566778899aabbccddee0245", "112233445566778899aabbccddee0245") + sstore("112233445566778899aabbccddee0246", "112233445566778899aabbccddee0246") + sstore("112233445566778899aabbccddee0247", "112233445566778899aabbccddee0247") + sstore("112233445566778899aabbccddee0248", "112233445566778899aabbccddee0248") + sstore("112233445566778899aabbccddee0249", "112233445566778899aabbccddee0249") + sstore("112233445566778899aabbccddee024a", "112233445566778899aabbccddee024a") + sstore("112233445566778899aabbccddee024b", "112233445566778899aabbccddee024b") + sstore("112233445566778899aabbccddee024c", "112233445566778899aabbccddee024c") + sstore("112233445566778899aabbccddee024d", "112233445566778899aabbccddee024d") + sstore("112233445566778899aabbccddee024e", "112233445566778899aabbccddee024e") + sstore("112233445566778899aabbccddee024f", "112233445566778899aabbccddee024f") + sstore("112233445566778899aabbccddee0250", "112233445566778899aabbccddee0250") + sstore("112233445566778899aabbccddee0251", "112233445566778899aabbccddee0251") + sstore("112233445566778899aabbccddee0252", "112233445566778899aabbccddee0252") + sstore("112233445566778899aabbccddee0253", "112233445566778899aabbccddee0253") + sstore("112233445566778899aabbccddee0254", "112233445566778899aabbccddee0254") + sstore("112233445566778899aabbccddee0255", "112233445566778899aabbccddee0255") + sstore("112233445566778899aabbccddee0256", "112233445566778899aabbccddee0256") + sstore("112233445566778899aabbccddee0257", "112233445566778899aabbccddee0257") + sstore("112233445566778899aabbccddee0258", "112233445566778899aabbccddee0258") + sstore("112233445566778899aabbccddee0259", "112233445566778899aabbccddee0259") + sstore("112233445566778899aabbccddee025a", "112233445566778899aabbccddee025a") + sstore("112233445566778899aabbccddee025b", "112233445566778899aabbccddee025b") + sstore("112233445566778899aabbccddee025c", "112233445566778899aabbccddee025c") + sstore("112233445566778899aabbccddee025d", "112233445566778899aabbccddee025d") + sstore("112233445566778899aabbccddee025e", "112233445566778899aabbccddee025e") + sstore("112233445566778899aabbccddee025f", "112233445566778899aabbccddee025f") + sstore("112233445566778899aabbccddee0260", "112233445566778899aabbccddee0260") + sstore("112233445566778899aabbccddee0261", "112233445566778899aabbccddee0261") + sstore("112233445566778899aabbccddee0262", "112233445566778899aabbccddee0262") + sstore("112233445566778899aabbccddee0263", "112233445566778899aabbccddee0263") + sstore("112233445566778899aabbccddee0264", "112233445566778899aabbccddee0264") + sstore("112233445566778899aabbccddee0265", "112233445566778899aabbccddee0265") + sstore("112233445566778899aabbccddee0266", "112233445566778899aabbccddee0266") + sstore("112233445566778899aabbccddee0267", "112233445566778899aabbccddee0267") + sstore("112233445566778899aabbccddee0268", "112233445566778899aabbccddee0268") + sstore("112233445566778899aabbccddee0269", "112233445566778899aabbccddee0269") + sstore("112233445566778899aabbccddee026a", "112233445566778899aabbccddee026a") + sstore("112233445566778899aabbccddee026b", "112233445566778899aabbccddee026b") + sstore("112233445566778899aabbccddee026c", "112233445566778899aabbccddee026c") + sstore("112233445566778899aabbccddee026d", "112233445566778899aabbccddee026d") + sstore("112233445566778899aabbccddee026e", "112233445566778899aabbccddee026e") + sstore("112233445566778899aabbccddee026f", "112233445566778899aabbccddee026f") + sstore("112233445566778899aabbccddee0270", "112233445566778899aabbccddee0270") + sstore("112233445566778899aabbccddee0271", "112233445566778899aabbccddee0271") + sstore("112233445566778899aabbccddee0272", "112233445566778899aabbccddee0272") + sstore("112233445566778899aabbccddee0273", "112233445566778899aabbccddee0273") + sstore("112233445566778899aabbccddee0274", "112233445566778899aabbccddee0274") + sstore("112233445566778899aabbccddee0275", "112233445566778899aabbccddee0275") + sstore("112233445566778899aabbccddee0276", "112233445566778899aabbccddee0276") + sstore("112233445566778899aabbccddee0277", "112233445566778899aabbccddee0277") + sstore("112233445566778899aabbccddee0278", "112233445566778899aabbccddee0278") + sstore("112233445566778899aabbccddee0279", "112233445566778899aabbccddee0279") + sstore("112233445566778899aabbccddee027a", "112233445566778899aabbccddee027a") + sstore("112233445566778899aabbccddee027b", "112233445566778899aabbccddee027b") + sstore("112233445566778899aabbccddee027c", "112233445566778899aabbccddee027c") + sstore("112233445566778899aabbccddee027d", "112233445566778899aabbccddee027d") + sstore("112233445566778899aabbccddee027e", "112233445566778899aabbccddee027e") + sstore("112233445566778899aabbccddee027f", "112233445566778899aabbccddee027f") + sstore("112233445566778899aabbccddee0280", "112233445566778899aabbccddee0280") + sstore("112233445566778899aabbccddee0281", "112233445566778899aabbccddee0281") + sstore("112233445566778899aabbccddee0282", "112233445566778899aabbccddee0282") + sstore("112233445566778899aabbccddee0283", "112233445566778899aabbccddee0283") + sstore("112233445566778899aabbccddee0284", "112233445566778899aabbccddee0284") + sstore("112233445566778899aabbccddee0285", "112233445566778899aabbccddee0285") + sstore("112233445566778899aabbccddee0286", "112233445566778899aabbccddee0286") + sstore("112233445566778899aabbccddee0287", "112233445566778899aabbccddee0287") + sstore("112233445566778899aabbccddee0288", "112233445566778899aabbccddee0288") + sstore("112233445566778899aabbccddee0289", "112233445566778899aabbccddee0289") + sstore("112233445566778899aabbccddee028a", "112233445566778899aabbccddee028a") + sstore("112233445566778899aabbccddee028b", "112233445566778899aabbccddee028b") + sstore("112233445566778899aabbccddee028c", "112233445566778899aabbccddee028c") + sstore("112233445566778899aabbccddee028d", "112233445566778899aabbccddee028d") + sstore("112233445566778899aabbccddee028e", "112233445566778899aabbccddee028e") + sstore("112233445566778899aabbccddee028f", "112233445566778899aabbccddee028f") + sstore("112233445566778899aabbccddee0290", "112233445566778899aabbccddee0290") + sstore("112233445566778899aabbccddee0291", "112233445566778899aabbccddee0291") + sstore("112233445566778899aabbccddee0292", "112233445566778899aabbccddee0292") + sstore("112233445566778899aabbccddee0293", "112233445566778899aabbccddee0293") + sstore("112233445566778899aabbccddee0294", "112233445566778899aabbccddee0294") + sstore("112233445566778899aabbccddee0295", "112233445566778899aabbccddee0295") + sstore("112233445566778899aabbccddee0296", "112233445566778899aabbccddee0296") + sstore("112233445566778899aabbccddee0297", "112233445566778899aabbccddee0297") + sstore("112233445566778899aabbccddee0298", "112233445566778899aabbccddee0298") + sstore("112233445566778899aabbccddee0299", "112233445566778899aabbccddee0299") + sstore("112233445566778899aabbccddee029a", "112233445566778899aabbccddee029a") + sstore("112233445566778899aabbccddee029b", "112233445566778899aabbccddee029b") + sstore("112233445566778899aabbccddee029c", "112233445566778899aabbccddee029c") + sstore("112233445566778899aabbccddee029d", "112233445566778899aabbccddee029d") + sstore("112233445566778899aabbccddee029e", "112233445566778899aabbccddee029e") + sstore("112233445566778899aabbccddee029f", "112233445566778899aabbccddee029f") + sstore("112233445566778899aabbccddee02a0", "112233445566778899aabbccddee02a0") + sstore("112233445566778899aabbccddee02a1", "112233445566778899aabbccddee02a1") + sstore("112233445566778899aabbccddee02a2", "112233445566778899aabbccddee02a2") + sstore("112233445566778899aabbccddee02a3", "112233445566778899aabbccddee02a3") + sstore("112233445566778899aabbccddee02a4", "112233445566778899aabbccddee02a4") + sstore("112233445566778899aabbccddee02a5", "112233445566778899aabbccddee02a5") + sstore("112233445566778899aabbccddee02a6", "112233445566778899aabbccddee02a6") + sstore("112233445566778899aabbccddee02a7", "112233445566778899aabbccddee02a7") + sstore("112233445566778899aabbccddee02a8", "112233445566778899aabbccddee02a8") + sstore("112233445566778899aabbccddee02a9", "112233445566778899aabbccddee02a9") + sstore("112233445566778899aabbccddee02aa", "112233445566778899aabbccddee02aa") + sstore("112233445566778899aabbccddee02ab", "112233445566778899aabbccddee02ab") + sstore("112233445566778899aabbccddee02ac", "112233445566778899aabbccddee02ac") + sstore("112233445566778899aabbccddee02ad", "112233445566778899aabbccddee02ad") + sstore("112233445566778899aabbccddee02ae", "112233445566778899aabbccddee02ae") + sstore("112233445566778899aabbccddee02af", "112233445566778899aabbccddee02af") + sstore("112233445566778899aabbccddee02b0", "112233445566778899aabbccddee02b0") + sstore("112233445566778899aabbccddee02b1", "112233445566778899aabbccddee02b1") + sstore("112233445566778899aabbccddee02b2", "112233445566778899aabbccddee02b2") + sstore("112233445566778899aabbccddee02b3", "112233445566778899aabbccddee02b3") + sstore("112233445566778899aabbccddee02b4", "112233445566778899aabbccddee02b4") + sstore("112233445566778899aabbccddee02b5", "112233445566778899aabbccddee02b5") + sstore("112233445566778899aabbccddee02b6", "112233445566778899aabbccddee02b6") + sstore("112233445566778899aabbccddee02b7", "112233445566778899aabbccddee02b7") + sstore("112233445566778899aabbccddee02b8", "112233445566778899aabbccddee02b8") + sstore("112233445566778899aabbccddee02b9", "112233445566778899aabbccddee02b9") + sstore("112233445566778899aabbccddee02ba", "112233445566778899aabbccddee02ba") + sstore("112233445566778899aabbccddee02bb", "112233445566778899aabbccddee02bb") + sstore("112233445566778899aabbccddee02bc", "112233445566778899aabbccddee02bc") + sstore("112233445566778899aabbccddee02bd", "112233445566778899aabbccddee02bd") + sstore("112233445566778899aabbccddee02be", "112233445566778899aabbccddee02be") + sstore("112233445566778899aabbccddee02bf", "112233445566778899aabbccddee02bf") + sstore("112233445566778899aabbccddee02c0", "112233445566778899aabbccddee02c0") + sstore("112233445566778899aabbccddee02c1", "112233445566778899aabbccddee02c1") + sstore("112233445566778899aabbccddee02c2", "112233445566778899aabbccddee02c2") + sstore("112233445566778899aabbccddee02c3", "112233445566778899aabbccddee02c3") + sstore("112233445566778899aabbccddee02c4", "112233445566778899aabbccddee02c4") + sstore("112233445566778899aabbccddee02c5", "112233445566778899aabbccddee02c5") + sstore("112233445566778899aabbccddee02c6", "112233445566778899aabbccddee02c6") + sstore("112233445566778899aabbccddee02c7", "112233445566778899aabbccddee02c7") + sstore("112233445566778899aabbccddee02c8", "112233445566778899aabbccddee02c8") + sstore("112233445566778899aabbccddee02c9", "112233445566778899aabbccddee02c9") + sstore("112233445566778899aabbccddee02ca", "112233445566778899aabbccddee02ca") + sstore("112233445566778899aabbccddee02cb", "112233445566778899aabbccddee02cb") + sstore("112233445566778899aabbccddee02cc", "112233445566778899aabbccddee02cc") + sstore("112233445566778899aabbccddee02cd", "112233445566778899aabbccddee02cd") + sstore("112233445566778899aabbccddee02ce", "112233445566778899aabbccddee02ce") + sstore("112233445566778899aabbccddee02cf", "112233445566778899aabbccddee02cf") + sstore("112233445566778899aabbccddee02d0", "112233445566778899aabbccddee02d0") + sstore("112233445566778899aabbccddee02d1", "112233445566778899aabbccddee02d1") + sstore("112233445566778899aabbccddee02d2", "112233445566778899aabbccddee02d2") + sstore("112233445566778899aabbccddee02d3", "112233445566778899aabbccddee02d3") + sstore("112233445566778899aabbccddee02d4", "112233445566778899aabbccddee02d4") + sstore("112233445566778899aabbccddee02d5", "112233445566778899aabbccddee02d5") + sstore("112233445566778899aabbccddee02d6", "112233445566778899aabbccddee02d6") + sstore("112233445566778899aabbccddee02d7", "112233445566778899aabbccddee02d7") + sstore("112233445566778899aabbccddee02d8", "112233445566778899aabbccddee02d8") + sstore("112233445566778899aabbccddee02d9", "112233445566778899aabbccddee02d9") + sstore("112233445566778899aabbccddee02da", "112233445566778899aabbccddee02da") + sstore("112233445566778899aabbccddee02db", "112233445566778899aabbccddee02db") + sstore("112233445566778899aabbccddee02dc", "112233445566778899aabbccddee02dc") + sstore("112233445566778899aabbccddee02dd", "112233445566778899aabbccddee02dd") + sstore("112233445566778899aabbccddee02de", "112233445566778899aabbccddee02de") + sstore("112233445566778899aabbccddee02df", "112233445566778899aabbccddee02df") + sstore("112233445566778899aabbccddee02e0", "112233445566778899aabbccddee02e0") + sstore("112233445566778899aabbccddee02e1", "112233445566778899aabbccddee02e1") + sstore("112233445566778899aabbccddee02e2", "112233445566778899aabbccddee02e2") + sstore("112233445566778899aabbccddee02e3", "112233445566778899aabbccddee02e3") + sstore("112233445566778899aabbccddee02e4", "112233445566778899aabbccddee02e4") + sstore("112233445566778899aabbccddee02e5", "112233445566778899aabbccddee02e5") + sstore("112233445566778899aabbccddee02e6", "112233445566778899aabbccddee02e6") + sstore("112233445566778899aabbccddee02e7", "112233445566778899aabbccddee02e7") + sstore("112233445566778899aabbccddee02e8", "112233445566778899aabbccddee02e8") + sstore("112233445566778899aabbccddee02e9", "112233445566778899aabbccddee02e9") + sstore("112233445566778899aabbccddee02ea", "112233445566778899aabbccddee02ea") + sstore("112233445566778899aabbccddee02eb", "112233445566778899aabbccddee02eb") + sstore("112233445566778899aabbccddee02ec", "112233445566778899aabbccddee02ec") + sstore("112233445566778899aabbccddee02ed", "112233445566778899aabbccddee02ed") + sstore("112233445566778899aabbccddee02ee", "112233445566778899aabbccddee02ee") + sstore("112233445566778899aabbccddee02ef", "112233445566778899aabbccddee02ef") + sstore("112233445566778899aabbccddee02f0", "112233445566778899aabbccddee02f0") + sstore("112233445566778899aabbccddee02f1", "112233445566778899aabbccddee02f1") + sstore("112233445566778899aabbccddee02f2", "112233445566778899aabbccddee02f2") + sstore("112233445566778899aabbccddee02f3", "112233445566778899aabbccddee02f3") + sstore("112233445566778899aabbccddee02f4", "112233445566778899aabbccddee02f4") + sstore("112233445566778899aabbccddee02f5", "112233445566778899aabbccddee02f5") + sstore("112233445566778899aabbccddee02f6", "112233445566778899aabbccddee02f6") + sstore("112233445566778899aabbccddee02f7", "112233445566778899aabbccddee02f7") + sstore("112233445566778899aabbccddee02f8", "112233445566778899aabbccddee02f8") + sstore("112233445566778899aabbccddee02f9", "112233445566778899aabbccddee02f9") + sstore("112233445566778899aabbccddee02fa", "112233445566778899aabbccddee02fa") + sstore("112233445566778899aabbccddee02fb", "112233445566778899aabbccddee02fb") + sstore("112233445566778899aabbccddee02fc", "112233445566778899aabbccddee02fc") + sstore("112233445566778899aabbccddee02fd", "112233445566778899aabbccddee02fd") + sstore("112233445566778899aabbccddee02fe", "112233445566778899aabbccddee02fe") + sstore("112233445566778899aabbccddee02ff", "112233445566778899aabbccddee02ff") + sstore("112233445566778899aabbccddee0300", "112233445566778899aabbccddee0300") + sstore("112233445566778899aabbccddee0301", "112233445566778899aabbccddee0301") + sstore("112233445566778899aabbccddee0302", "112233445566778899aabbccddee0302") + sstore("112233445566778899aabbccddee0303", "112233445566778899aabbccddee0303") + sstore("112233445566778899aabbccddee0304", "112233445566778899aabbccddee0304") + sstore("112233445566778899aabbccddee0305", "112233445566778899aabbccddee0305") + sstore("112233445566778899aabbccddee0306", "112233445566778899aabbccddee0306") + sstore("112233445566778899aabbccddee0307", "112233445566778899aabbccddee0307") + sstore("112233445566778899aabbccddee0308", "112233445566778899aabbccddee0308") + sstore("112233445566778899aabbccddee0309", "112233445566778899aabbccddee0309") + sstore("112233445566778899aabbccddee030a", "112233445566778899aabbccddee030a") + sstore("112233445566778899aabbccddee030b", "112233445566778899aabbccddee030b") + sstore("112233445566778899aabbccddee030c", "112233445566778899aabbccddee030c") + sstore("112233445566778899aabbccddee030d", "112233445566778899aabbccddee030d") + sstore("112233445566778899aabbccddee030e", "112233445566778899aabbccddee030e") + sstore("112233445566778899aabbccddee030f", "112233445566778899aabbccddee030f") + sstore("112233445566778899aabbccddee0310", "112233445566778899aabbccddee0310") + sstore("112233445566778899aabbccddee0311", "112233445566778899aabbccddee0311") + sstore("112233445566778899aabbccddee0312", "112233445566778899aabbccddee0312") + sstore("112233445566778899aabbccddee0313", "112233445566778899aabbccddee0313") + sstore("112233445566778899aabbccddee0314", "112233445566778899aabbccddee0314") + sstore("112233445566778899aabbccddee0315", "112233445566778899aabbccddee0315") + sstore("112233445566778899aabbccddee0316", "112233445566778899aabbccddee0316") + sstore("112233445566778899aabbccddee0317", "112233445566778899aabbccddee0317") + sstore("112233445566778899aabbccddee0318", "112233445566778899aabbccddee0318") + sstore("112233445566778899aabbccddee0319", "112233445566778899aabbccddee0319") + sstore("112233445566778899aabbccddee031a", "112233445566778899aabbccddee031a") + sstore("112233445566778899aabbccddee031b", "112233445566778899aabbccddee031b") + sstore("112233445566778899aabbccddee031c", "112233445566778899aabbccddee031c") + sstore("112233445566778899aabbccddee031d", "112233445566778899aabbccddee031d") + sstore("112233445566778899aabbccddee031e", "112233445566778899aabbccddee031e") + sstore("112233445566778899aabbccddee031f", "112233445566778899aabbccddee031f") + sstore("112233445566778899aabbccddee0320", "112233445566778899aabbccddee0320") + sstore("112233445566778899aabbccddee0321", "112233445566778899aabbccddee0321") + sstore("112233445566778899aabbccddee0322", "112233445566778899aabbccddee0322") + sstore("112233445566778899aabbccddee0323", "112233445566778899aabbccddee0323") + sstore("112233445566778899aabbccddee0324", "112233445566778899aabbccddee0324") + sstore("112233445566778899aabbccddee0325", "112233445566778899aabbccddee0325") + sstore("112233445566778899aabbccddee0326", "112233445566778899aabbccddee0326") + sstore("112233445566778899aabbccddee0327", "112233445566778899aabbccddee0327") + sstore("112233445566778899aabbccddee0328", "112233445566778899aabbccddee0328") + sstore("112233445566778899aabbccddee0329", "112233445566778899aabbccddee0329") + sstore("112233445566778899aabbccddee032a", "112233445566778899aabbccddee032a") + sstore("112233445566778899aabbccddee032b", "112233445566778899aabbccddee032b") + sstore("112233445566778899aabbccddee032c", "112233445566778899aabbccddee032c") + sstore("112233445566778899aabbccddee032d", "112233445566778899aabbccddee032d") + sstore("112233445566778899aabbccddee032e", "112233445566778899aabbccddee032e") + sstore("112233445566778899aabbccddee032f", "112233445566778899aabbccddee032f") + sstore("112233445566778899aabbccddee0330", "112233445566778899aabbccddee0330") + sstore("112233445566778899aabbccddee0331", "112233445566778899aabbccddee0331") + sstore("112233445566778899aabbccddee0332", "112233445566778899aabbccddee0332") + sstore("112233445566778899aabbccddee0333", "112233445566778899aabbccddee0333") + sstore("112233445566778899aabbccddee0334", "112233445566778899aabbccddee0334") + sstore("112233445566778899aabbccddee0335", "112233445566778899aabbccddee0335") + sstore("112233445566778899aabbccddee0336", "112233445566778899aabbccddee0336") + sstore("112233445566778899aabbccddee0337", "112233445566778899aabbccddee0337") + sstore("112233445566778899aabbccddee0338", "112233445566778899aabbccddee0338") + sstore("112233445566778899aabbccddee0339", "112233445566778899aabbccddee0339") + sstore("112233445566778899aabbccddee033a", "112233445566778899aabbccddee033a") + sstore("112233445566778899aabbccddee033b", "112233445566778899aabbccddee033b") + sstore("112233445566778899aabbccddee033c", "112233445566778899aabbccddee033c") + sstore("112233445566778899aabbccddee033d", "112233445566778899aabbccddee033d") + sstore("112233445566778899aabbccddee033e", "112233445566778899aabbccddee033e") + sstore("112233445566778899aabbccddee033f", "112233445566778899aabbccddee033f") + sstore("112233445566778899aabbccddee0340", "112233445566778899aabbccddee0340") + sstore("112233445566778899aabbccddee0341", "112233445566778899aabbccddee0341") + sstore("112233445566778899aabbccddee0342", "112233445566778899aabbccddee0342") + sstore("112233445566778899aabbccddee0343", "112233445566778899aabbccddee0343") + sstore("112233445566778899aabbccddee0344", "112233445566778899aabbccddee0344") + sstore("112233445566778899aabbccddee0345", "112233445566778899aabbccddee0345") + sstore("112233445566778899aabbccddee0346", "112233445566778899aabbccddee0346") + sstore("112233445566778899aabbccddee0347", "112233445566778899aabbccddee0347") + sstore("112233445566778899aabbccddee0348", "112233445566778899aabbccddee0348") + sstore("112233445566778899aabbccddee0349", "112233445566778899aabbccddee0349") + sstore("112233445566778899aabbccddee034a", "112233445566778899aabbccddee034a") + sstore("112233445566778899aabbccddee034b", "112233445566778899aabbccddee034b") + sstore("112233445566778899aabbccddee034c", "112233445566778899aabbccddee034c") + sstore("112233445566778899aabbccddee034d", "112233445566778899aabbccddee034d") + sstore("112233445566778899aabbccddee034e", "112233445566778899aabbccddee034e") + sstore("112233445566778899aabbccddee034f", "112233445566778899aabbccddee034f") + sstore("112233445566778899aabbccddee0350", "112233445566778899aabbccddee0350") + sstore("112233445566778899aabbccddee0351", "112233445566778899aabbccddee0351") + sstore("112233445566778899aabbccddee0352", "112233445566778899aabbccddee0352") + sstore("112233445566778899aabbccddee0353", "112233445566778899aabbccddee0353") + sstore("112233445566778899aabbccddee0354", "112233445566778899aabbccddee0354") + sstore("112233445566778899aabbccddee0355", "112233445566778899aabbccddee0355") + sstore("112233445566778899aabbccddee0356", "112233445566778899aabbccddee0356") + sstore("112233445566778899aabbccddee0357", "112233445566778899aabbccddee0357") + sstore("112233445566778899aabbccddee0358", "112233445566778899aabbccddee0358") + sstore("112233445566778899aabbccddee0359", "112233445566778899aabbccddee0359") + sstore("112233445566778899aabbccddee035a", "112233445566778899aabbccddee035a") + sstore("112233445566778899aabbccddee035b", "112233445566778899aabbccddee035b") + sstore("112233445566778899aabbccddee035c", "112233445566778899aabbccddee035c") + sstore("112233445566778899aabbccddee035d", "112233445566778899aabbccddee035d") + sstore("112233445566778899aabbccddee035e", "112233445566778899aabbccddee035e") + sstore("112233445566778899aabbccddee035f", "112233445566778899aabbccddee035f") + sstore("112233445566778899aabbccddee0360", "112233445566778899aabbccddee0360") + sstore("112233445566778899aabbccddee0361", "112233445566778899aabbccddee0361") + sstore("112233445566778899aabbccddee0362", "112233445566778899aabbccddee0362") + sstore("112233445566778899aabbccddee0363", "112233445566778899aabbccddee0363") + sstore("112233445566778899aabbccddee0364", "112233445566778899aabbccddee0364") + sstore("112233445566778899aabbccddee0365", "112233445566778899aabbccddee0365") + sstore("112233445566778899aabbccddee0366", "112233445566778899aabbccddee0366") + sstore("112233445566778899aabbccddee0367", "112233445566778899aabbccddee0367") + sstore("112233445566778899aabbccddee0368", "112233445566778899aabbccddee0368") + sstore("112233445566778899aabbccddee0369", "112233445566778899aabbccddee0369") + sstore("112233445566778899aabbccddee036a", "112233445566778899aabbccddee036a") + sstore("112233445566778899aabbccddee036b", "112233445566778899aabbccddee036b") + sstore("112233445566778899aabbccddee036c", "112233445566778899aabbccddee036c") + sstore("112233445566778899aabbccddee036d", "112233445566778899aabbccddee036d") + sstore("112233445566778899aabbccddee036e", "112233445566778899aabbccddee036e") + sstore("112233445566778899aabbccddee036f", "112233445566778899aabbccddee036f") + sstore("112233445566778899aabbccddee0370", "112233445566778899aabbccddee0370") + sstore("112233445566778899aabbccddee0371", "112233445566778899aabbccddee0371") + sstore("112233445566778899aabbccddee0372", "112233445566778899aabbccddee0372") + sstore("112233445566778899aabbccddee0373", "112233445566778899aabbccddee0373") + sstore("112233445566778899aabbccddee0374", "112233445566778899aabbccddee0374") + sstore("112233445566778899aabbccddee0375", "112233445566778899aabbccddee0375") + sstore("112233445566778899aabbccddee0376", "112233445566778899aabbccddee0376") + sstore("112233445566778899aabbccddee0377", "112233445566778899aabbccddee0377") + sstore("112233445566778899aabbccddee0378", "112233445566778899aabbccddee0378") + sstore("112233445566778899aabbccddee0379", "112233445566778899aabbccddee0379") + sstore("112233445566778899aabbccddee037a", "112233445566778899aabbccddee037a") + sstore("112233445566778899aabbccddee037b", "112233445566778899aabbccddee037b") + sstore("112233445566778899aabbccddee037c", "112233445566778899aabbccddee037c") + sstore("112233445566778899aabbccddee037d", "112233445566778899aabbccddee037d") + sstore("112233445566778899aabbccddee037e", "112233445566778899aabbccddee037e") + sstore("112233445566778899aabbccddee037f", "112233445566778899aabbccddee037f") + sstore("112233445566778899aabbccddee0380", "112233445566778899aabbccddee0380") + sstore("112233445566778899aabbccddee0381", "112233445566778899aabbccddee0381") + sstore("112233445566778899aabbccddee0382", "112233445566778899aabbccddee0382") + sstore("112233445566778899aabbccddee0383", "112233445566778899aabbccddee0383") + sstore("112233445566778899aabbccddee0384", "112233445566778899aabbccddee0384") + sstore("112233445566778899aabbccddee0385", "112233445566778899aabbccddee0385") + sstore("112233445566778899aabbccddee0386", "112233445566778899aabbccddee0386") + sstore("112233445566778899aabbccddee0387", "112233445566778899aabbccddee0387") + sstore("112233445566778899aabbccddee0388", "112233445566778899aabbccddee0388") + sstore("112233445566778899aabbccddee0389", "112233445566778899aabbccddee0389") + sstore("112233445566778899aabbccddee038a", "112233445566778899aabbccddee038a") + sstore("112233445566778899aabbccddee038b", "112233445566778899aabbccddee038b") + sstore("112233445566778899aabbccddee038c", "112233445566778899aabbccddee038c") + sstore("112233445566778899aabbccddee038d", "112233445566778899aabbccddee038d") + sstore("112233445566778899aabbccddee038e", "112233445566778899aabbccddee038e") + sstore("112233445566778899aabbccddee038f", "112233445566778899aabbccddee038f") + sstore("112233445566778899aabbccddee0390", "112233445566778899aabbccddee0390") + sstore("112233445566778899aabbccddee0391", "112233445566778899aabbccddee0391") + sstore("112233445566778899aabbccddee0392", "112233445566778899aabbccddee0392") + sstore("112233445566778899aabbccddee0393", "112233445566778899aabbccddee0393") + sstore("112233445566778899aabbccddee0394", "112233445566778899aabbccddee0394") + sstore("112233445566778899aabbccddee0395", "112233445566778899aabbccddee0395") + sstore("112233445566778899aabbccddee0396", "112233445566778899aabbccddee0396") + sstore("112233445566778899aabbccddee0397", "112233445566778899aabbccddee0397") + sstore("112233445566778899aabbccddee0398", "112233445566778899aabbccddee0398") + sstore("112233445566778899aabbccddee0399", "112233445566778899aabbccddee0399") + sstore("112233445566778899aabbccddee039a", "112233445566778899aabbccddee039a") + sstore("112233445566778899aabbccddee039b", "112233445566778899aabbccddee039b") + sstore("112233445566778899aabbccddee039c", "112233445566778899aabbccddee039c") + sstore("112233445566778899aabbccddee039d", "112233445566778899aabbccddee039d") + sstore("112233445566778899aabbccddee039e", "112233445566778899aabbccddee039e") + sstore("112233445566778899aabbccddee039f", "112233445566778899aabbccddee039f") + sstore("112233445566778899aabbccddee03a0", "112233445566778899aabbccddee03a0") + sstore("112233445566778899aabbccddee03a1", "112233445566778899aabbccddee03a1") + sstore("112233445566778899aabbccddee03a2", "112233445566778899aabbccddee03a2") + sstore("112233445566778899aabbccddee03a3", "112233445566778899aabbccddee03a3") + sstore("112233445566778899aabbccddee03a4", "112233445566778899aabbccddee03a4") + sstore("112233445566778899aabbccddee03a5", "112233445566778899aabbccddee03a5") + sstore("112233445566778899aabbccddee03a6", "112233445566778899aabbccddee03a6") + sstore("112233445566778899aabbccddee03a7", "112233445566778899aabbccddee03a7") + sstore("112233445566778899aabbccddee03a8", "112233445566778899aabbccddee03a8") + sstore("112233445566778899aabbccddee03a9", "112233445566778899aabbccddee03a9") + sstore("112233445566778899aabbccddee03aa", "112233445566778899aabbccddee03aa") + sstore("112233445566778899aabbccddee03ab", "112233445566778899aabbccddee03ab") + sstore("112233445566778899aabbccddee03ac", "112233445566778899aabbccddee03ac") + sstore("112233445566778899aabbccddee03ad", "112233445566778899aabbccddee03ad") + sstore("112233445566778899aabbccddee03ae", "112233445566778899aabbccddee03ae") + sstore("112233445566778899aabbccddee03af", "112233445566778899aabbccddee03af") + sstore("112233445566778899aabbccddee03b0", "112233445566778899aabbccddee03b0") + sstore("112233445566778899aabbccddee03b1", "112233445566778899aabbccddee03b1") + sstore("112233445566778899aabbccddee03b2", "112233445566778899aabbccddee03b2") + sstore("112233445566778899aabbccddee03b3", "112233445566778899aabbccddee03b3") + sstore("112233445566778899aabbccddee03b4", "112233445566778899aabbccddee03b4") + sstore("112233445566778899aabbccddee03b5", "112233445566778899aabbccddee03b5") + sstore("112233445566778899aabbccddee03b6", "112233445566778899aabbccddee03b6") + sstore("112233445566778899aabbccddee03b7", "112233445566778899aabbccddee03b7") + sstore("112233445566778899aabbccddee03b8", "112233445566778899aabbccddee03b8") + sstore("112233445566778899aabbccddee03b9", "112233445566778899aabbccddee03b9") + sstore("112233445566778899aabbccddee03ba", "112233445566778899aabbccddee03ba") + sstore("112233445566778899aabbccddee03bb", "112233445566778899aabbccddee03bb") + sstore("112233445566778899aabbccddee03bc", "112233445566778899aabbccddee03bc") + sstore("112233445566778899aabbccddee03bd", "112233445566778899aabbccddee03bd") + sstore("112233445566778899aabbccddee03be", "112233445566778899aabbccddee03be") + sstore("112233445566778899aabbccddee03bf", "112233445566778899aabbccddee03bf") + sstore("112233445566778899aabbccddee03c0", "112233445566778899aabbccddee03c0") + sstore("112233445566778899aabbccddee03c1", "112233445566778899aabbccddee03c1") + sstore("112233445566778899aabbccddee03c2", "112233445566778899aabbccddee03c2") + sstore("112233445566778899aabbccddee03c3", "112233445566778899aabbccddee03c3") + sstore("112233445566778899aabbccddee03c4", "112233445566778899aabbccddee03c4") + sstore("112233445566778899aabbccddee03c5", "112233445566778899aabbccddee03c5") + sstore("112233445566778899aabbccddee03c6", "112233445566778899aabbccddee03c6") + sstore("112233445566778899aabbccddee03c7", "112233445566778899aabbccddee03c7") + sstore("112233445566778899aabbccddee03c8", "112233445566778899aabbccddee03c8") + sstore("112233445566778899aabbccddee03c9", "112233445566778899aabbccddee03c9") + sstore("112233445566778899aabbccddee03ca", "112233445566778899aabbccddee03ca") + sstore("112233445566778899aabbccddee03cb", "112233445566778899aabbccddee03cb") + sstore("112233445566778899aabbccddee03cc", "112233445566778899aabbccddee03cc") + sstore("112233445566778899aabbccddee03cd", "112233445566778899aabbccddee03cd") + sstore("112233445566778899aabbccddee03ce", "112233445566778899aabbccddee03ce") + sstore("112233445566778899aabbccddee03cf", "112233445566778899aabbccddee03cf") + sstore("112233445566778899aabbccddee03d0", "112233445566778899aabbccddee03d0") + sstore("112233445566778899aabbccddee03d1", "112233445566778899aabbccddee03d1") + sstore("112233445566778899aabbccddee03d2", "112233445566778899aabbccddee03d2") + sstore("112233445566778899aabbccddee03d3", "112233445566778899aabbccddee03d3") + sstore("112233445566778899aabbccddee03d4", "112233445566778899aabbccddee03d4") + sstore("112233445566778899aabbccddee03d5", "112233445566778899aabbccddee03d5") + sstore("112233445566778899aabbccddee03d6", "112233445566778899aabbccddee03d6") + sstore("112233445566778899aabbccddee03d7", "112233445566778899aabbccddee03d7") + sstore("112233445566778899aabbccddee03d8", "112233445566778899aabbccddee03d8") + sstore("112233445566778899aabbccddee03d9", "112233445566778899aabbccddee03d9") + sstore("112233445566778899aabbccddee03da", "112233445566778899aabbccddee03da") + sstore("112233445566778899aabbccddee03db", "112233445566778899aabbccddee03db") + sstore("112233445566778899aabbccddee03dc", "112233445566778899aabbccddee03dc") + sstore("112233445566778899aabbccddee03dd", "112233445566778899aabbccddee03dd") + sstore("112233445566778899aabbccddee03de", "112233445566778899aabbccddee03de") + sstore("112233445566778899aabbccddee03df", "112233445566778899aabbccddee03df") + sstore("112233445566778899aabbccddee03e0", "112233445566778899aabbccddee03e0") + sstore("112233445566778899aabbccddee03e1", "112233445566778899aabbccddee03e1") + sstore("112233445566778899aabbccddee03e2", "112233445566778899aabbccddee03e2") + sstore("112233445566778899aabbccddee03e3", "112233445566778899aabbccddee03e3") + sstore("112233445566778899aabbccddee03e4", "112233445566778899aabbccddee03e4") + sstore("112233445566778899aabbccddee03e5", "112233445566778899aabbccddee03e5") + sstore("112233445566778899aabbccddee03e6", "112233445566778899aabbccddee03e6") + sstore("112233445566778899aabbccddee03e7", "112233445566778899aabbccddee03e7") + sstore("112233445566778899aabbccddee03e8", "112233445566778899aabbccddee03e8") + sstore("112233445566778899aabbccddee03e9", "112233445566778899aabbccddee03e9") + sstore("112233445566778899aabbccddee03ea", "112233445566778899aabbccddee03ea") + sstore("112233445566778899aabbccddee03eb", "112233445566778899aabbccddee03eb") + sstore("112233445566778899aabbccddee03ec", "112233445566778899aabbccddee03ec") + sstore("112233445566778899aabbccddee03ed", "112233445566778899aabbccddee03ed") + sstore("112233445566778899aabbccddee03ee", "112233445566778899aabbccddee03ee") + sstore("112233445566778899aabbccddee03ef", "112233445566778899aabbccddee03ef") + sstore("112233445566778899aabbccddee03f0", "112233445566778899aabbccddee03f0") + sstore("112233445566778899aabbccddee03f1", "112233445566778899aabbccddee03f1") + sstore("112233445566778899aabbccddee03f2", "112233445566778899aabbccddee03f2") + sstore("112233445566778899aabbccddee03f3", "112233445566778899aabbccddee03f3") + sstore("112233445566778899aabbccddee03f4", "112233445566778899aabbccddee03f4") + sstore("112233445566778899aabbccddee03f5", "112233445566778899aabbccddee03f5") + sstore("112233445566778899aabbccddee03f6", "112233445566778899aabbccddee03f6") + sstore("112233445566778899aabbccddee03f7", "112233445566778899aabbccddee03f7") + sstore("112233445566778899aabbccddee03f8", "112233445566778899aabbccddee03f8") + sstore("112233445566778899aabbccddee03f9", "112233445566778899aabbccddee03f9") + sstore("112233445566778899aabbccddee03fa", "112233445566778899aabbccddee03fa") + sstore("112233445566778899aabbccddee03fb", "112233445566778899aabbccddee03fb") + sstore("112233445566778899aabbccddee03fc", "112233445566778899aabbccddee03fc") + sstore("112233445566778899aabbccddee03fd", "112233445566778899aabbccddee03fd") + sstore("112233445566778899aabbccddee03fe", "112233445566778899aabbccddee03fe") + sstore("112233445566778899aabbccddee03ff", "112233445566778899aabbccddee03ff") + sstore("112233445566778899aabbccddee0400", "112233445566778899aabbccddee0400") + sstore("112233445566778899aabbccddee0401", "112233445566778899aabbccddee0401") + sstore("112233445566778899aabbccddee0402", "112233445566778899aabbccddee0402") + sstore("112233445566778899aabbccddee0403", "112233445566778899aabbccddee0403") + sstore("112233445566778899aabbccddee0404", "112233445566778899aabbccddee0404") + sstore("112233445566778899aabbccddee0405", "112233445566778899aabbccddee0405") + sstore("112233445566778899aabbccddee0406", "112233445566778899aabbccddee0406") + sstore("112233445566778899aabbccddee0407", "112233445566778899aabbccddee0407") + sstore("112233445566778899aabbccddee0408", "112233445566778899aabbccddee0408") + sstore("112233445566778899aabbccddee0409", "112233445566778899aabbccddee0409") + sstore("112233445566778899aabbccddee040a", "112233445566778899aabbccddee040a") + sstore("112233445566778899aabbccddee040b", "112233445566778899aabbccddee040b") + sstore("112233445566778899aabbccddee040c", "112233445566778899aabbccddee040c") + sstore("112233445566778899aabbccddee040d", "112233445566778899aabbccddee040d") + sstore("112233445566778899aabbccddee040e", "112233445566778899aabbccddee040e") + sstore("112233445566778899aabbccddee040f", "112233445566778899aabbccddee040f") + sstore("112233445566778899aabbccddee0410", "112233445566778899aabbccddee0410") + sstore("112233445566778899aabbccddee0411", "112233445566778899aabbccddee0411") + sstore("112233445566778899aabbccddee0412", "112233445566778899aabbccddee0412") + sstore("112233445566778899aabbccddee0413", "112233445566778899aabbccddee0413") + sstore("112233445566778899aabbccddee0414", "112233445566778899aabbccddee0414") + sstore("112233445566778899aabbccddee0415", "112233445566778899aabbccddee0415") + sstore("112233445566778899aabbccddee0416", "112233445566778899aabbccddee0416") + sstore("112233445566778899aabbccddee0417", "112233445566778899aabbccddee0417") + sstore("112233445566778899aabbccddee0418", "112233445566778899aabbccddee0418") + sstore("112233445566778899aabbccddee0419", "112233445566778899aabbccddee0419") + sstore("112233445566778899aabbccddee041a", "112233445566778899aabbccddee041a") + sstore("112233445566778899aabbccddee041b", "112233445566778899aabbccddee041b") + sstore("112233445566778899aabbccddee041c", "112233445566778899aabbccddee041c") + sstore("112233445566778899aabbccddee041d", "112233445566778899aabbccddee041d") + sstore("112233445566778899aabbccddee041e", "112233445566778899aabbccddee041e") + sstore("112233445566778899aabbccddee041f", "112233445566778899aabbccddee041f") + sstore("112233445566778899aabbccddee0420", "112233445566778899aabbccddee0420") + sstore("112233445566778899aabbccddee0421", "112233445566778899aabbccddee0421") + sstore("112233445566778899aabbccddee0422", "112233445566778899aabbccddee0422") + sstore("112233445566778899aabbccddee0423", "112233445566778899aabbccddee0423") + sstore("112233445566778899aabbccddee0424", "112233445566778899aabbccddee0424") + sstore("112233445566778899aabbccddee0425", "112233445566778899aabbccddee0425") + sstore("112233445566778899aabbccddee0426", "112233445566778899aabbccddee0426") + sstore("112233445566778899aabbccddee0427", "112233445566778899aabbccddee0427") + sstore("112233445566778899aabbccddee0428", "112233445566778899aabbccddee0428") + sstore("112233445566778899aabbccddee0429", "112233445566778899aabbccddee0429") + sstore("112233445566778899aabbccddee042a", "112233445566778899aabbccddee042a") + sstore("112233445566778899aabbccddee042b", "112233445566778899aabbccddee042b") + sstore("112233445566778899aabbccddee042c", "112233445566778899aabbccddee042c") + sstore("112233445566778899aabbccddee042d", "112233445566778899aabbccddee042d") + sstore("112233445566778899aabbccddee042e", "112233445566778899aabbccddee042e") + sstore("112233445566778899aabbccddee042f", "112233445566778899aabbccddee042f") + sstore("112233445566778899aabbccddee0430", "112233445566778899aabbccddee0430") + sstore("112233445566778899aabbccddee0431", "112233445566778899aabbccddee0431") + sstore("112233445566778899aabbccddee0432", "112233445566778899aabbccddee0432") + sstore("112233445566778899aabbccddee0433", "112233445566778899aabbccddee0433") + sstore("112233445566778899aabbccddee0434", "112233445566778899aabbccddee0434") + sstore("112233445566778899aabbccddee0435", "112233445566778899aabbccddee0435") + sstore("112233445566778899aabbccddee0436", "112233445566778899aabbccddee0436") + sstore("112233445566778899aabbccddee0437", "112233445566778899aabbccddee0437") + sstore("112233445566778899aabbccddee0438", "112233445566778899aabbccddee0438") + sstore("112233445566778899aabbccddee0439", "112233445566778899aabbccddee0439") + sstore("112233445566778899aabbccddee043a", "112233445566778899aabbccddee043a") + sstore("112233445566778899aabbccddee043b", "112233445566778899aabbccddee043b") + sstore("112233445566778899aabbccddee043c", "112233445566778899aabbccddee043c") + sstore("112233445566778899aabbccddee043d", "112233445566778899aabbccddee043d") + sstore("112233445566778899aabbccddee043e", "112233445566778899aabbccddee043e") + sstore("112233445566778899aabbccddee043f", "112233445566778899aabbccddee043f") + sstore("112233445566778899aabbccddee0440", "112233445566778899aabbccddee0440") + sstore("112233445566778899aabbccddee0441", "112233445566778899aabbccddee0441") + sstore("112233445566778899aabbccddee0442", "112233445566778899aabbccddee0442") + sstore("112233445566778899aabbccddee0443", "112233445566778899aabbccddee0443") + sstore("112233445566778899aabbccddee0444", "112233445566778899aabbccddee0444") + sstore("112233445566778899aabbccddee0445", "112233445566778899aabbccddee0445") + sstore("112233445566778899aabbccddee0446", "112233445566778899aabbccddee0446") + sstore("112233445566778899aabbccddee0447", "112233445566778899aabbccddee0447") + sstore("112233445566778899aabbccddee0448", "112233445566778899aabbccddee0448") + sstore("112233445566778899aabbccddee0449", "112233445566778899aabbccddee0449") + sstore("112233445566778899aabbccddee044a", "112233445566778899aabbccddee044a") + sstore("112233445566778899aabbccddee044b", "112233445566778899aabbccddee044b") + sstore("112233445566778899aabbccddee044c", "112233445566778899aabbccddee044c") + sstore("112233445566778899aabbccddee044d", "112233445566778899aabbccddee044d") + sstore("112233445566778899aabbccddee044e", "112233445566778899aabbccddee044e") + sstore("112233445566778899aabbccddee044f", "112233445566778899aabbccddee044f") + sstore("112233445566778899aabbccddee0450", "112233445566778899aabbccddee0450") + sstore("112233445566778899aabbccddee0451", "112233445566778899aabbccddee0451") + sstore("112233445566778899aabbccddee0452", "112233445566778899aabbccddee0452") + sstore("112233445566778899aabbccddee0453", "112233445566778899aabbccddee0453") + sstore("112233445566778899aabbccddee0454", "112233445566778899aabbccddee0454") + sstore("112233445566778899aabbccddee0455", "112233445566778899aabbccddee0455") + sstore("112233445566778899aabbccddee0456", "112233445566778899aabbccddee0456") + sstore("112233445566778899aabbccddee0457", "112233445566778899aabbccddee0457") + sstore("112233445566778899aabbccddee0458", "112233445566778899aabbccddee0458") + sstore("112233445566778899aabbccddee0459", "112233445566778899aabbccddee0459") + sstore("112233445566778899aabbccddee045a", "112233445566778899aabbccddee045a") + sstore("112233445566778899aabbccddee045b", "112233445566778899aabbccddee045b") + sstore("112233445566778899aabbccddee045c", "112233445566778899aabbccddee045c") + sstore("112233445566778899aabbccddee045d", "112233445566778899aabbccddee045d") + sstore("112233445566778899aabbccddee045e", "112233445566778899aabbccddee045e") + sstore("112233445566778899aabbccddee045f", "112233445566778899aabbccddee045f") + sstore("112233445566778899aabbccddee0460", "112233445566778899aabbccddee0460") + sstore("112233445566778899aabbccddee0461", "112233445566778899aabbccddee0461") + sstore("112233445566778899aabbccddee0462", "112233445566778899aabbccddee0462") + sstore("112233445566778899aabbccddee0463", "112233445566778899aabbccddee0463") + sstore("112233445566778899aabbccddee0464", "112233445566778899aabbccddee0464") + sstore("112233445566778899aabbccddee0465", "112233445566778899aabbccddee0465") + sstore("112233445566778899aabbccddee0466", "112233445566778899aabbccddee0466") + sstore("112233445566778899aabbccddee0467", "112233445566778899aabbccddee0467") + sstore("112233445566778899aabbccddee0468", "112233445566778899aabbccddee0468") + sstore("112233445566778899aabbccddee0469", "112233445566778899aabbccddee0469") + sstore("112233445566778899aabbccddee046a", "112233445566778899aabbccddee046a") + sstore("112233445566778899aabbccddee046b", "112233445566778899aabbccddee046b") + sstore("112233445566778899aabbccddee046c", "112233445566778899aabbccddee046c") + sstore("112233445566778899aabbccddee046d", "112233445566778899aabbccddee046d") + sstore("112233445566778899aabbccddee046e", "112233445566778899aabbccddee046e") + sstore("112233445566778899aabbccddee046f", "112233445566778899aabbccddee046f") + sstore("112233445566778899aabbccddee0470", "112233445566778899aabbccddee0470") + sstore("112233445566778899aabbccddee0471", "112233445566778899aabbccddee0471") + sstore("112233445566778899aabbccddee0472", "112233445566778899aabbccddee0472") + sstore("112233445566778899aabbccddee0473", "112233445566778899aabbccddee0473") + sstore("112233445566778899aabbccddee0474", "112233445566778899aabbccddee0474") + sstore("112233445566778899aabbccddee0475", "112233445566778899aabbccddee0475") + sstore("112233445566778899aabbccddee0476", "112233445566778899aabbccddee0476") + sstore("112233445566778899aabbccddee0477", "112233445566778899aabbccddee0477") + sstore("112233445566778899aabbccddee0478", "112233445566778899aabbccddee0478") + sstore("112233445566778899aabbccddee0479", "112233445566778899aabbccddee0479") + sstore("112233445566778899aabbccddee047a", "112233445566778899aabbccddee047a") + sstore("112233445566778899aabbccddee047b", "112233445566778899aabbccddee047b") + sstore("112233445566778899aabbccddee047c", "112233445566778899aabbccddee047c") + sstore("112233445566778899aabbccddee047d", "112233445566778899aabbccddee047d") + sstore("112233445566778899aabbccddee047e", "112233445566778899aabbccddee047e") + sstore("112233445566778899aabbccddee047f", "112233445566778899aabbccddee047f") + sstore("112233445566778899aabbccddee0480", "112233445566778899aabbccddee0480") + sstore("112233445566778899aabbccddee0481", "112233445566778899aabbccddee0481") + sstore("112233445566778899aabbccddee0482", "112233445566778899aabbccddee0482") + sstore("112233445566778899aabbccddee0483", "112233445566778899aabbccddee0483") + sstore("112233445566778899aabbccddee0484", "112233445566778899aabbccddee0484") + sstore("112233445566778899aabbccddee0485", "112233445566778899aabbccddee0485") + sstore("112233445566778899aabbccddee0486", "112233445566778899aabbccddee0486") + sstore("112233445566778899aabbccddee0487", "112233445566778899aabbccddee0487") + sstore("112233445566778899aabbccddee0488", "112233445566778899aabbccddee0488") + sstore("112233445566778899aabbccddee0489", "112233445566778899aabbccddee0489") + sstore("112233445566778899aabbccddee048a", "112233445566778899aabbccddee048a") + sstore("112233445566778899aabbccddee048b", "112233445566778899aabbccddee048b") + sstore("112233445566778899aabbccddee048c", "112233445566778899aabbccddee048c") + sstore("112233445566778899aabbccddee048d", "112233445566778899aabbccddee048d") + sstore("112233445566778899aabbccddee048e", "112233445566778899aabbccddee048e") + sstore("112233445566778899aabbccddee048f", "112233445566778899aabbccddee048f") + sstore("112233445566778899aabbccddee0490", "112233445566778899aabbccddee0490") + sstore("112233445566778899aabbccddee0491", "112233445566778899aabbccddee0491") + sstore("112233445566778899aabbccddee0492", "112233445566778899aabbccddee0492") + sstore("112233445566778899aabbccddee0493", "112233445566778899aabbccddee0493") + sstore("112233445566778899aabbccddee0494", "112233445566778899aabbccddee0494") + sstore("112233445566778899aabbccddee0495", "112233445566778899aabbccddee0495") + sstore("112233445566778899aabbccddee0496", "112233445566778899aabbccddee0496") + sstore("112233445566778899aabbccddee0497", "112233445566778899aabbccddee0497") + sstore("112233445566778899aabbccddee0498", "112233445566778899aabbccddee0498") + sstore("112233445566778899aabbccddee0499", "112233445566778899aabbccddee0499") + sstore("112233445566778899aabbccddee049a", "112233445566778899aabbccddee049a") + sstore("112233445566778899aabbccddee049b", "112233445566778899aabbccddee049b") + sstore("112233445566778899aabbccddee049c", "112233445566778899aabbccddee049c") + sstore("112233445566778899aabbccddee049d", "112233445566778899aabbccddee049d") + sstore("112233445566778899aabbccddee049e", "112233445566778899aabbccddee049e") + sstore("112233445566778899aabbccddee049f", "112233445566778899aabbccddee049f") + sstore("112233445566778899aabbccddee04a0", "112233445566778899aabbccddee04a0") + sstore("112233445566778899aabbccddee04a1", "112233445566778899aabbccddee04a1") + sstore("112233445566778899aabbccddee04a2", "112233445566778899aabbccddee04a2") + sstore("112233445566778899aabbccddee04a3", "112233445566778899aabbccddee04a3") + sstore("112233445566778899aabbccddee04a4", "112233445566778899aabbccddee04a4") + sstore("112233445566778899aabbccddee04a5", "112233445566778899aabbccddee04a5") + sstore("112233445566778899aabbccddee04a6", "112233445566778899aabbccddee04a6") + sstore("112233445566778899aabbccddee04a7", "112233445566778899aabbccddee04a7") + sstore("112233445566778899aabbccddee04a8", "112233445566778899aabbccddee04a8") + sstore("112233445566778899aabbccddee04a9", "112233445566778899aabbccddee04a9") + sstore("112233445566778899aabbccddee04aa", "112233445566778899aabbccddee04aa") + sstore("112233445566778899aabbccddee04ab", "112233445566778899aabbccddee04ab") + sstore("112233445566778899aabbccddee04ac", "112233445566778899aabbccddee04ac") + sstore("112233445566778899aabbccddee04ad", "112233445566778899aabbccddee04ad") + sstore("112233445566778899aabbccddee04ae", "112233445566778899aabbccddee04ae") + sstore("112233445566778899aabbccddee04af", "112233445566778899aabbccddee04af") + sstore("112233445566778899aabbccddee04b0", "112233445566778899aabbccddee04b0") + sstore("112233445566778899aabbccddee04b1", "112233445566778899aabbccddee04b1") + sstore("112233445566778899aabbccddee04b2", "112233445566778899aabbccddee04b2") + sstore("112233445566778899aabbccddee04b3", "112233445566778899aabbccddee04b3") + sstore("112233445566778899aabbccddee04b4", "112233445566778899aabbccddee04b4") + sstore("112233445566778899aabbccddee04b5", "112233445566778899aabbccddee04b5") + sstore("112233445566778899aabbccddee04b6", "112233445566778899aabbccddee04b6") + sstore("112233445566778899aabbccddee04b7", "112233445566778899aabbccddee04b7") + sstore("112233445566778899aabbccddee04b8", "112233445566778899aabbccddee04b8") + sstore("112233445566778899aabbccddee04b9", "112233445566778899aabbccddee04b9") + sstore("112233445566778899aabbccddee04ba", "112233445566778899aabbccddee04ba") + sstore("112233445566778899aabbccddee04bb", "112233445566778899aabbccddee04bb") + sstore("112233445566778899aabbccddee04bc", "112233445566778899aabbccddee04bc") + sstore("112233445566778899aabbccddee04bd", "112233445566778899aabbccddee04bd") + sstore("112233445566778899aabbccddee04be", "112233445566778899aabbccddee04be") + sstore("112233445566778899aabbccddee04bf", "112233445566778899aabbccddee04bf") + sstore("112233445566778899aabbccddee04c0", "112233445566778899aabbccddee04c0") + sstore("112233445566778899aabbccddee04c1", "112233445566778899aabbccddee04c1") + sstore("112233445566778899aabbccddee04c2", "112233445566778899aabbccddee04c2") + sstore("112233445566778899aabbccddee04c3", "112233445566778899aabbccddee04c3") + sstore("112233445566778899aabbccddee04c4", "112233445566778899aabbccddee04c4") + sstore("112233445566778899aabbccddee04c5", "112233445566778899aabbccddee04c5") + sstore("112233445566778899aabbccddee04c6", "112233445566778899aabbccddee04c6") + sstore("112233445566778899aabbccddee04c7", "112233445566778899aabbccddee04c7") + sstore("112233445566778899aabbccddee04c8", "112233445566778899aabbccddee04c8") + sstore("112233445566778899aabbccddee04c9", "112233445566778899aabbccddee04c9") + sstore("112233445566778899aabbccddee04ca", "112233445566778899aabbccddee04ca") + sstore("112233445566778899aabbccddee04cb", "112233445566778899aabbccddee04cb") + sstore("112233445566778899aabbccddee04cc", "112233445566778899aabbccddee04cc") + sstore("112233445566778899aabbccddee04cd", "112233445566778899aabbccddee04cd") + sstore("112233445566778899aabbccddee04ce", "112233445566778899aabbccddee04ce") + sstore("112233445566778899aabbccddee04cf", "112233445566778899aabbccddee04cf") + sstore("112233445566778899aabbccddee04d0", "112233445566778899aabbccddee04d0") + sstore("112233445566778899aabbccddee04d1", "112233445566778899aabbccddee04d1") + sstore("112233445566778899aabbccddee04d2", "112233445566778899aabbccddee04d2") + sstore("112233445566778899aabbccddee04d3", "112233445566778899aabbccddee04d3") + sstore("112233445566778899aabbccddee04d4", "112233445566778899aabbccddee04d4") + sstore("112233445566778899aabbccddee04d5", "112233445566778899aabbccddee04d5") + sstore("112233445566778899aabbccddee04d6", "112233445566778899aabbccddee04d6") + sstore("112233445566778899aabbccddee04d7", "112233445566778899aabbccddee04d7") + sstore("112233445566778899aabbccddee04d8", "112233445566778899aabbccddee04d8") + sstore("112233445566778899aabbccddee04d9", "112233445566778899aabbccddee04d9") + sstore("112233445566778899aabbccddee04da", "112233445566778899aabbccddee04da") + sstore("112233445566778899aabbccddee04db", "112233445566778899aabbccddee04db") + sstore("112233445566778899aabbccddee04dc", "112233445566778899aabbccddee04dc") + sstore("112233445566778899aabbccddee04dd", "112233445566778899aabbccddee04dd") + sstore("112233445566778899aabbccddee04de", "112233445566778899aabbccddee04de") + sstore("112233445566778899aabbccddee04df", "112233445566778899aabbccddee04df") + sstore("112233445566778899aabbccddee04e0", "112233445566778899aabbccddee04e0") + sstore("112233445566778899aabbccddee04e1", "112233445566778899aabbccddee04e1") + sstore("112233445566778899aabbccddee04e2", "112233445566778899aabbccddee04e2") + sstore("112233445566778899aabbccddee04e3", "112233445566778899aabbccddee04e3") + sstore("112233445566778899aabbccddee04e4", "112233445566778899aabbccddee04e4") + sstore("112233445566778899aabbccddee04e5", "112233445566778899aabbccddee04e5") + sstore("112233445566778899aabbccddee04e6", "112233445566778899aabbccddee04e6") + sstore("112233445566778899aabbccddee04e7", "112233445566778899aabbccddee04e7") + sstore("112233445566778899aabbccddee04e8", "112233445566778899aabbccddee04e8") + sstore("112233445566778899aabbccddee04e9", "112233445566778899aabbccddee04e9") + sstore("112233445566778899aabbccddee04ea", "112233445566778899aabbccddee04ea") + sstore("112233445566778899aabbccddee04eb", "112233445566778899aabbccddee04eb") + sstore("112233445566778899aabbccddee04ec", "112233445566778899aabbccddee04ec") + sstore("112233445566778899aabbccddee04ed", "112233445566778899aabbccddee04ed") + sstore("112233445566778899aabbccddee04ee", "112233445566778899aabbccddee04ee") + sstore("112233445566778899aabbccddee04ef", "112233445566778899aabbccddee04ef") + sstore("112233445566778899aabbccddee04f0", "112233445566778899aabbccddee04f0") + sstore("112233445566778899aabbccddee04f1", "112233445566778899aabbccddee04f1") + sstore("112233445566778899aabbccddee04f2", "112233445566778899aabbccddee04f2") + sstore("112233445566778899aabbccddee04f3", "112233445566778899aabbccddee04f3") + sstore("112233445566778899aabbccddee04f4", "112233445566778899aabbccddee04f4") + sstore("112233445566778899aabbccddee04f5", "112233445566778899aabbccddee04f5") + sstore("112233445566778899aabbccddee04f6", "112233445566778899aabbccddee04f6") + sstore("112233445566778899aabbccddee04f7", "112233445566778899aabbccddee04f7") + sstore("112233445566778899aabbccddee04f8", "112233445566778899aabbccddee04f8") + sstore("112233445566778899aabbccddee04f9", "112233445566778899aabbccddee04f9") + sstore("112233445566778899aabbccddee04fa", "112233445566778899aabbccddee04fa") + sstore("112233445566778899aabbccddee04fb", "112233445566778899aabbccddee04fb") + sstore("112233445566778899aabbccddee04fc", "112233445566778899aabbccddee04fc") + sstore("112233445566778899aabbccddee04fd", "112233445566778899aabbccddee04fd") + sstore("112233445566778899aabbccddee04fe", "112233445566778899aabbccddee04fe") + sstore("112233445566778899aabbccddee04ff", "112233445566778899aabbccddee04ff") + sstore("112233445566778899aabbccddee0500", "112233445566778899aabbccddee0500") + sstore("112233445566778899aabbccddee0501", "112233445566778899aabbccddee0501") + sstore("112233445566778899aabbccddee0502", "112233445566778899aabbccddee0502") + sstore("112233445566778899aabbccddee0503", "112233445566778899aabbccddee0503") + sstore("112233445566778899aabbccddee0504", "112233445566778899aabbccddee0504") + sstore("112233445566778899aabbccddee0505", "112233445566778899aabbccddee0505") + sstore("112233445566778899aabbccddee0506", "112233445566778899aabbccddee0506") + sstore("112233445566778899aabbccddee0507", "112233445566778899aabbccddee0507") + sstore("112233445566778899aabbccddee0508", "112233445566778899aabbccddee0508") + sstore("112233445566778899aabbccddee0509", "112233445566778899aabbccddee0509") + sstore("112233445566778899aabbccddee050a", "112233445566778899aabbccddee050a") + sstore("112233445566778899aabbccddee050b", "112233445566778899aabbccddee050b") + sstore("112233445566778899aabbccddee050c", "112233445566778899aabbccddee050c") + sstore("112233445566778899aabbccddee050d", "112233445566778899aabbccddee050d") + sstore("112233445566778899aabbccddee050e", "112233445566778899aabbccddee050e") + sstore("112233445566778899aabbccddee050f", "112233445566778899aabbccddee050f") + sstore("112233445566778899aabbccddee0510", "112233445566778899aabbccddee0510") + sstore("112233445566778899aabbccddee0511", "112233445566778899aabbccddee0511") + sstore("112233445566778899aabbccddee0512", "112233445566778899aabbccddee0512") + sstore("112233445566778899aabbccddee0513", "112233445566778899aabbccddee0513") + sstore("112233445566778899aabbccddee0514", "112233445566778899aabbccddee0514") + sstore("112233445566778899aabbccddee0515", "112233445566778899aabbccddee0515") + sstore("112233445566778899aabbccddee0516", "112233445566778899aabbccddee0516") + sstore("112233445566778899aabbccddee0517", "112233445566778899aabbccddee0517") + sstore("112233445566778899aabbccddee0518", "112233445566778899aabbccddee0518") + sstore("112233445566778899aabbccddee0519", "112233445566778899aabbccddee0519") + sstore("112233445566778899aabbccddee051a", "112233445566778899aabbccddee051a") + sstore("112233445566778899aabbccddee051b", "112233445566778899aabbccddee051b") + sstore("112233445566778899aabbccddee051c", "112233445566778899aabbccddee051c") + sstore("112233445566778899aabbccddee051d", "112233445566778899aabbccddee051d") + sstore("112233445566778899aabbccddee051e", "112233445566778899aabbccddee051e") + sstore("112233445566778899aabbccddee051f", "112233445566778899aabbccddee051f") + sstore("112233445566778899aabbccddee0520", "112233445566778899aabbccddee0520") + sstore("112233445566778899aabbccddee0521", "112233445566778899aabbccddee0521") + sstore("112233445566778899aabbccddee0522", "112233445566778899aabbccddee0522") + sstore("112233445566778899aabbccddee0523", "112233445566778899aabbccddee0523") + sstore("112233445566778899aabbccddee0524", "112233445566778899aabbccddee0524") + sstore("112233445566778899aabbccddee0525", "112233445566778899aabbccddee0525") + sstore("112233445566778899aabbccddee0526", "112233445566778899aabbccddee0526") + sstore("112233445566778899aabbccddee0527", "112233445566778899aabbccddee0527") + sstore("112233445566778899aabbccddee0528", "112233445566778899aabbccddee0528") + sstore("112233445566778899aabbccddee0529", "112233445566778899aabbccddee0529") + sstore("112233445566778899aabbccddee052a", "112233445566778899aabbccddee052a") + sstore("112233445566778899aabbccddee052b", "112233445566778899aabbccddee052b") + sstore("112233445566778899aabbccddee052c", "112233445566778899aabbccddee052c") + sstore("112233445566778899aabbccddee052d", "112233445566778899aabbccddee052d") + sstore("112233445566778899aabbccddee052e", "112233445566778899aabbccddee052e") + sstore("112233445566778899aabbccddee052f", "112233445566778899aabbccddee052f") + sstore("112233445566778899aabbccddee0530", "112233445566778899aabbccddee0530") + sstore("112233445566778899aabbccddee0531", "112233445566778899aabbccddee0531") + sstore("112233445566778899aabbccddee0532", "112233445566778899aabbccddee0532") + sstore("112233445566778899aabbccddee0533", "112233445566778899aabbccddee0533") + sstore("112233445566778899aabbccddee0534", "112233445566778899aabbccddee0534") + sstore("112233445566778899aabbccddee0535", "112233445566778899aabbccddee0535") + sstore("112233445566778899aabbccddee0536", "112233445566778899aabbccddee0536") + sstore("112233445566778899aabbccddee0537", "112233445566778899aabbccddee0537") + sstore("112233445566778899aabbccddee0538", "112233445566778899aabbccddee0538") + sstore("112233445566778899aabbccddee0539", "112233445566778899aabbccddee0539") + sstore("112233445566778899aabbccddee053a", "112233445566778899aabbccddee053a") + sstore("112233445566778899aabbccddee053b", "112233445566778899aabbccddee053b") + sstore("112233445566778899aabbccddee053c", "112233445566778899aabbccddee053c") + sstore("112233445566778899aabbccddee053d", "112233445566778899aabbccddee053d") + sstore("112233445566778899aabbccddee053e", "112233445566778899aabbccddee053e") + sstore("112233445566778899aabbccddee053f", "112233445566778899aabbccddee053f") + sstore("112233445566778899aabbccddee0540", "112233445566778899aabbccddee0540") + sstore("112233445566778899aabbccddee0541", "112233445566778899aabbccddee0541") + sstore("112233445566778899aabbccddee0542", "112233445566778899aabbccddee0542") + sstore("112233445566778899aabbccddee0543", "112233445566778899aabbccddee0543") + sstore("112233445566778899aabbccddee0544", "112233445566778899aabbccddee0544") + sstore("112233445566778899aabbccddee0545", "112233445566778899aabbccddee0545") + sstore("112233445566778899aabbccddee0546", "112233445566778899aabbccddee0546") + sstore("112233445566778899aabbccddee0547", "112233445566778899aabbccddee0547") + sstore("112233445566778899aabbccddee0548", "112233445566778899aabbccddee0548") + sstore("112233445566778899aabbccddee0549", "112233445566778899aabbccddee0549") + sstore("112233445566778899aabbccddee054a", "112233445566778899aabbccddee054a") + sstore("112233445566778899aabbccddee054b", "112233445566778899aabbccddee054b") + sstore("112233445566778899aabbccddee054c", "112233445566778899aabbccddee054c") + sstore("112233445566778899aabbccddee054d", "112233445566778899aabbccddee054d") + sstore("112233445566778899aabbccddee054e", "112233445566778899aabbccddee054e") + sstore("112233445566778899aabbccddee054f", "112233445566778899aabbccddee054f") + sstore("112233445566778899aabbccddee0550", "112233445566778899aabbccddee0550") + sstore("112233445566778899aabbccddee0551", "112233445566778899aabbccddee0551") + sstore("112233445566778899aabbccddee0552", "112233445566778899aabbccddee0552") + sstore("112233445566778899aabbccddee0553", "112233445566778899aabbccddee0553") + sstore("112233445566778899aabbccddee0554", "112233445566778899aabbccddee0554") + sstore("112233445566778899aabbccddee0555", "112233445566778899aabbccddee0555") + sstore("112233445566778899aabbccddee0556", "112233445566778899aabbccddee0556") + sstore("112233445566778899aabbccddee0557", "112233445566778899aabbccddee0557") + sstore("112233445566778899aabbccddee0558", "112233445566778899aabbccddee0558") + sstore("112233445566778899aabbccddee0559", "112233445566778899aabbccddee0559") + sstore("112233445566778899aabbccddee055a", "112233445566778899aabbccddee055a") + sstore("112233445566778899aabbccddee055b", "112233445566778899aabbccddee055b") + sstore("112233445566778899aabbccddee055c", "112233445566778899aabbccddee055c") + sstore("112233445566778899aabbccddee055d", "112233445566778899aabbccddee055d") + sstore("112233445566778899aabbccddee055e", "112233445566778899aabbccddee055e") + sstore("112233445566778899aabbccddee055f", "112233445566778899aabbccddee055f") + sstore("112233445566778899aabbccddee0560", "112233445566778899aabbccddee0560") + sstore("112233445566778899aabbccddee0561", "112233445566778899aabbccddee0561") + sstore("112233445566778899aabbccddee0562", "112233445566778899aabbccddee0562") + sstore("112233445566778899aabbccddee0563", "112233445566778899aabbccddee0563") + sstore("112233445566778899aabbccddee0564", "112233445566778899aabbccddee0564") + sstore("112233445566778899aabbccddee0565", "112233445566778899aabbccddee0565") + sstore("112233445566778899aabbccddee0566", "112233445566778899aabbccddee0566") + sstore("112233445566778899aabbccddee0567", "112233445566778899aabbccddee0567") + sstore("112233445566778899aabbccddee0568", "112233445566778899aabbccddee0568") + sstore("112233445566778899aabbccddee0569", "112233445566778899aabbccddee0569") + sstore("112233445566778899aabbccddee056a", "112233445566778899aabbccddee056a") + sstore("112233445566778899aabbccddee056b", "112233445566778899aabbccddee056b") + sstore("112233445566778899aabbccddee056c", "112233445566778899aabbccddee056c") + sstore("112233445566778899aabbccddee056d", "112233445566778899aabbccddee056d") + sstore("112233445566778899aabbccddee056e", "112233445566778899aabbccddee056e") + sstore("112233445566778899aabbccddee056f", "112233445566778899aabbccddee056f") + sstore("112233445566778899aabbccddee0570", "112233445566778899aabbccddee0570") + sstore("112233445566778899aabbccddee0571", "112233445566778899aabbccddee0571") + sstore("112233445566778899aabbccddee0572", "112233445566778899aabbccddee0572") + sstore("112233445566778899aabbccddee0573", "112233445566778899aabbccddee0573") + sstore("112233445566778899aabbccddee0574", "112233445566778899aabbccddee0574") + sstore("112233445566778899aabbccddee0575", "112233445566778899aabbccddee0575") + sstore("112233445566778899aabbccddee0576", "112233445566778899aabbccddee0576") + sstore("112233445566778899aabbccddee0577", "112233445566778899aabbccddee0577") + sstore("112233445566778899aabbccddee0578", "112233445566778899aabbccddee0578") + sstore("112233445566778899aabbccddee0579", "112233445566778899aabbccddee0579") + sstore("112233445566778899aabbccddee057a", "112233445566778899aabbccddee057a") + sstore("112233445566778899aabbccddee057b", "112233445566778899aabbccddee057b") + sstore("112233445566778899aabbccddee057c", "112233445566778899aabbccddee057c") + sstore("112233445566778899aabbccddee057d", "112233445566778899aabbccddee057d") + sstore("112233445566778899aabbccddee057e", "112233445566778899aabbccddee057e") + sstore("112233445566778899aabbccddee057f", "112233445566778899aabbccddee057f") + sstore("112233445566778899aabbccddee0580", "112233445566778899aabbccddee0580") + sstore("112233445566778899aabbccddee0581", "112233445566778899aabbccddee0581") + sstore("112233445566778899aabbccddee0582", "112233445566778899aabbccddee0582") + sstore("112233445566778899aabbccddee0583", "112233445566778899aabbccddee0583") + sstore("112233445566778899aabbccddee0584", "112233445566778899aabbccddee0584") + sstore("112233445566778899aabbccddee0585", "112233445566778899aabbccddee0585") + sstore("112233445566778899aabbccddee0586", "112233445566778899aabbccddee0586") + sstore("112233445566778899aabbccddee0587", "112233445566778899aabbccddee0587") + sstore("112233445566778899aabbccddee0588", "112233445566778899aabbccddee0588") + sstore("112233445566778899aabbccddee0589", "112233445566778899aabbccddee0589") + sstore("112233445566778899aabbccddee058a", "112233445566778899aabbccddee058a") + sstore("112233445566778899aabbccddee058b", "112233445566778899aabbccddee058b") + sstore("112233445566778899aabbccddee058c", "112233445566778899aabbccddee058c") + sstore("112233445566778899aabbccddee058d", "112233445566778899aabbccddee058d") + sstore("112233445566778899aabbccddee058e", "112233445566778899aabbccddee058e") + sstore("112233445566778899aabbccddee058f", "112233445566778899aabbccddee058f") + sstore("112233445566778899aabbccddee0590", "112233445566778899aabbccddee0590") + sstore("112233445566778899aabbccddee0591", "112233445566778899aabbccddee0591") + sstore("112233445566778899aabbccddee0592", "112233445566778899aabbccddee0592") + sstore("112233445566778899aabbccddee0593", "112233445566778899aabbccddee0593") + sstore("112233445566778899aabbccddee0594", "112233445566778899aabbccddee0594") + sstore("112233445566778899aabbccddee0595", "112233445566778899aabbccddee0595") + sstore("112233445566778899aabbccddee0596", "112233445566778899aabbccddee0596") + sstore("112233445566778899aabbccddee0597", "112233445566778899aabbccddee0597") + sstore("112233445566778899aabbccddee0598", "112233445566778899aabbccddee0598") + sstore("112233445566778899aabbccddee0599", "112233445566778899aabbccddee0599") + sstore("112233445566778899aabbccddee059a", "112233445566778899aabbccddee059a") + sstore("112233445566778899aabbccddee059b", "112233445566778899aabbccddee059b") + sstore("112233445566778899aabbccddee059c", "112233445566778899aabbccddee059c") + sstore("112233445566778899aabbccddee059d", "112233445566778899aabbccddee059d") + sstore("112233445566778899aabbccddee059e", "112233445566778899aabbccddee059e") + sstore("112233445566778899aabbccddee059f", "112233445566778899aabbccddee059f") + sstore("112233445566778899aabbccddee05a0", "112233445566778899aabbccddee05a0") + sstore("112233445566778899aabbccddee05a1", "112233445566778899aabbccddee05a1") + sstore("112233445566778899aabbccddee05a2", "112233445566778899aabbccddee05a2") + sstore("112233445566778899aabbccddee05a3", "112233445566778899aabbccddee05a3") + sstore("112233445566778899aabbccddee05a4", "112233445566778899aabbccddee05a4") + sstore("112233445566778899aabbccddee05a5", "112233445566778899aabbccddee05a5") + sstore("112233445566778899aabbccddee05a6", "112233445566778899aabbccddee05a6") + sstore("112233445566778899aabbccddee05a7", "112233445566778899aabbccddee05a7") + sstore("112233445566778899aabbccddee05a8", "112233445566778899aabbccddee05a8") + sstore("112233445566778899aabbccddee05a9", "112233445566778899aabbccddee05a9") + sstore("112233445566778899aabbccddee05aa", "112233445566778899aabbccddee05aa") + sstore("112233445566778899aabbccddee05ab", "112233445566778899aabbccddee05ab") + sstore("112233445566778899aabbccddee05ac", "112233445566778899aabbccddee05ac") + sstore("112233445566778899aabbccddee05ad", "112233445566778899aabbccddee05ad") + sstore("112233445566778899aabbccddee05ae", "112233445566778899aabbccddee05ae") + sstore("112233445566778899aabbccddee05af", "112233445566778899aabbccddee05af") + sstore("112233445566778899aabbccddee05b0", "112233445566778899aabbccddee05b0") + sstore("112233445566778899aabbccddee05b1", "112233445566778899aabbccddee05b1") + sstore("112233445566778899aabbccddee05b2", "112233445566778899aabbccddee05b2") + sstore("112233445566778899aabbccddee05b3", "112233445566778899aabbccddee05b3") + sstore("112233445566778899aabbccddee05b4", "112233445566778899aabbccddee05b4") + sstore("112233445566778899aabbccddee05b5", "112233445566778899aabbccddee05b5") + sstore("112233445566778899aabbccddee05b6", "112233445566778899aabbccddee05b6") + sstore("112233445566778899aabbccddee05b7", "112233445566778899aabbccddee05b7") + sstore("112233445566778899aabbccddee05b8", "112233445566778899aabbccddee05b8") + sstore("112233445566778899aabbccddee05b9", "112233445566778899aabbccddee05b9") + sstore("112233445566778899aabbccddee05ba", "112233445566778899aabbccddee05ba") + sstore("112233445566778899aabbccddee05bb", "112233445566778899aabbccddee05bb") + sstore("112233445566778899aabbccddee05bc", "112233445566778899aabbccddee05bc") + sstore("112233445566778899aabbccddee05bd", "112233445566778899aabbccddee05bd") + sstore("112233445566778899aabbccddee05be", "112233445566778899aabbccddee05be") + sstore("112233445566778899aabbccddee05bf", "112233445566778899aabbccddee05bf") + sstore("112233445566778899aabbccddee05c0", "112233445566778899aabbccddee05c0") + sstore("112233445566778899aabbccddee05c1", "112233445566778899aabbccddee05c1") + sstore("112233445566778899aabbccddee05c2", "112233445566778899aabbccddee05c2") + sstore("112233445566778899aabbccddee05c3", "112233445566778899aabbccddee05c3") + sstore("112233445566778899aabbccddee05c4", "112233445566778899aabbccddee05c4") + sstore("112233445566778899aabbccddee05c5", "112233445566778899aabbccddee05c5") + sstore("112233445566778899aabbccddee05c6", "112233445566778899aabbccddee05c6") + sstore("112233445566778899aabbccddee05c7", "112233445566778899aabbccddee05c7") + sstore("112233445566778899aabbccddee05c8", "112233445566778899aabbccddee05c8") + sstore("112233445566778899aabbccddee05c9", "112233445566778899aabbccddee05c9") + sstore("112233445566778899aabbccddee05ca", "112233445566778899aabbccddee05ca") + sstore("112233445566778899aabbccddee05cb", "112233445566778899aabbccddee05cb") + sstore("112233445566778899aabbccddee05cc", "112233445566778899aabbccddee05cc") + sstore("112233445566778899aabbccddee05cd", "112233445566778899aabbccddee05cd") + sstore("112233445566778899aabbccddee05ce", "112233445566778899aabbccddee05ce") + sstore("112233445566778899aabbccddee05cf", "112233445566778899aabbccddee05cf") + sstore("112233445566778899aabbccddee05d0", "112233445566778899aabbccddee05d0") + sstore("112233445566778899aabbccddee05d1", "112233445566778899aabbccddee05d1") + sstore("112233445566778899aabbccddee05d2", "112233445566778899aabbccddee05d2") + sstore("112233445566778899aabbccddee05d3", "112233445566778899aabbccddee05d3") + sstore("112233445566778899aabbccddee05d4", "112233445566778899aabbccddee05d4") + sstore("112233445566778899aabbccddee05d5", "112233445566778899aabbccddee05d5") + sstore("112233445566778899aabbccddee05d6", "112233445566778899aabbccddee05d6") + sstore("112233445566778899aabbccddee05d7", "112233445566778899aabbccddee05d7") + sstore("112233445566778899aabbccddee05d8", "112233445566778899aabbccddee05d8") + sstore("112233445566778899aabbccddee05d9", "112233445566778899aabbccddee05d9") + sstore("112233445566778899aabbccddee05da", "112233445566778899aabbccddee05da") + sstore("112233445566778899aabbccddee05db", "112233445566778899aabbccddee05db") + sstore("112233445566778899aabbccddee05dc", "112233445566778899aabbccddee05dc") + sstore("112233445566778899aabbccddee05dd", "112233445566778899aabbccddee05dd") + sstore("112233445566778899aabbccddee05de", "112233445566778899aabbccddee05de") + sstore("112233445566778899aabbccddee05df", "112233445566778899aabbccddee05df") + sstore("112233445566778899aabbccddee05e0", "112233445566778899aabbccddee05e0") + sstore("112233445566778899aabbccddee05e1", "112233445566778899aabbccddee05e1") + sstore("112233445566778899aabbccddee05e2", "112233445566778899aabbccddee05e2") + sstore("112233445566778899aabbccddee05e3", "112233445566778899aabbccddee05e3") + sstore("112233445566778899aabbccddee05e4", "112233445566778899aabbccddee05e4") + sstore("112233445566778899aabbccddee05e5", "112233445566778899aabbccddee05e5") + sstore("112233445566778899aabbccddee05e6", "112233445566778899aabbccddee05e6") + sstore("112233445566778899aabbccddee05e7", "112233445566778899aabbccddee05e7") + sstore("112233445566778899aabbccddee05e8", "112233445566778899aabbccddee05e8") + sstore("112233445566778899aabbccddee05e9", "112233445566778899aabbccddee05e9") + sstore("112233445566778899aabbccddee05ea", "112233445566778899aabbccddee05ea") + sstore("112233445566778899aabbccddee05eb", "112233445566778899aabbccddee05eb") + sstore("112233445566778899aabbccddee05ec", "112233445566778899aabbccddee05ec") + sstore("112233445566778899aabbccddee05ed", "112233445566778899aabbccddee05ed") + sstore("112233445566778899aabbccddee05ee", "112233445566778899aabbccddee05ee") + sstore("112233445566778899aabbccddee05ef", "112233445566778899aabbccddee05ef") + sstore("112233445566778899aabbccddee05f0", "112233445566778899aabbccddee05f0") + sstore("112233445566778899aabbccddee05f1", "112233445566778899aabbccddee05f1") + sstore("112233445566778899aabbccddee05f2", "112233445566778899aabbccddee05f2") + sstore("112233445566778899aabbccddee05f3", "112233445566778899aabbccddee05f3") + sstore("112233445566778899aabbccddee05f4", "112233445566778899aabbccddee05f4") + sstore("112233445566778899aabbccddee05f5", "112233445566778899aabbccddee05f5") + sstore("112233445566778899aabbccddee05f6", "112233445566778899aabbccddee05f6") + sstore("112233445566778899aabbccddee05f7", "112233445566778899aabbccddee05f7") + sstore("112233445566778899aabbccddee05f8", "112233445566778899aabbccddee05f8") + sstore("112233445566778899aabbccddee05f9", "112233445566778899aabbccddee05f9") + sstore("112233445566778899aabbccddee05fa", "112233445566778899aabbccddee05fa") + sstore("112233445566778899aabbccddee05fb", "112233445566778899aabbccddee05fb") + sstore("112233445566778899aabbccddee05fc", "112233445566778899aabbccddee05fc") + sstore("112233445566778899aabbccddee05fd", "112233445566778899aabbccddee05fd") + sstore("112233445566778899aabbccddee05fe", "112233445566778899aabbccddee05fe") + sstore("112233445566778899aabbccddee05ff", "112233445566778899aabbccddee05ff") + sstore("112233445566778899aabbccddee0600", "112233445566778899aabbccddee0600") + sstore("112233445566778899aabbccddee0601", "112233445566778899aabbccddee0601") + sstore("112233445566778899aabbccddee0602", "112233445566778899aabbccddee0602") + sstore("112233445566778899aabbccddee0603", "112233445566778899aabbccddee0603") + sstore("112233445566778899aabbccddee0604", "112233445566778899aabbccddee0604") + sstore("112233445566778899aabbccddee0605", "112233445566778899aabbccddee0605") + sstore("112233445566778899aabbccddee0606", "112233445566778899aabbccddee0606") + sstore("112233445566778899aabbccddee0607", "112233445566778899aabbccddee0607") + sstore("112233445566778899aabbccddee0608", "112233445566778899aabbccddee0608") + sstore("112233445566778899aabbccddee0609", "112233445566778899aabbccddee0609") + sstore("112233445566778899aabbccddee060a", "112233445566778899aabbccddee060a") + sstore("112233445566778899aabbccddee060b", "112233445566778899aabbccddee060b") + sstore("112233445566778899aabbccddee060c", "112233445566778899aabbccddee060c") + sstore("112233445566778899aabbccddee060d", "112233445566778899aabbccddee060d") + sstore("112233445566778899aabbccddee060e", "112233445566778899aabbccddee060e") + sstore("112233445566778899aabbccddee060f", "112233445566778899aabbccddee060f") + sstore("112233445566778899aabbccddee0610", "112233445566778899aabbccddee0610") + sstore("112233445566778899aabbccddee0611", "112233445566778899aabbccddee0611") + sstore("112233445566778899aabbccddee0612", "112233445566778899aabbccddee0612") + sstore("112233445566778899aabbccddee0613", "112233445566778899aabbccddee0613") + sstore("112233445566778899aabbccddee0614", "112233445566778899aabbccddee0614") + sstore("112233445566778899aabbccddee0615", "112233445566778899aabbccddee0615") + sstore("112233445566778899aabbccddee0616", "112233445566778899aabbccddee0616") + sstore("112233445566778899aabbccddee0617", "112233445566778899aabbccddee0617") + sstore("112233445566778899aabbccddee0618", "112233445566778899aabbccddee0618") + sstore("112233445566778899aabbccddee0619", "112233445566778899aabbccddee0619") + sstore("112233445566778899aabbccddee061a", "112233445566778899aabbccddee061a") + sstore("112233445566778899aabbccddee061b", "112233445566778899aabbccddee061b") + sstore("112233445566778899aabbccddee061c", "112233445566778899aabbccddee061c") + sstore("112233445566778899aabbccddee061d", "112233445566778899aabbccddee061d") + sstore("112233445566778899aabbccddee061e", "112233445566778899aabbccddee061e") + sstore("112233445566778899aabbccddee061f", "112233445566778899aabbccddee061f") + sstore("112233445566778899aabbccddee0620", "112233445566778899aabbccddee0620") + sstore("112233445566778899aabbccddee0621", "112233445566778899aabbccddee0621") + sstore("112233445566778899aabbccddee0622", "112233445566778899aabbccddee0622") + sstore("112233445566778899aabbccddee0623", "112233445566778899aabbccddee0623") + sstore("112233445566778899aabbccddee0624", "112233445566778899aabbccddee0624") + sstore("112233445566778899aabbccddee0625", "112233445566778899aabbccddee0625") + sstore("112233445566778899aabbccddee0626", "112233445566778899aabbccddee0626") + sstore("112233445566778899aabbccddee0627", "112233445566778899aabbccddee0627") + sstore("112233445566778899aabbccddee0628", "112233445566778899aabbccddee0628") + sstore("112233445566778899aabbccddee0629", "112233445566778899aabbccddee0629") + sstore("112233445566778899aabbccddee062a", "112233445566778899aabbccddee062a") + sstore("112233445566778899aabbccddee062b", "112233445566778899aabbccddee062b") + sstore("112233445566778899aabbccddee062c", "112233445566778899aabbccddee062c") + sstore("112233445566778899aabbccddee062d", "112233445566778899aabbccddee062d") + sstore("112233445566778899aabbccddee062e", "112233445566778899aabbccddee062e") + sstore("112233445566778899aabbccddee062f", "112233445566778899aabbccddee062f") + sstore("112233445566778899aabbccddee0630", "112233445566778899aabbccddee0630") + sstore("112233445566778899aabbccddee0631", "112233445566778899aabbccddee0631") + sstore("112233445566778899aabbccddee0632", "112233445566778899aabbccddee0632") + sstore("112233445566778899aabbccddee0633", "112233445566778899aabbccddee0633") + sstore("112233445566778899aabbccddee0634", "112233445566778899aabbccddee0634") + sstore("112233445566778899aabbccddee0635", "112233445566778899aabbccddee0635") + sstore("112233445566778899aabbccddee0636", "112233445566778899aabbccddee0636") + sstore("112233445566778899aabbccddee0637", "112233445566778899aabbccddee0637") + sstore("112233445566778899aabbccddee0638", "112233445566778899aabbccddee0638") + sstore("112233445566778899aabbccddee0639", "112233445566778899aabbccddee0639") + sstore("112233445566778899aabbccddee063a", "112233445566778899aabbccddee063a") + sstore("112233445566778899aabbccddee063b", "112233445566778899aabbccddee063b") + sstore("112233445566778899aabbccddee063c", "112233445566778899aabbccddee063c") + sstore("112233445566778899aabbccddee063d", "112233445566778899aabbccddee063d") + sstore("112233445566778899aabbccddee063e", "112233445566778899aabbccddee063e") + sstore("112233445566778899aabbccddee063f", "112233445566778899aabbccddee063f") + sstore("112233445566778899aabbccddee0640", "112233445566778899aabbccddee0640") + sstore("112233445566778899aabbccddee0641", "112233445566778899aabbccddee0641") + sstore("112233445566778899aabbccddee0642", "112233445566778899aabbccddee0642") + sstore("112233445566778899aabbccddee0643", "112233445566778899aabbccddee0643") + sstore("112233445566778899aabbccddee0644", "112233445566778899aabbccddee0644") + sstore("112233445566778899aabbccddee0645", "112233445566778899aabbccddee0645") + sstore("112233445566778899aabbccddee0646", "112233445566778899aabbccddee0646") + sstore("112233445566778899aabbccddee0647", "112233445566778899aabbccddee0647") + sstore("112233445566778899aabbccddee0648", "112233445566778899aabbccddee0648") + sstore("112233445566778899aabbccddee0649", "112233445566778899aabbccddee0649") + sstore("112233445566778899aabbccddee064a", "112233445566778899aabbccddee064a") + sstore("112233445566778899aabbccddee064b", "112233445566778899aabbccddee064b") + sstore("112233445566778899aabbccddee064c", "112233445566778899aabbccddee064c") + sstore("112233445566778899aabbccddee064d", "112233445566778899aabbccddee064d") + sstore("112233445566778899aabbccddee064e", "112233445566778899aabbccddee064e") + sstore("112233445566778899aabbccddee064f", "112233445566778899aabbccddee064f") + sstore("112233445566778899aabbccddee0650", "112233445566778899aabbccddee0650") + sstore("112233445566778899aabbccddee0651", "112233445566778899aabbccddee0651") + sstore("112233445566778899aabbccddee0652", "112233445566778899aabbccddee0652") + sstore("112233445566778899aabbccddee0653", "112233445566778899aabbccddee0653") + sstore("112233445566778899aabbccddee0654", "112233445566778899aabbccddee0654") + sstore("112233445566778899aabbccddee0655", "112233445566778899aabbccddee0655") + sstore("112233445566778899aabbccddee0656", "112233445566778899aabbccddee0656") + sstore("112233445566778899aabbccddee0657", "112233445566778899aabbccddee0657") + sstore("112233445566778899aabbccddee0658", "112233445566778899aabbccddee0658") + sstore("112233445566778899aabbccddee0659", "112233445566778899aabbccddee0659") + sstore("112233445566778899aabbccddee065a", "112233445566778899aabbccddee065a") + sstore("112233445566778899aabbccddee065b", "112233445566778899aabbccddee065b") + sstore("112233445566778899aabbccddee065c", "112233445566778899aabbccddee065c") + sstore("112233445566778899aabbccddee065d", "112233445566778899aabbccddee065d") + sstore("112233445566778899aabbccddee065e", "112233445566778899aabbccddee065e") + sstore("112233445566778899aabbccddee065f", "112233445566778899aabbccddee065f") + sstore("112233445566778899aabbccddee0660", "112233445566778899aabbccddee0660") + sstore("112233445566778899aabbccddee0661", "112233445566778899aabbccddee0661") + sstore("112233445566778899aabbccddee0662", "112233445566778899aabbccddee0662") + sstore("112233445566778899aabbccddee0663", "112233445566778899aabbccddee0663") + sstore("112233445566778899aabbccddee0664", "112233445566778899aabbccddee0664") + sstore("112233445566778899aabbccddee0665", "112233445566778899aabbccddee0665") + sstore("112233445566778899aabbccddee0666", "112233445566778899aabbccddee0666") + sstore("112233445566778899aabbccddee0667", "112233445566778899aabbccddee0667") + sstore("112233445566778899aabbccddee0668", "112233445566778899aabbccddee0668") + sstore("112233445566778899aabbccddee0669", "112233445566778899aabbccddee0669") + sstore("112233445566778899aabbccddee066a", "112233445566778899aabbccddee066a") + sstore("112233445566778899aabbccddee066b", "112233445566778899aabbccddee066b") + sstore("112233445566778899aabbccddee066c", "112233445566778899aabbccddee066c") + sstore("112233445566778899aabbccddee066d", "112233445566778899aabbccddee066d") + sstore("112233445566778899aabbccddee066e", "112233445566778899aabbccddee066e") + sstore("112233445566778899aabbccddee066f", "112233445566778899aabbccddee066f") + sstore("112233445566778899aabbccddee0670", "112233445566778899aabbccddee0670") + sstore("112233445566778899aabbccddee0671", "112233445566778899aabbccddee0671") + sstore("112233445566778899aabbccddee0672", "112233445566778899aabbccddee0672") + sstore("112233445566778899aabbccddee0673", "112233445566778899aabbccddee0673") + sstore("112233445566778899aabbccddee0674", "112233445566778899aabbccddee0674") + sstore("112233445566778899aabbccddee0675", "112233445566778899aabbccddee0675") + sstore("112233445566778899aabbccddee0676", "112233445566778899aabbccddee0676") + sstore("112233445566778899aabbccddee0677", "112233445566778899aabbccddee0677") + sstore("112233445566778899aabbccddee0678", "112233445566778899aabbccddee0678") + sstore("112233445566778899aabbccddee0679", "112233445566778899aabbccddee0679") + sstore("112233445566778899aabbccddee067a", "112233445566778899aabbccddee067a") + sstore("112233445566778899aabbccddee067b", "112233445566778899aabbccddee067b") + sstore("112233445566778899aabbccddee067c", "112233445566778899aabbccddee067c") + sstore("112233445566778899aabbccddee067d", "112233445566778899aabbccddee067d") + sstore("112233445566778899aabbccddee067e", "112233445566778899aabbccddee067e") + sstore("112233445566778899aabbccddee067f", "112233445566778899aabbccddee067f") + sstore("112233445566778899aabbccddee0680", "112233445566778899aabbccddee0680") + sstore("112233445566778899aabbccddee0681", "112233445566778899aabbccddee0681") + sstore("112233445566778899aabbccddee0682", "112233445566778899aabbccddee0682") + sstore("112233445566778899aabbccddee0683", "112233445566778899aabbccddee0683") + sstore("112233445566778899aabbccddee0684", "112233445566778899aabbccddee0684") + sstore("112233445566778899aabbccddee0685", "112233445566778899aabbccddee0685") + sstore("112233445566778899aabbccddee0686", "112233445566778899aabbccddee0686") + sstore("112233445566778899aabbccddee0687", "112233445566778899aabbccddee0687") + sstore("112233445566778899aabbccddee0688", "112233445566778899aabbccddee0688") + sstore("112233445566778899aabbccddee0689", "112233445566778899aabbccddee0689") + sstore("112233445566778899aabbccddee068a", "112233445566778899aabbccddee068a") + sstore("112233445566778899aabbccddee068b", "112233445566778899aabbccddee068b") + sstore("112233445566778899aabbccddee068c", "112233445566778899aabbccddee068c") + sstore("112233445566778899aabbccddee068d", "112233445566778899aabbccddee068d") + sstore("112233445566778899aabbccddee068e", "112233445566778899aabbccddee068e") + sstore("112233445566778899aabbccddee068f", "112233445566778899aabbccddee068f") + sstore("112233445566778899aabbccddee0690", "112233445566778899aabbccddee0690") + sstore("112233445566778899aabbccddee0691", "112233445566778899aabbccddee0691") + sstore("112233445566778899aabbccddee0692", "112233445566778899aabbccddee0692") + sstore("112233445566778899aabbccddee0693", "112233445566778899aabbccddee0693") + sstore("112233445566778899aabbccddee0694", "112233445566778899aabbccddee0694") + sstore("112233445566778899aabbccddee0695", "112233445566778899aabbccddee0695") + sstore("112233445566778899aabbccddee0696", "112233445566778899aabbccddee0696") + sstore("112233445566778899aabbccddee0697", "112233445566778899aabbccddee0697") + sstore("112233445566778899aabbccddee0698", "112233445566778899aabbccddee0698") + sstore("112233445566778899aabbccddee0699", "112233445566778899aabbccddee0699") + sstore("112233445566778899aabbccddee069a", "112233445566778899aabbccddee069a") + sstore("112233445566778899aabbccddee069b", "112233445566778899aabbccddee069b") + sstore("112233445566778899aabbccddee069c", "112233445566778899aabbccddee069c") + sstore("112233445566778899aabbccddee069d", "112233445566778899aabbccddee069d") + sstore("112233445566778899aabbccddee069e", "112233445566778899aabbccddee069e") + sstore("112233445566778899aabbccddee069f", "112233445566778899aabbccddee069f") + sstore("112233445566778899aabbccddee06a0", "112233445566778899aabbccddee06a0") + sstore("112233445566778899aabbccddee06a1", "112233445566778899aabbccddee06a1") + sstore("112233445566778899aabbccddee06a2", "112233445566778899aabbccddee06a2") + sstore("112233445566778899aabbccddee06a3", "112233445566778899aabbccddee06a3") + sstore("112233445566778899aabbccddee06a4", "112233445566778899aabbccddee06a4") + sstore("112233445566778899aabbccddee06a5", "112233445566778899aabbccddee06a5") + sstore("112233445566778899aabbccddee06a6", "112233445566778899aabbccddee06a6") + sstore("112233445566778899aabbccddee06a7", "112233445566778899aabbccddee06a7") + sstore("112233445566778899aabbccddee06a8", "112233445566778899aabbccddee06a8") + sstore("112233445566778899aabbccddee06a9", "112233445566778899aabbccddee06a9") + sstore("112233445566778899aabbccddee06aa", "112233445566778899aabbccddee06aa") + sstore("112233445566778899aabbccddee06ab", "112233445566778899aabbccddee06ab") + sstore("112233445566778899aabbccddee06ac", "112233445566778899aabbccddee06ac") + sstore("112233445566778899aabbccddee06ad", "112233445566778899aabbccddee06ad") + sstore("112233445566778899aabbccddee06ae", "112233445566778899aabbccddee06ae") + sstore("112233445566778899aabbccddee06af", "112233445566778899aabbccddee06af") + sstore("112233445566778899aabbccddee06b0", "112233445566778899aabbccddee06b0") + sstore("112233445566778899aabbccddee06b1", "112233445566778899aabbccddee06b1") + sstore("112233445566778899aabbccddee06b2", "112233445566778899aabbccddee06b2") + sstore("112233445566778899aabbccddee06b3", "112233445566778899aabbccddee06b3") + sstore("112233445566778899aabbccddee06b4", "112233445566778899aabbccddee06b4") + sstore("112233445566778899aabbccddee06b5", "112233445566778899aabbccddee06b5") + sstore("112233445566778899aabbccddee06b6", "112233445566778899aabbccddee06b6") + sstore("112233445566778899aabbccddee06b7", "112233445566778899aabbccddee06b7") + sstore("112233445566778899aabbccddee06b8", "112233445566778899aabbccddee06b8") + sstore("112233445566778899aabbccddee06b9", "112233445566778899aabbccddee06b9") + sstore("112233445566778899aabbccddee06ba", "112233445566778899aabbccddee06ba") + sstore("112233445566778899aabbccddee06bb", "112233445566778899aabbccddee06bb") + sstore("112233445566778899aabbccddee06bc", "112233445566778899aabbccddee06bc") + sstore("112233445566778899aabbccddee06bd", "112233445566778899aabbccddee06bd") + sstore("112233445566778899aabbccddee06be", "112233445566778899aabbccddee06be") + sstore("112233445566778899aabbccddee06bf", "112233445566778899aabbccddee06bf") + sstore("112233445566778899aabbccddee06c0", "112233445566778899aabbccddee06c0") + sstore("112233445566778899aabbccddee06c1", "112233445566778899aabbccddee06c1") + sstore("112233445566778899aabbccddee06c2", "112233445566778899aabbccddee06c2") + sstore("112233445566778899aabbccddee06c3", "112233445566778899aabbccddee06c3") + sstore("112233445566778899aabbccddee06c4", "112233445566778899aabbccddee06c4") + sstore("112233445566778899aabbccddee06c5", "112233445566778899aabbccddee06c5") + sstore("112233445566778899aabbccddee06c6", "112233445566778899aabbccddee06c6") + sstore("112233445566778899aabbccddee06c7", "112233445566778899aabbccddee06c7") + sstore("112233445566778899aabbccddee06c8", "112233445566778899aabbccddee06c8") + sstore("112233445566778899aabbccddee06c9", "112233445566778899aabbccddee06c9") + sstore("112233445566778899aabbccddee06ca", "112233445566778899aabbccddee06ca") + sstore("112233445566778899aabbccddee06cb", "112233445566778899aabbccddee06cb") + sstore("112233445566778899aabbccddee06cc", "112233445566778899aabbccddee06cc") + sstore("112233445566778899aabbccddee06cd", "112233445566778899aabbccddee06cd") + sstore("112233445566778899aabbccddee06ce", "112233445566778899aabbccddee06ce") + sstore("112233445566778899aabbccddee06cf", "112233445566778899aabbccddee06cf") + sstore("112233445566778899aabbccddee06d0", "112233445566778899aabbccddee06d0") + sstore("112233445566778899aabbccddee06d1", "112233445566778899aabbccddee06d1") + sstore("112233445566778899aabbccddee06d2", "112233445566778899aabbccddee06d2") + sstore("112233445566778899aabbccddee06d3", "112233445566778899aabbccddee06d3") + sstore("112233445566778899aabbccddee06d4", "112233445566778899aabbccddee06d4") + sstore("112233445566778899aabbccddee06d5", "112233445566778899aabbccddee06d5") + sstore("112233445566778899aabbccddee06d6", "112233445566778899aabbccddee06d6") + sstore("112233445566778899aabbccddee06d7", "112233445566778899aabbccddee06d7") + sstore("112233445566778899aabbccddee06d8", "112233445566778899aabbccddee06d8") + sstore("112233445566778899aabbccddee06d9", "112233445566778899aabbccddee06d9") + sstore("112233445566778899aabbccddee06da", "112233445566778899aabbccddee06da") + sstore("112233445566778899aabbccddee06db", "112233445566778899aabbccddee06db") + sstore("112233445566778899aabbccddee06dc", "112233445566778899aabbccddee06dc") + sstore("112233445566778899aabbccddee06dd", "112233445566778899aabbccddee06dd") + sstore("112233445566778899aabbccddee06de", "112233445566778899aabbccddee06de") + sstore("112233445566778899aabbccddee06df", "112233445566778899aabbccddee06df") + sstore("112233445566778899aabbccddee06e0", "112233445566778899aabbccddee06e0") + sstore("112233445566778899aabbccddee06e1", "112233445566778899aabbccddee06e1") + sstore("112233445566778899aabbccddee06e2", "112233445566778899aabbccddee06e2") + sstore("112233445566778899aabbccddee06e3", "112233445566778899aabbccddee06e3") + sstore("112233445566778899aabbccddee06e4", "112233445566778899aabbccddee06e4") + sstore("112233445566778899aabbccddee06e5", "112233445566778899aabbccddee06e5") + sstore("112233445566778899aabbccddee06e6", "112233445566778899aabbccddee06e6") + sstore("112233445566778899aabbccddee06e7", "112233445566778899aabbccddee06e7") + sstore("112233445566778899aabbccddee06e8", "112233445566778899aabbccddee06e8") + sstore("112233445566778899aabbccddee06e9", "112233445566778899aabbccddee06e9") + sstore("112233445566778899aabbccddee06ea", "112233445566778899aabbccddee06ea") + sstore("112233445566778899aabbccddee06eb", "112233445566778899aabbccddee06eb") + sstore("112233445566778899aabbccddee06ec", "112233445566778899aabbccddee06ec") + sstore("112233445566778899aabbccddee06ed", "112233445566778899aabbccddee06ed") + sstore("112233445566778899aabbccddee06ee", "112233445566778899aabbccddee06ee") + sstore("112233445566778899aabbccddee06ef", "112233445566778899aabbccddee06ef") + sstore("112233445566778899aabbccddee06f0", "112233445566778899aabbccddee06f0") + sstore("112233445566778899aabbccddee06f1", "112233445566778899aabbccddee06f1") + sstore("112233445566778899aabbccddee06f2", "112233445566778899aabbccddee06f2") + sstore("112233445566778899aabbccddee06f3", "112233445566778899aabbccddee06f3") + sstore("112233445566778899aabbccddee06f4", "112233445566778899aabbccddee06f4") + sstore("112233445566778899aabbccddee06f5", "112233445566778899aabbccddee06f5") + sstore("112233445566778899aabbccddee06f6", "112233445566778899aabbccddee06f6") + sstore("112233445566778899aabbccddee06f7", "112233445566778899aabbccddee06f7") + sstore("112233445566778899aabbccddee06f8", "112233445566778899aabbccddee06f8") + sstore("112233445566778899aabbccddee06f9", "112233445566778899aabbccddee06f9") + sstore("112233445566778899aabbccddee06fa", "112233445566778899aabbccddee06fa") + sstore("112233445566778899aabbccddee06fb", "112233445566778899aabbccddee06fb") + sstore("112233445566778899aabbccddee06fc", "112233445566778899aabbccddee06fc") + sstore("112233445566778899aabbccddee06fd", "112233445566778899aabbccddee06fd") + sstore("112233445566778899aabbccddee06fe", "112233445566778899aabbccddee06fe") + sstore("112233445566778899aabbccddee06ff", "112233445566778899aabbccddee06ff") + sstore("112233445566778899aabbccddee0700", "112233445566778899aabbccddee0700") + sstore("112233445566778899aabbccddee0701", "112233445566778899aabbccddee0701") + sstore("112233445566778899aabbccddee0702", "112233445566778899aabbccddee0702") + sstore("112233445566778899aabbccddee0703", "112233445566778899aabbccddee0703") + sstore("112233445566778899aabbccddee0704", "112233445566778899aabbccddee0704") + sstore("112233445566778899aabbccddee0705", "112233445566778899aabbccddee0705") + sstore("112233445566778899aabbccddee0706", "112233445566778899aabbccddee0706") + sstore("112233445566778899aabbccddee0707", "112233445566778899aabbccddee0707") + sstore("112233445566778899aabbccddee0708", "112233445566778899aabbccddee0708") + sstore("112233445566778899aabbccddee0709", "112233445566778899aabbccddee0709") + sstore("112233445566778899aabbccddee070a", "112233445566778899aabbccddee070a") + sstore("112233445566778899aabbccddee070b", "112233445566778899aabbccddee070b") + sstore("112233445566778899aabbccddee070c", "112233445566778899aabbccddee070c") + sstore("112233445566778899aabbccddee070d", "112233445566778899aabbccddee070d") + sstore("112233445566778899aabbccddee070e", "112233445566778899aabbccddee070e") + sstore("112233445566778899aabbccddee070f", "112233445566778899aabbccddee070f") + sstore("112233445566778899aabbccddee0710", "112233445566778899aabbccddee0710") + sstore("112233445566778899aabbccddee0711", "112233445566778899aabbccddee0711") + sstore("112233445566778899aabbccddee0712", "112233445566778899aabbccddee0712") + sstore("112233445566778899aabbccddee0713", "112233445566778899aabbccddee0713") + sstore("112233445566778899aabbccddee0714", "112233445566778899aabbccddee0714") + sstore("112233445566778899aabbccddee0715", "112233445566778899aabbccddee0715") + sstore("112233445566778899aabbccddee0716", "112233445566778899aabbccddee0716") + sstore("112233445566778899aabbccddee0717", "112233445566778899aabbccddee0717") + sstore("112233445566778899aabbccddee0718", "112233445566778899aabbccddee0718") + sstore("112233445566778899aabbccddee0719", "112233445566778899aabbccddee0719") + sstore("112233445566778899aabbccddee071a", "112233445566778899aabbccddee071a") + sstore("112233445566778899aabbccddee071b", "112233445566778899aabbccddee071b") + sstore("112233445566778899aabbccddee071c", "112233445566778899aabbccddee071c") + sstore("112233445566778899aabbccddee071d", "112233445566778899aabbccddee071d") + sstore("112233445566778899aabbccddee071e", "112233445566778899aabbccddee071e") + sstore("112233445566778899aabbccddee071f", "112233445566778899aabbccddee071f") + sstore("112233445566778899aabbccddee0720", "112233445566778899aabbccddee0720") + sstore("112233445566778899aabbccddee0721", "112233445566778899aabbccddee0721") + sstore("112233445566778899aabbccddee0722", "112233445566778899aabbccddee0722") + sstore("112233445566778899aabbccddee0723", "112233445566778899aabbccddee0723") + sstore("112233445566778899aabbccddee0724", "112233445566778899aabbccddee0724") + sstore("112233445566778899aabbccddee0725", "112233445566778899aabbccddee0725") + sstore("112233445566778899aabbccddee0726", "112233445566778899aabbccddee0726") + sstore("112233445566778899aabbccddee0727", "112233445566778899aabbccddee0727") + sstore("112233445566778899aabbccddee0728", "112233445566778899aabbccddee0728") + sstore("112233445566778899aabbccddee0729", "112233445566778899aabbccddee0729") + sstore("112233445566778899aabbccddee072a", "112233445566778899aabbccddee072a") + sstore("112233445566778899aabbccddee072b", "112233445566778899aabbccddee072b") + sstore("112233445566778899aabbccddee072c", "112233445566778899aabbccddee072c") + sstore("112233445566778899aabbccddee072d", "112233445566778899aabbccddee072d") + sstore("112233445566778899aabbccddee072e", "112233445566778899aabbccddee072e") + sstore("112233445566778899aabbccddee072f", "112233445566778899aabbccddee072f") + sstore("112233445566778899aabbccddee0730", "112233445566778899aabbccddee0730") + sstore("112233445566778899aabbccddee0731", "112233445566778899aabbccddee0731") + sstore("112233445566778899aabbccddee0732", "112233445566778899aabbccddee0732") + sstore("112233445566778899aabbccddee0733", "112233445566778899aabbccddee0733") + sstore("112233445566778899aabbccddee0734", "112233445566778899aabbccddee0734") + sstore("112233445566778899aabbccddee0735", "112233445566778899aabbccddee0735") + sstore("112233445566778899aabbccddee0736", "112233445566778899aabbccddee0736") + sstore("112233445566778899aabbccddee0737", "112233445566778899aabbccddee0737") + sstore("112233445566778899aabbccddee0738", "112233445566778899aabbccddee0738") + sstore("112233445566778899aabbccddee0739", "112233445566778899aabbccddee0739") + sstore("112233445566778899aabbccddee073a", "112233445566778899aabbccddee073a") + sstore("112233445566778899aabbccddee073b", "112233445566778899aabbccddee073b") + sstore("112233445566778899aabbccddee073c", "112233445566778899aabbccddee073c") + sstore("112233445566778899aabbccddee073d", "112233445566778899aabbccddee073d") + sstore("112233445566778899aabbccddee073e", "112233445566778899aabbccddee073e") + sstore("112233445566778899aabbccddee073f", "112233445566778899aabbccddee073f") + sstore("112233445566778899aabbccddee0740", "112233445566778899aabbccddee0740") + sstore("112233445566778899aabbccddee0741", "112233445566778899aabbccddee0741") + sstore("112233445566778899aabbccddee0742", "112233445566778899aabbccddee0742") + sstore("112233445566778899aabbccddee0743", "112233445566778899aabbccddee0743") + sstore("112233445566778899aabbccddee0744", "112233445566778899aabbccddee0744") + sstore("112233445566778899aabbccddee0745", "112233445566778899aabbccddee0745") + sstore("112233445566778899aabbccddee0746", "112233445566778899aabbccddee0746") + sstore("112233445566778899aabbccddee0747", "112233445566778899aabbccddee0747") + sstore("112233445566778899aabbccddee0748", "112233445566778899aabbccddee0748") + sstore("112233445566778899aabbccddee0749", "112233445566778899aabbccddee0749") + sstore("112233445566778899aabbccddee074a", "112233445566778899aabbccddee074a") + sstore("112233445566778899aabbccddee074b", "112233445566778899aabbccddee074b") + sstore("112233445566778899aabbccddee074c", "112233445566778899aabbccddee074c") + sstore("112233445566778899aabbccddee074d", "112233445566778899aabbccddee074d") + sstore("112233445566778899aabbccddee074e", "112233445566778899aabbccddee074e") + sstore("112233445566778899aabbccddee074f", "112233445566778899aabbccddee074f") + sstore("112233445566778899aabbccddee0750", "112233445566778899aabbccddee0750") + return(0, 32) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// CodeGenerationError 2202: Code section too large for EOF. diff --git a/test/libyul/yulSyntaxTests/eof/too_many_functions_arguments_or_returns.yul b/test/libyul/yulSyntaxTests/eof/too_many_functions_arguments_or_returns.yul new file mode 100644 index 000000000000..623bf6ded6fb --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/too_many_functions_arguments_or_returns.yul @@ -0,0 +1,26 @@ +object "a" { + code { + function too_many_arguments( + i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, + i31, i32, i33, i34, i35, i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47, i48, i49, i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i60, + i61, i62, i63, i64, i65, i66, i67, i68, i69, i70, i71, i72, i73, i74, i75, i76, i77, i78, i79, i80, i81, i82, i83, i84, i85, i86, i87, i88, i89, i90, + i91, i92, i93, i94, i95, i96, i97, i98, i99, i100, i101, i102, i103, i104, i105, i106, i107, i108, i109, i110, i111, i112, i113, i114, i115, i116, i117, i118, i119, i120, + i121, i122, i123, i124, i125, i126, i127, i128 + ) + {} + + function too_many_returns()-> + i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, + i31, i32, i33, i34, i35, i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47, i48, i49, i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i60, + i61, i62, i63, i64, i65, i66, i67, i68, i69, i70, i71, i72, i73, i74, i75, i76, i77, i78, i79, i80, i81, i82, i83, i84, i85, i86, i87, i88, i89, i90, + i91, i92, i93, i94, i95, i96, i97, i98, i99, i100, i101, i102, i103, i104, i105, i106, i107, i108, i109, i110, i111, i112, i113, i114, i115, i116, i117, i118, i119, i120, + i121, i122, i123, i124, i125, i126, i127, i128 + {} + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 8534: (32-800): Too many function parameters. At most 127 parameters allowed for EOF +// TypeError 2101: (810-1569): Too many function return variables. At most 127 return variables allowed for EOF diff --git a/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul b/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul new file mode 100644 index 000000000000..314d4fa3df72 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul @@ -0,0 +1,269 @@ +object "a" { + code { + mstore(0, eofcreate("s0000", 0, 0, 0, 0)) + return(0, 32) + } + + object "s0000" {code{}} + object "s0001" {code{}} + object "s0002" {code{}} + object "s0003" {code{}} + object "s0004" {code{}} + object "s0005" {code{}} + object "s0006" {code{}} + object "s0007" {code{}} + object "s0008" {code{}} + object "s0009" {code{}} + object "s0010" {code{}} + object "s0011" {code{}} + object "s0012" {code{}} + object "s0013" {code{}} + object "s0014" {code{}} + object "s0015" {code{}} + object "s0016" {code{}} + object "s0017" {code{}} + object "s0018" {code{}} + object "s0019" {code{}} + object "s0020" {code{}} + object "s0021" {code{}} + object "s0022" {code{}} + object "s0023" {code{}} + object "s0024" {code{}} + object "s0025" {code{}} + object "s0026" {code{}} + object "s0027" {code{}} + object "s0028" {code{}} + object "s0029" {code{}} + object "s0030" {code{}} + object "s0031" {code{}} + object "s0032" {code{}} + object "s0033" {code{}} + object "s0034" {code{}} + object "s0035" {code{}} + object "s0036" {code{}} + object "s0037" {code{}} + object "s0038" {code{}} + object "s0039" {code{}} + object "s0040" {code{}} + object "s0041" {code{}} + object "s0042" {code{}} + object "s0043" {code{}} + object "s0044" {code{}} + object "s0045" {code{}} + object "s0046" {code{}} + object "s0047" {code{}} + object "s0048" {code{}} + object "s0049" {code{}} + object "s0050" {code{}} + object "s0051" {code{}} + object "s0052" {code{}} + object "s0053" {code{}} + object "s0054" {code{}} + object "s0055" {code{}} + object "s0056" {code{}} + object "s0057" {code{}} + object "s0058" {code{}} + object "s0059" {code{}} + object "s0060" {code{}} + object "s0061" {code{}} + object "s0062" {code{}} + object "s0063" {code{}} + object "s0064" {code{}} + object "s0065" {code{}} + object "s0066" {code{}} + object "s0067" {code{}} + object "s0068" {code{}} + object "s0069" {code{}} + object "s0070" {code{}} + object "s0071" {code{}} + object "s0072" {code{}} + object "s0073" {code{}} + object "s0074" {code{}} + object "s0075" {code{}} + object "s0076" {code{}} + object "s0077" {code{}} + object "s0078" {code{}} + object "s0079" {code{}} + object "s0080" {code{}} + object "s0081" {code{}} + object "s0082" {code{}} + object "s0083" {code{}} + object "s0084" {code{}} + object "s0085" {code{}} + object "s0086" {code{}} + object "s0087" {code{}} + object "s0088" {code{}} + object "s0089" {code{}} + object "s0090" {code{}} + object "s0091" {code{}} + object "s0092" {code{}} + object "s0093" {code{}} + object "s0094" {code{}} + object "s0095" {code{}} + object "s0096" {code{}} + object "s0097" {code{}} + object "s0098" {code{}} + object "s0099" {code{}} + object "s0100" {code{}} + object "s0101" {code{}} + object "s0102" {code{}} + object "s0103" {code{}} + object "s0104" {code{}} + object "s0105" {code{}} + object "s0106" {code{}} + object "s0107" {code{}} + object "s0108" {code{}} + object "s0109" {code{}} + object "s0110" {code{}} + object "s0111" {code{}} + object "s0112" {code{}} + object "s0113" {code{}} + object "s0114" {code{}} + object "s0115" {code{}} + object "s0116" {code{}} + object "s0117" {code{}} + object "s0118" {code{}} + object "s0119" {code{}} + object "s0120" {code{}} + object "s0121" {code{}} + object "s0122" {code{}} + object "s0123" {code{}} + object "s0124" {code{}} + object "s0125" {code{}} + object "s0126" {code{}} + object "s0127" {code{}} + object "s0128" {code{}} + object "s0129" {code{}} + object "s0130" {code{}} + object "s0131" {code{}} + object "s0132" {code{}} + object "s0133" {code{}} + object "s0134" {code{}} + object "s0135" {code{}} + object "s0136" {code{}} + object "s0137" {code{}} + object "s0138" {code{}} + object "s0139" {code{}} + object "s0140" {code{}} + object "s0141" {code{}} + object "s0142" {code{}} + object "s0143" {code{}} + object "s0144" {code{}} + object "s0145" {code{}} + object "s0146" {code{}} + object "s0147" {code{}} + object "s0148" {code{}} + object "s0149" {code{}} + object "s0150" {code{}} + object "s0151" {code{}} + object "s0152" {code{}} + object "s0153" {code{}} + object "s0154" {code{}} + object "s0155" {code{}} + object "s0156" {code{}} + object "s0157" {code{}} + object "s0158" {code{}} + object "s0159" {code{}} + object "s0160" {code{}} + object "s0161" {code{}} + object "s0162" {code{}} + object "s0163" {code{}} + object "s0164" {code{}} + object "s0165" {code{}} + object "s0166" {code{}} + object "s0167" {code{}} + object "s0168" {code{}} + object "s0169" {code{}} + object "s0170" {code{}} + object "s0171" {code{}} + object "s0172" {code{}} + object "s0173" {code{}} + object "s0174" {code{}} + object "s0175" {code{}} + object "s0176" {code{}} + object "s0177" {code{}} + object "s0178" {code{}} + object "s0179" {code{}} + object "s0180" {code{}} + object "s0181" {code{}} + object "s0182" {code{}} + object "s0183" {code{}} + object "s0184" {code{}} + object "s0185" {code{}} + object "s0186" {code{}} + object "s0187" {code{}} + object "s0188" {code{}} + object "s0189" {code{}} + object "s0190" {code{}} + object "s0191" {code{}} + object "s0192" {code{}} + object "s0193" {code{}} + object "s0194" {code{}} + object "s0195" {code{}} + object "s0196" {code{}} + object "s0197" {code{}} + object "s0198" {code{}} + object "s0199" {code{}} + object "s0200" {code{}} + object "s0201" {code{}} + object "s0202" {code{}} + object "s0203" {code{}} + object "s0204" {code{}} + object "s0205" {code{}} + object "s0206" {code{}} + object "s0207" {code{}} + object "s0208" {code{}} + object "s0209" {code{}} + object "s0210" {code{}} + object "s0211" {code{}} + object "s0212" {code{}} + object "s0213" {code{}} + object "s0214" {code{}} + object "s0215" {code{}} + object "s0216" {code{}} + object "s0217" {code{}} + object "s0218" {code{}} + object "s0219" {code{}} + object "s0220" {code{}} + object "s0221" {code{}} + object "s0222" {code{}} + object "s0223" {code{}} + object "s0224" {code{}} + object "s0225" {code{}} + object "s0226" {code{}} + object "s0227" {code{}} + object "s0228" {code{}} + object "s0229" {code{}} + object "s0230" {code{}} + object "s0231" {code{}} + object "s0232" {code{}} + object "s0233" {code{}} + object "s0234" {code{}} + object "s0235" {code{}} + object "s0236" {code{}} + object "s0237" {code{}} + object "s0238" {code{}} + object "s0239" {code{}} + object "s0240" {code{}} + object "s0241" {code{}} + object "s0242" {code{}} + object "s0243" {code{}} + object "s0244" {code{}} + object "s0245" {code{}} + object "s0246" {code{}} + object "s0247" {code{}} + object "s0248" {code{}} + object "s0249" {code{}} + object "s0250" {code{}} + object "s0251" {code{}} + object "s0252" {code{}} + object "s0253" {code{}} + object "s0254" {code{}} + object "s0255" {code{}} + object "s0256" {code{}} +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// SyntaxError 1305: (22-101): Too many subobjects in "a". At most 256 subobjects allowed when compiling to EOF diff --git a/test/libyul/yulSyntaxTests/hex_switch_case.yul b/test/libyul/yulSyntaxTests/hex_switch_case.yul index e0d00539a4a8..ec1e3edde9a0 100644 --- a/test/libyul/yulSyntaxTests/hex_switch_case.yul +++ b/test/libyul/yulSyntaxTests/hex_switch_case.yul @@ -1,5 +1,5 @@ { - switch codesize() + switch calldataload(0) case hex"00" {} case hex"1122" {} } diff --git a/test/libyul/yulSyntaxTests/hex_switch_case_long.yul b/test/libyul/yulSyntaxTests/hex_switch_case_long.yul index abdbc6ec15f6..93035730b1d1 100644 --- a/test/libyul/yulSyntaxTests/hex_switch_case_long.yul +++ b/test/libyul/yulSyntaxTests/hex_switch_case_long.yul @@ -1,7 +1,7 @@ { - switch codesize() + switch calldataload(0) case hex"00" {} case hex"112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900" {} } // ---- -// TypeError 3069: (53-178): String literal too long (60 > 32) +// TypeError 3069: (58-183): String literal too long (60 > 32) diff --git a/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul b/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul new file mode 100644 index 000000000000..2e4252af412d --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul @@ -0,0 +1,13 @@ +{ + let x: memoryguard + x := true: linkersymbol + + function f(y: linkersymbol) {} +} +// ---- +// ParserError 5568: (13-24): Cannot use builtin function name "memoryguard" as identifier name. +// ParserError 5473: (10-24): Types are not supported in untyped Yul. +// ParserError 5568: (40-52): Cannot use builtin function name "linkersymbol" as identifier name. +// ParserError 5473: (34-52): Types are not supported in untyped Yul. +// ParserError 5568: (72-84): Cannot use builtin function name "linkersymbol" as identifier name. +// ParserError 5473: (69-84): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul new file mode 100644 index 000000000000..6f582442322b --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul @@ -0,0 +1,11 @@ +{ + { function memoryguard() {} } + { function f(memoryguard) {} } + { function f() -> memoryguard {} } + { let memoryguard } +} +// ---- +// ParserError 5568: (17-28): Cannot use builtin function name "memoryguard" as identifier name. +// ParserError 5568: (53-64): Cannot use builtin function name "memoryguard" as identifier name. +// ParserError 5568: (93-104): Cannot use builtin function name "memoryguard" as identifier name. +// ParserError 5568: (120-131): Cannot use builtin function name "memoryguard" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul new file mode 100644 index 000000000000..f146f06aeb76 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul @@ -0,0 +1,11 @@ +{ + // NOTE: All EVM instruction names are reserved identifiers in Yul. + // NOTE: We do provide builtins corresponding to these instructions. + function add(mstore) -> sstore {} + let coinbase +} +// ---- +// ParserError 5568: (160-163): Cannot use builtin function name "add" as identifier name. +// ParserError 5568: (164-170): Cannot use builtin function name "mstore" as identifier name. +// ParserError 5568: (175-181): Cannot use builtin function name "sstore" as identifier name. +// ParserError 5568: (193-201): Cannot use builtin function name "coinbase" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_non_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_non_builtin.yul new file mode 100644 index 000000000000..bf7ad840cd05 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_non_builtin.yul @@ -0,0 +1,11 @@ +{ + // NOTE: All EVM instruction names are reserved identifiers in Yul. + // NOTE: We don't provide builtins corresponding to these instructions. + function dup1(dup2) -> dup3 {} + let dup4 +} +// ---- +// DeclarationError 5017: (154-184): The identifier "dup1" is reserved and can not be used. +// DeclarationError 5017: (168-172): The identifier "dup2" is reserved and can not be used. +// DeclarationError 5017: (177-181): The identifier "dup3" is reserved and can not be used. +// DeclarationError 5017: (193-197): The identifier "dup4" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul new file mode 100644 index 000000000000..66698c63377b --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul @@ -0,0 +1,13 @@ +{ + // NOTE: These are builtins but only in pure Yul, not inline assembly. + // NOTE: Names of these builtins are also reserved identifiers. + function loadimmutable(setimmutable) -> datasize {} + let dataoffset +} +// ==== +// bytecodeFormat: legacy +// ---- +// ParserError 5568: (158-171): Cannot use builtin function name "loadimmutable" as identifier name. +// ParserError 5568: (172-184): Cannot use builtin function name "setimmutable" as identifier name. +// ParserError 5568: (189-197): Cannot use builtin function name "datasize" as identifier name. +// ParserError 5568: (209-219): Cannot use builtin function name "dataoffset" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin_eof.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin_eof.yul new file mode 100644 index 000000000000..0466cc9b62d8 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin_eof.yul @@ -0,0 +1,13 @@ +{ + // NOTE: These are builtins but only in pure Yul, not inline assembly. + // NOTE: Names of these builtins are also reserved identifiers. + function auxdataloadn(eofcreate) -> returncontract {} + let eofcreate +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (158-170): Cannot use builtin function name "auxdataloadn" as identifier name. +// ParserError 5568: (171-180): Cannot use builtin function name "eofcreate" as identifier name. +// ParserError 5568: (185-199): Cannot use builtin function name "returncontract" as identifier name. +// ParserError 5568: (211-220): Cannot use builtin function name "eofcreate" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul b/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul index d5b3847b1743..6a5587c972ae 100644 --- a/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul +++ b/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul @@ -1,5 +1,7 @@ { pop(pc()) } +// ==== +// bytecodeFormat: legacy // ---- // SyntaxError 2450: (10-12): PC instruction is a low-level EVM feature. Because of that PC is disallowed in strict assembly. diff --git a/test/libyul/yulSyntaxTests/invalid/reserved_identifier_as_type.yul b/test/libyul/yulSyntaxTests/invalid/reserved_identifier_as_type.yul new file mode 100644 index 000000000000..df46d16b5a69 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/reserved_identifier_as_type.yul @@ -0,0 +1,10 @@ +{ + let x: jump + x := true: dup12 + + function f(y: jumpi) {} +} +// ---- +// ParserError 5473: (10-17): Types are not supported in untyped Yul. +// ParserError 5473: (27-38): Types are not supported in untyped Yul. +// ParserError 5473: (55-63): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.sol b/test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.yul similarity index 100% rename from test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.sol rename to test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.yul diff --git a/test/libyul/yulSyntaxTests/loadimmutable.yul b/test/libyul/yulSyntaxTests/loadimmutable.yul index 6aea058b5d57..7c40a65034d5 100644 --- a/test/libyul/yulSyntaxTests/loadimmutable.yul +++ b/test/libyul/yulSyntaxTests/loadimmutable.yul @@ -3,4 +3,5 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul b/test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul index 2aadd2f208f0..ea1d7186f29f 100644 --- a/test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul +++ b/test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul @@ -5,6 +5,7 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // TypeError 5859: (24-25): Function expects string literal. // TypeError 5859: (50-54): Function expects string literal. diff --git a/test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul b/test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul index 8711d0b17757..8156bd4fba49 100644 --- a/test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul +++ b/test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul @@ -3,5 +3,6 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-28): Cannot use builtin function name "loadimmutable" as identifier name. diff --git a/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul b/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul new file mode 100644 index 000000000000..42ca7eb2f8d4 --- /dev/null +++ b/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul @@ -0,0 +1,13 @@ +object "C" { + code {} + + object "C_deployed" { + code { + sstore(0, loadimmutable("1")) + } + } +} +// ==== +// bytecodeFormat: legacy +// ---- +// CodeGenerationError 1284: Some immutables were read from but never assigned, possibly because of optimization. diff --git a/test/libyul/yulSyntaxTests/mcopy_as_identifier.yul b/test/libyul/yulSyntaxTests/mcopy_as_identifier.yul index e48c27d06d81..be00e0a3584f 100644 --- a/test/libyul/yulSyntaxTests/mcopy_as_identifier.yul +++ b/test/libyul/yulSyntaxTests/mcopy_as_identifier.yul @@ -12,3 +12,4 @@ // EVMVersion: >=cancun // ---- // ParserError 5568: (20-25): Cannot use builtin function name "mcopy" as identifier name. +// ParserError 5568: (61-66): Cannot use builtin function name "mcopy" as identifier name. diff --git a/test/libyul/yulSyntaxTests/metadata_access.yul b/test/libyul/yulSyntaxTests/metadata_access.yul index 63aeb4760296..52bf786cda73 100644 --- a/test/libyul/yulSyntaxTests/metadata_access.yul +++ b/test/libyul/yulSyntaxTests/metadata_access.yul @@ -21,6 +21,8 @@ object "A" { data ".metadata" "Hello, World!" data ".other" "Hello, World2!" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (41-49): Unknown data object ".other". // TypeError 3517: (69-77): Unknown data object ".other". diff --git a/test/libyul/yulSyntaxTests/metadata_access_2.yul b/test/libyul/yulSyntaxTests/metadata_access_2.yul index a4b013e854ff..204409d3e97f 100644 --- a/test/libyul/yulSyntaxTests/metadata_access_2.yul +++ b/test/libyul/yulSyntaxTests/metadata_access_2.yul @@ -9,5 +9,7 @@ object "A" { data "1" "XYZ" data ".mightbereservedinthefuture" "TRS" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (90-119): Unknown data object ".mightbereservedinthefuture". diff --git a/test/libyul/yulSyntaxTests/metadata_access_subobject.yul b/test/libyul/yulSyntaxTests/metadata_access_subobject.yul index 216b56ac649c..c52ab9e1a66c 100644 --- a/test/libyul/yulSyntaxTests/metadata_access_subobject.yul +++ b/test/libyul/yulSyntaxTests/metadata_access_subobject.yul @@ -8,5 +8,7 @@ object "A" { data "x" "ABC" } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (41-54): Unknown data object ".metadata.x". diff --git a/test/libyul/yulSyntaxTests/objects/data.yul b/test/libyul/yulSyntaxTests/objects/data.yul index 47d7b59c7f0a..744a88c64578 100644 --- a/test/libyul/yulSyntaxTests/objects/data.yul +++ b/test/libyul/yulSyntaxTests/objects/data.yul @@ -6,4 +6,6 @@ object "A" { data "2" hex"0011" data "3" "hello world this is longer than 32 bytes and should still work" } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/objects/data_access.yul b/test/libyul/yulSyntaxTests/objects/data_access.yul index e9455fafab33..681cb5028056 100644 --- a/test/libyul/yulSyntaxTests/objects/data_access.yul +++ b/test/libyul/yulSyntaxTests/objects/data_access.yul @@ -6,4 +6,6 @@ object "A" { data "B" hex"00" } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/objects/datacopy.yul b/test/libyul/yulSyntaxTests/objects/datacopy.yul index 6e36025fcbd1..1afb88e2739b 100644 --- a/test/libyul/yulSyntaxTests/objects/datacopy.yul +++ b/test/libyul/yulSyntaxTests/objects/datacopy.yul @@ -6,4 +6,6 @@ let s := "" datacopy(x, "11", s) } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/objects/dataoffset_nonliteral.yul b/test/libyul/yulSyntaxTests/objects/dataoffset_nonliteral.yul index d53e26281eae..ba80b462efd0 100644 --- a/test/libyul/yulSyntaxTests/objects/dataoffset_nonliteral.yul +++ b/test/libyul/yulSyntaxTests/objects/dataoffset_nonliteral.yul @@ -6,5 +6,7 @@ object "A" { data "B" hex"00" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9114: (47-57): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/objects/dataoffset_nonstring.yul b/test/libyul/yulSyntaxTests/objects/dataoffset_nonstring.yul index 93a981d924e0..1ac18c19c5bb 100644 --- a/test/libyul/yulSyntaxTests/objects/dataoffset_nonstring.yul +++ b/test/libyul/yulSyntaxTests/objects/dataoffset_nonstring.yul @@ -3,5 +3,7 @@ object "A" { pop(dataoffset(0)) } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 5859: (41-42): Function expects string literal. diff --git a/test/libyul/yulSyntaxTests/objects/dataoffset_notfound.yul b/test/libyul/yulSyntaxTests/objects/dataoffset_notfound.yul index 14df40201418..3ee03d66e63d 100644 --- a/test/libyul/yulSyntaxTests/objects/dataoffset_notfound.yul +++ b/test/libyul/yulSyntaxTests/objects/dataoffset_notfound.yul @@ -4,5 +4,7 @@ object "A" { } data "B" "" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (41-44): Unknown data object "C". diff --git a/test/libyul/yulSyntaxTests/objects/datasize_nonliteral.yul b/test/libyul/yulSyntaxTests/objects/datasize_nonliteral.yul index 837408b9a00b..a5179f3e45e2 100644 --- a/test/libyul/yulSyntaxTests/objects/datasize_nonliteral.yul +++ b/test/libyul/yulSyntaxTests/objects/datasize_nonliteral.yul @@ -6,5 +6,7 @@ object "A" { data "B" hex"00" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9114: (47-55): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/objects/datasize_nonstring.yul b/test/libyul/yulSyntaxTests/objects/datasize_nonstring.yul index 19042a2df738..c8697d06b3dc 100644 --- a/test/libyul/yulSyntaxTests/objects/datasize_nonstring.yul +++ b/test/libyul/yulSyntaxTests/objects/datasize_nonstring.yul @@ -3,5 +3,7 @@ object "A" { pop(datasize(0)) } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 5859: (39-40): Function expects string literal. diff --git a/test/libyul/yulSyntaxTests/objects/datasize_notfound.yul b/test/libyul/yulSyntaxTests/objects/datasize_notfound.yul index 48a2c268e205..4fe607a0b8da 100644 --- a/test/libyul/yulSyntaxTests/objects/datasize_notfound.yul +++ b/test/libyul/yulSyntaxTests/objects/datasize_notfound.yul @@ -4,5 +4,7 @@ object "A" { } data "B" "" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (39-42): Unknown data object "C". diff --git a/test/libyul/yulSyntaxTests/objects/subobject_access.yul b/test/libyul/yulSyntaxTests/objects/subobject_access.yul index 59426a0aa631..11fd37d9c6f0 100644 --- a/test/libyul/yulSyntaxTests/objects/subobject_access.yul +++ b/test/libyul/yulSyntaxTests/objects/subobject_access.yul @@ -8,4 +8,6 @@ object "A" { code {} } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/opcode_for_function_args_1.yul b/test/libyul/yulSyntaxTests/opcode_for_function_args_1.yul index 00c357bb44aa..dfe4ed903274 100644 --- a/test/libyul/yulSyntaxTests/opcode_for_function_args_1.yul +++ b/test/libyul/yulSyntaxTests/opcode_for_function_args_1.yul @@ -1,5 +1,5 @@ { - function f(gas) {} + function f(mload) {} } // ---- -// ParserError 5568: (14-17): Cannot use builtin function name "gas" as identifier name. +// ParserError 5568: (14-19): Cannot use builtin function name "mload" as identifier name. diff --git a/test/libyul/yulSyntaxTests/opcode_for_function_args_2.yul b/test/libyul/yulSyntaxTests/opcode_for_function_args_2.yul index 989cfce9e007..9fdb7727787b 100644 --- a/test/libyul/yulSyntaxTests/opcode_for_function_args_2.yul +++ b/test/libyul/yulSyntaxTests/opcode_for_function_args_2.yul @@ -1,5 +1,5 @@ { - function f() -> gas {} + function f() -> mload {} } // ---- -// ParserError 5568: (19-22): Cannot use builtin function name "gas" as identifier name. +// ParserError 5568: (19-24): Cannot use builtin function name "mload" as identifier name. diff --git a/test/libyul/yulSyntaxTests/opcode_for_functions.yul b/test/libyul/yulSyntaxTests/opcode_for_functions.yul index 0efc7cbccedd..8dea8893d337 100644 --- a/test/libyul/yulSyntaxTests/opcode_for_functions.yul +++ b/test/libyul/yulSyntaxTests/opcode_for_functions.yul @@ -1,5 +1,5 @@ { - function gas() {} + function mload() {} } // ---- -// ParserError 5568: (12-15): Cannot use builtin function name "gas" as identifier name. +// ParserError 5568: (12-17): Cannot use builtin function name "mload" as identifier name. diff --git a/test/libyul/yulSyntaxTests/passing_builtin_with_literal_argument_into_literal_argument.yul b/test/libyul/yulSyntaxTests/passing_builtin_with_literal_argument_into_literal_argument.yul index 433d36683dfe..d1e6d50e9e80 100644 --- a/test/libyul/yulSyntaxTests/passing_builtin_with_literal_argument_into_literal_argument.yul +++ b/test/libyul/yulSyntaxTests/passing_builtin_with_literal_argument_into_literal_argument.yul @@ -3,5 +3,6 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // TypeError 9114: (6-18): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/selfdestruct.yul b/test/libyul/yulSyntaxTests/selfdestruct.yul index faecf92c3805..181e9806ddaa 100644 --- a/test/libyul/yulSyntaxTests/selfdestruct.yul +++ b/test/libyul/yulSyntaxTests/selfdestruct.yul @@ -1,5 +1,7 @@ { selfdestruct(0x02) } +// ==== +// bytecodeFormat: legacy // ---- // Warning 1699: (3-15): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. diff --git a/test/libyul/yulSyntaxTests/setimmutable.yul b/test/libyul/yulSyntaxTests/setimmutable.yul index e1d6a74919c9..88e38b1338a4 100644 --- a/test/libyul/yulSyntaxTests/setimmutable.yul +++ b/test/libyul/yulSyntaxTests/setimmutable.yul @@ -3,4 +3,5 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul b/test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul index 9e4bc8032c78..175ab15aa59e 100644 --- a/test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul +++ b/test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul @@ -5,6 +5,7 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // TypeError 5859: (22-23): Function expects string literal. // TypeError 5859: (89-93): Function expects string literal. diff --git a/test/libyul/yulSyntaxTests/setimmutable_shadowing.yul b/test/libyul/yulSyntaxTests/setimmutable_shadowing.yul index b76a5de9b729..fbcfeb15ff98 100644 --- a/test/libyul/yulSyntaxTests/setimmutable_shadowing.yul +++ b/test/libyul/yulSyntaxTests/setimmutable_shadowing.yul @@ -3,5 +3,6 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-27): Cannot use builtin function name "setimmutable" as identifier name. diff --git a/test/libyul/yulSyntaxTests/simple_functions.yul b/test/libyul/yulSyntaxTests/simple_functions.yul index 5b63885f2b5f..8d97e4ac0e39 100644 --- a/test/libyul/yulSyntaxTests/simple_functions.yul +++ b/test/libyul/yulSyntaxTests/simple_functions.yul @@ -2,7 +2,7 @@ function a() {} function f() { mstore(0, 1) } function g() { sstore(0, 1) } - function h() { let x := msize() } + function h() { let x := balance(0x0) } function i() { let z := mload(0) } } // ==== diff --git a/test/libyul/yulSyntaxTests/string_literal_switch_case.yul b/test/libyul/yulSyntaxTests/string_literal_switch_case.yul index 6f0d72229947..b69b56c662cd 100644 --- a/test/libyul/yulSyntaxTests/string_literal_switch_case.yul +++ b/test/libyul/yulSyntaxTests/string_literal_switch_case.yul @@ -1,5 +1,5 @@ { - switch codesize() + switch calldataload(0) case "1" {} case "2" {} } diff --git a/test/libyul/yulSyntaxTests/string_literal_too_long_immutable.yul b/test/libyul/yulSyntaxTests/string_literal_too_long_immutable.yul index 98707451e600..d81f69a082ee 100644 --- a/test/libyul/yulSyntaxTests/string_literal_too_long_immutable.yul +++ b/test/libyul/yulSyntaxTests/string_literal_too_long_immutable.yul @@ -7,4 +7,5 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- diff --git a/test/scripts/test_bytecodecompare_prepare_report.py b/test/scripts/test_bytecodecompare_prepare_report.py index 28a89ec315cb..e1987c60c17c 100644 --- a/test/scripts/test_bytecodecompare_prepare_report.py +++ b/test/scripts/test_bytecodecompare_prepare_report.py @@ -24,7 +24,7 @@ SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH = FIXTURE_DIR / 'smt_contract_with_mixed_newlines.sol' SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_CODE = load_fixture(SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH) -SYNTAX_SMOKE_TEST_SOL_PATH = LIBSOLIDITY_TEST_DIR / 'syntaxTests/smoke_test.sol' +SYNTAX_SMOKE_TEST_SOL_PATH = LIBSOLIDITY_TEST_DIR / 'syntaxTests/smoke/smoke_test.sol' SYNTAX_SMOKE_TEST_SOL_CODE = load_libsolidity_test_case(SYNTAX_SMOKE_TEST_SOL_PATH) LIBRARY_INHERITED2_SOL_JSON_OUTPUT = load_fixture('library_inherited2_sol_json_output.json') @@ -58,19 +58,19 @@ def test_format_report(self): contract_reports=[ ContractReport( contract_name='A', - file_name=Path('syntaxTests/smoke_test.sol'), + file_name=Path('syntaxTests/smoke/smoke_test.sol'), bytecode=None, metadata=None, ), ContractReport( contract_name='B', - file_name=Path('syntaxTests/smoke_test.sol'), + file_name=Path('syntaxTests/smoke/smoke_test.sol'), bytecode=None, metadata='{"language":"Solidity"}', ), ContractReport( contract_name='Lib', - file_name=Path('syntaxTests/smoke_test.sol'), + file_name=Path('syntaxTests/smoke/smoke_test.sol'), bytecode='60566050600b828282398051', metadata=None, ), diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 6d19df01b3f8..adfd24b02b26 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1412,6 +1412,291 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_ambiguous_import) BOOST_REQUIRE(!result.success); } +BOOST_AUTO_TEST_CASE(cli_ethdebug_no_ethdebug_in_help) +{ + OptionsReaderAndMessages result = runCLI({"solc", "--help"}); + BOOST_REQUIRE(result.stdoutContent.find("ethdebug") == std::string::npos); + // just in case + BOOST_REQUIRE(result.stderrContent.find("ethdebug") == std::string::npos); +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}); + static std::vector> tests{ + { + {"solc", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--via-ir", "--ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--via-ir", "--ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--via-ir", "--ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--via-ir", "--ethdebug-runtime", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--via-ir", "--ethdebug-runtime", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug-runtime", "--import-asm-json", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.json"}, + } + }; + for (auto const& test: tests) + { + OptionsReaderAndMessages result = runCLI(test, ""); + BOOST_REQUIRE(!result.success); + } +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_input_modes) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.json"}); + static std::vector> tests{ + { + {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--ethdebug", "--via-ir", "--import-asm-json", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--ethdebug", "--import-ast", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--ethdebug", "--via-ir", "--import-ast", tempDir.path().string() + "/input.json"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ir", "--import-ast", tempDir.path().string() + "/input.json"}, + } + }; + for (auto const& test: tests) + { + OptionsReaderAndMessages result = runCLI(test, ""); + BOOST_REQUIRE(!result.success); + } +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); + createFilesWithParentDirs({tempDir.path() / "input.yul"}, "{}"); + static std::vector> erroneousCLIFlagCombinations{ + { + {"solc", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "location", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "location", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "location", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "all", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "all", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "all", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + }; + static std::vector> supportedCLIFlagCombinations{ + { + {"solc", "--debug-info", "ethdebug", "--ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + { + "solc", + "--debug-info", + "ethdebug", + "--ethdebug-runtime", + "--via-ir", + tempDir.path().string() + "/input.sol" + }, + }, + { + {"solc", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + }, + { + {"solc", "--ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + }, + { + { + "solc", + "--debug-info", + "ethdebug", + "--ethdebug", + "--ethdebug-runtime", + "--via-ir", + tempDir.path().string() + "/input.sol" + }, + }, + }; + + for (auto const& test: erroneousCLIFlagCombinations) + { + OptionsReaderAndMessages result{runCLI(test, "")}; + BOOST_REQUIRE(!result.success); + } + for (auto const& test: supportedCLIFlagCombinations) + { + OptionsReaderAndMessages result{runCLI(test, "")}; + BOOST_REQUIRE(result.success); + } +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_ethdebug_output) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); + static std::vector> erroneousCLIFlagCombinations{ + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + }, + { + { + "solc", + "--ethdebug-runtime", + "--via-ir", + "--ir-optimized", + "--optimize", + tempDir.path().string() + "/input.sol" + }, + }, + { + {"solc", "--ethdebug", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + }, + }; + static std::vector> supportedCLIFlagCombinations{ + { + {"solc", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + }, + }; + + for (auto const& test: erroneousCLIFlagCombinations) + { + OptionsReaderAndMessages result{runCLI(test, "")}; + BOOST_REQUIRE(!result.success); + } + for (auto const& test: supportedCLIFlagCombinations) + { + OptionsReaderAndMessages result{runCLI(test, "")}; + BOOST_REQUIRE(result.success); + } +} + BOOST_AUTO_TEST_SUITE_END() } // namespace solidity::frontend::test diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 227b1b9213d8..85eeaebe31a8 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -628,6 +628,43 @@ BOOST_AUTO_TEST_CASE(invalid_optimizer_sequence_without_optimize) } } +BOOST_AUTO_TEST_CASE(ethdebug) +{ + CommandLineOptions commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ethdebug", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ethdebug-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + // debug-info "ethdebug" selected implicitly, + // if compiled with --ethdebug or --ethdebug-runtime and no debug-info was selected. + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug", "--ethdebug-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ir, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace solidity::frontend::test diff --git a/test/soltest.cpp b/test/soltest.cpp index 8e7a3ddcd4a9..9bc60d1181f8 100644 --- a/test/soltest.cpp +++ b/test/soltest.cpp @@ -230,9 +230,6 @@ test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) if (solidity::test::CommonOptions::get().disableSemanticTests) std::cout << std::endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << std::endl << std::endl; - if (!solidity::test::CommonOptions::get().enforceGasTest) - std::cout << std::endl << "WARNING :: Gas Cost Expectations are not being enforced" << std::endl << std::endl; - Batcher batcher(CommonOptions::get().selectedBatch, CommonOptions::get().batches); if (CommonOptions::get().batches > 1) std::cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << std::endl; diff --git a/test/tools/IsolTestOptions.cpp b/test/tools/IsolTestOptions.cpp index 0994b63a83ef..e0980c7646e6 100644 --- a/test/tools/IsolTestOptions.cpp +++ b/test/tools/IsolTestOptions.cpp @@ -92,7 +92,7 @@ void IsolTestOptions::validate() const CommonOptions::validate(); static std::string filterString{"[a-zA-Z0-9_/*]*"}; static std::regex filterExpression{filterString}; - assertThrow( + solRequire( regex_match(testFilter, filterExpression), ConfigException, "Invalid test unit filter - can only contain '" + filterString + ": " + testFilter diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 1caa5357e534..6a70c1cc8f77 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -39,19 +39,7 @@ using namespace solidity::frontend; using namespace solidity::langutil; using namespace solidity::util; -static std::vector s_evmVersions = { - EVMVersion::homestead(), - EVMVersion::tangerineWhistle(), - EVMVersion::spuriousDragon(), - EVMVersion::byzantium(), - EVMVersion::constantinople(), - EVMVersion::petersburg(), - EVMVersion::istanbul(), - EVMVersion::berlin(), - EVMVersion::london(), - EVMVersion::paris(), - EVMVersion::prague() -}; +static std::vector s_evmVersions = EVMVersion::allVersions(); void FuzzerUtil::testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet) { diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt index 9449eddbad55..da18968928ea 100644 --- a/test/tools/ossfuzz/CMakeLists.txt +++ b/test/tools/ossfuzz/CMakeLists.txt @@ -74,7 +74,16 @@ if (OSSFUZZ) # are auto-generated by the protobuf compiler because the compiler # does not generate warning-free C++ bindings with regard to # upstream Clang builds that are used by ossfuzz. - target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + set( + SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS + -Wno-sign-conversion + -Wno-suggest-destructor-override + -Wno-inconsistent-missing-destructor-override + -Wno-shorten-64-to-32 + -Wno-deprecated + ) + + target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable( yul_proto_diff_ossfuzz @@ -92,7 +101,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_diff_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(yul_proto_diff_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(yul_proto_diff_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable(yul_proto_diff_custom_mutate_ossfuzz yulProto_diff_ossfuzz.cpp @@ -110,7 +119,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_diff_custom_mutate_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(yul_proto_diff_custom_mutate_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(yul_proto_diff_custom_mutate_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable(stack_reuse_codegen_ossfuzz StackReuseCodegenFuzzer.cpp @@ -130,12 +139,7 @@ if (OSSFUZZ) set_target_properties(stack_reuse_codegen_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) target_compile_options(stack_reuse_codegen_ossfuzz PUBLIC ${COMPILE_OPTIONS} - -Wno-sign-conversion - -Wno-inconsistent-missing-destructor-override - -Wno-unused-parameter - -Wno-zero-length-array - -Wno-suggest-destructor-override - -Wno-shorten-64-to-32 + ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS} ) add_executable(abiv2_proto_ossfuzz @@ -156,7 +160,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(abiv2_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(abiv2_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(abiv2_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable(abiv2_isabelle_ossfuzz AbiV2IsabelleFuzzer.cpp @@ -178,7 +182,7 @@ if (OSSFUZZ) gmp.a ) set_target_properties(abiv2_isabelle_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(abiv2_isabelle_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(abiv2_isabelle_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable(sol_proto_ossfuzz solProtoFuzzer.cpp @@ -198,7 +202,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(sol_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(sol_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(sol_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) else() add_library(solc_ossfuzz solc_ossfuzz.cpp diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index 6f603e335d46..71a4ff54a9f4 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -52,11 +52,10 @@ static evmc::VM evmone = evmc::VM{evmc_create_evmone()}; namespace { /// @returns true if there are recursive functions, false otherwise. -bool recursiveFunctionExists(Dialect const& _dialect, yul::Object& _object) +bool recursiveFunctionExists(Dialect const& /*_dialect*/, yul::Object& _object) { auto recursiveFunctions = CallGraphGenerator::callGraph(_object.code()->root()).recursiveFunctions(); for(auto&& [function, variables]: CompilabilityChecker{ - _dialect, _object, true }.unreachableVariables diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 5a57b779dc87..cc5f68e71ecf 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -121,6 +121,8 @@ EVMVersion ProtoConverter::evmVersionMapping(Program_Version const& _ver) return EVMVersion::cancun(); case Program::PRAGUE: return EVMVersion::prague(); + case Program::OSAKA: + return EVMVersion::osaka(); } } diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index 595aecdca3f4..5a9192bc3a05 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -41,7 +41,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::minimal(), - langutil::DebugInfoSelection::All() + langutil::DebugInfoSelection::AllExceptExperimental() ); if (!stack.parseAndAnalyze("source", input)) diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index ffeb14702183..a4515b30957a 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -65,7 +65,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); try { diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index 7553c81c0f44..4543804926ee 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -42,7 +42,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); if (!stack.parseAndAnalyze("source", input)) diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index 033dfc044d12..b95df8f2138c 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -64,7 +64,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( } catch (ExpressionNestingLimitReached const&) { - reason = TerminationReason::ExpresionNestingLimitReached; + reason = TerminationReason::ExpressionNestingLimitReached; } catch (ExplicitlyTerminated const&) { @@ -83,5 +83,5 @@ bool yulFuzzerUtil::resourceLimitsExceeded(TerminationReason _reason) return _reason == yulFuzzerUtil::TerminationReason::StepLimitReached || _reason == yulFuzzerUtil::TerminationReason::TraceLimitReached || - _reason == yulFuzzerUtil::TerminationReason::ExpresionNestingLimitReached; + _reason == yulFuzzerUtil::TerminationReason::ExpressionNestingLimitReached; } diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h index 6575db11face..afcb0f2d3c9e 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.h +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -28,7 +28,7 @@ struct yulFuzzerUtil ExplicitlyTerminated, StepLimitReached, TraceLimitReached, - ExpresionNestingLimitReached, + ExpressionNestingLimitReached, None }; diff --git a/test/tools/ossfuzz/yulProto.proto b/test/tools/ossfuzz/yulProto.proto index 15ac01396bcc..a22aacb0df03 100644 --- a/test/tools/ossfuzz/yulProto.proto +++ b/test/tools/ossfuzz/yulProto.proto @@ -407,6 +407,7 @@ message Program { SHANGHAI = 10; CANCUN = 11; PRAGUE = 12; + OSAKA = 13; } oneof program_oneof { Block block = 1; diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index 4e9387f6f51e..2f372c3254c1 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -80,10 +80,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // TODO: Add EOF support // Optimize - YulOptimizerTestCommon optimizerTest( - stack.parserResult(), - EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt) - ); + YulOptimizerTestCommon optimizerTest(stack.parserResult()); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); auto const* astRoot = optimizerTest.run(); yulAssert(astRoot != nullptr, "Optimiser error."); diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index eff96f831eaf..d15043972693 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -99,10 +99,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) return; // TODO: Add EOF support - YulOptimizerTestCommon optimizerTest( - stack.parserResult(), - EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt) - ); + YulOptimizerTestCommon optimizerTest(stack.parserResult()); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); auto const* astRoot = optimizerTest.run(); yulAssert(astRoot != nullptr, "Optimiser error."); diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index a2621970aadf..0e91c38e1248 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -106,8 +107,6 @@ void copyZeroExtendedWithOverlap( } -using u512 = boost::multiprecision::number>; - u256 EVMInstructionInterpreter::eval( evmasm::Instruction _instruction, std::vector const& _arguments @@ -417,7 +416,7 @@ u256 EVMInstructionInterpreter::eval( m_state.trace.clear(); BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); case Instruction::POP: - break; + return 0; // --------------- invalid in strict assembly --------------- case Instruction::JUMP: case Instruction::JUMPI: @@ -487,6 +486,8 @@ u256 EVMInstructionInterpreter::eval( case Instruction::SWAP14: case Instruction::SWAP15: case Instruction::SWAP16: + case Instruction::SWAPN: + case Instruction::DUPN: // --------------- Tron --------------- case Instruction::CALLTOKEN: case Instruction::TOKENBALANCE: @@ -504,13 +505,22 @@ u256 EVMInstructionInterpreter::eval( case Instruction::NATIVEWITHDRAWEXPIREUNFREEZE: case Instruction::NATIVEDELEGATERESOURCE: case Instruction::NATIVEUNDELEGATERESOURCE: - { - yulAssert(false, ""); - return 0; - } + yulAssert(false, "Impossible in strict assembly."); + case Instruction::DATALOADN: + case Instruction::CALLF: + case Instruction::RETF: + case Instruction::JUMPF: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: + case Instruction::RJUMP: + case Instruction::RJUMPI: + case Instruction::EXTCALL: + case Instruction::EXTSTATICCALL: + case Instruction::EXTDELEGATECALL: + solUnimplemented("EOF not yet supported by Yul interpreter."); } - return 0; + util::unreachable(); } u256 EVMInstructionInterpreter::evalBuiltin( @@ -522,7 +532,7 @@ u256 EVMInstructionInterpreter::evalBuiltin( if (_fun.instruction) return eval(*_fun.instruction, _evaluatedArguments); - std::string fun = _fun.name.str(); + std::string const& fun = _fun.name; // Evaluate datasize/offset/copy instructions if (fun == "datasize" || fun == "dataoffset") { diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index 21e97f0769c8..2709d1b468aa 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -309,14 +309,14 @@ void ExpressionEvaluator::operator()(Identifier const& _identifier) void ExpressionEvaluator::operator()(FunctionCall const& _funCall) { std::vector> const* literalArguments = nullptr; - if (BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name)) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_funCall.functionName, m_dialect)) if (!builtin->literalArguments.empty()) literalArguments = &builtin->literalArguments; evaluateArgs(_funCall.arguments, literalArguments); if (EVMDialect const* dialect = dynamic_cast(&m_dialect)) { - if (BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) + if (BuiltinFunctionForEVM const* fun = resolveBuiltinFunctionForEVM(_funCall.functionName, *dialect)) { EVMInstructionInterpreter interpreter(dialect->evmVersion(), m_state, m_disableMemoryTrace); @@ -334,13 +334,14 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall) } } + yulAssert(!isBuiltinFunctionCall(_funCall)); Scope* scope = &m_scope; for (; scope; scope = scope->parent) - if (scope->names.count(_funCall.functionName.name)) + if (scope->names.count(std::get(_funCall.functionName).name)) break; yulAssert(scope, ""); - FunctionDefinition const* fun = scope->names.at(_funCall.functionName.name); + FunctionDefinition const* fun = scope->names.at(std::get(_funCall.functionName).name); yulAssert(fun, "Function not found."); yulAssert(m_values.size() == fun->parameters.size(), ""); std::map variables; diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index 356a190709a7..427a30d9ea08 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -35,7 +35,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; } namespace solidity::yul::test diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index cbe0219676fa..b164bfb4f3d1 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -91,7 +91,7 @@ class YulOpti try { auto ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); - if (!m_astRoot || errorReporter.hasErrors()) + if (!ast || errorReporter.hasErrors()) { std::cerr << "Error parsing source." << std::endl; printErrors(_charStream, errors); @@ -180,7 +180,7 @@ class YulOpti parse(_source); disambiguate(); OptimiserSuite{m_context}.runSequence(_steps, *m_astRoot); - std::cout << AsmPrinter{}(*m_astRoot) << std::endl; + std::cout << AsmPrinter{m_dialect}(*m_astRoot) << std::endl; } void runInteractive(std::string _source, bool _disambiguated = false) @@ -218,8 +218,8 @@ class YulOpti case ';': { Object obj; - obj.setCode(std::make_shared(std::get(ASTCopier{}(*m_astRoot)))); - *m_astRoot = std::get<1>(StackCompressor::run(m_dialect, obj, true, 16)); + obj.setCode(std::make_shared(m_dialect, std::get(ASTCopier{}(*m_astRoot)))); + *m_astRoot = std::get<1>(StackCompressor::run(obj, true, 16)); break; } default: @@ -228,7 +228,7 @@ class YulOpti *m_astRoot ); } - _source = AsmPrinter{}(*m_astRoot); + _source = AsmPrinter{m_dialect}(*m_astRoot); } catch (...) { diff --git a/test/yulPhaser/Chromosome.cpp b/test/yulPhaser/Chromosome.cpp index da109086a916..5503de1bfe34 100644 --- a/test/yulPhaser/Chromosome.cpp +++ b/test/yulPhaser/Chromosome.cpp @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(makeRandom_should_use_every_possible_step_with_the_same_pro constexpr int samplesPerStep = 500; constexpr double relativeTolerance = 0.02; - std::map stepIndices = enumerateOptmisationSteps(); + std::map stepIndices = enumerateOptimisationSteps(); auto chromosome = Chromosome::makeRandom(stepIndices.size() * samplesPerStep); std::vector samples; @@ -85,8 +85,8 @@ BOOST_AUTO_TEST_CASE(makeRandom_should_use_every_possible_step_with_the_same_pro const double expectedValue = double(stepIndices.size() - 1) / 2.0; const double variance = double(stepIndices.size() * stepIndices.size() - 1) / 12.0; - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(fabs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(fabs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(constructor_should_store_genes) @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(randomOptimisationStep_should_return_each_step_with_same_pr constexpr int samplesPerStep = 500; constexpr double relativeTolerance = 0.02; - std::map stepIndices = enumerateOptmisationSteps(); + std::map stepIndices = enumerateOptimisationSteps(); std::vector samples; for (size_t i = 0; i <= stepIndices.size() * samplesPerStep; ++i) samples.push_back(stepIndices.at(Chromosome::randomOptimisationStep())); @@ -159,8 +159,8 @@ BOOST_AUTO_TEST_CASE(randomOptimisationStep_should_return_each_step_with_same_pr const double expectedValue = double(stepIndices.size() - 1) / 2.0; const double variance = double(stepIndices.size() * stepIndices.size() - 1) / 12.0; - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(fabs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(fabs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(stepsToGenes_should_translate_optimisation_step_names_to_abbreviations) diff --git a/test/yulPhaser/Population.cpp b/test/yulPhaser/Population.cpp index aed014592c1b..dedaa766f912 100644 --- a/test/yulPhaser/Population.cpp +++ b/test/yulPhaser/Population.cpp @@ -185,7 +185,7 @@ BOOST_FIXTURE_TEST_CASE(makeRandom_should_return_population_with_random_chromoso constexpr int chromosomeLength = 30; constexpr double relativeTolerance = 0.01; - std::map stepIndices = enumerateOptmisationSteps(); + std::map stepIndices = enumerateOptimisationSteps(); auto population = Population::makeRandom(m_fitnessMetric, populationSize, chromosomeLength, chromosomeLength); std::vector samples; diff --git a/test/yulPhaser/TestHelpers.cpp b/test/yulPhaser/TestHelpers.cpp index d75b63b4ac8b..baf7fb222f1c 100644 --- a/test/yulPhaser/TestHelpers.cpp +++ b/test/yulPhaser/TestHelpers.cpp @@ -53,7 +53,7 @@ std::vector phaser::test::chromosomeLengths(Population const& _populatio return lengths; } -std::map phaser::test::enumerateOptmisationSteps() +std::map phaser::test::enumerateOptimisationSteps() { std::map stepIndices; size_t i = 0; diff --git a/test/yulPhaser/TestHelpers.h b/test/yulPhaser/TestHelpers.h index f9d0afa4cf59..adfea7946d50 100644 --- a/test/yulPhaser/TestHelpers.h +++ b/test/yulPhaser/TestHelpers.h @@ -105,7 +105,7 @@ size_t countDifferences(Chromosome const& _chromosome1, Chromosome const& _chrom /// Assigns indices from 0 to N to all optimisation steps available in the OptimiserSuite. /// This is a convenience helper to make it easier to test their distribution with tools made for /// integers. -std::map enumerateOptmisationSteps(); +std::map enumerateOptimisationSteps(); // STRING UTILITIES diff --git a/test/yulPhaser/TestHelpersTest.cpp b/test/yulPhaser/TestHelpersTest.cpp index 23be74230cca..d4f698561a34 100644 --- a/test/yulPhaser/TestHelpersTest.cpp +++ b/test/yulPhaser/TestHelpersTest.cpp @@ -96,10 +96,10 @@ BOOST_AUTO_TEST_CASE(countDifferences_should_count_missing_characters_as_differe BOOST_TEST(countDifferences(Chromosome("aa"), Chromosome("cccc")) == 4); } -BOOST_AUTO_TEST_CASE(enumerateOptimisationSteps_should_assing_indices_to_all_available_optimisation_steps) +BOOST_AUTO_TEST_CASE(enumerateOptimisationSteps_should_assign_indices_to_all_available_optimisation_steps) { std::map stepsAndAbbreviations = OptimiserSuite::stepNameToAbbreviationMap(); - std::map stepsAndIndices = enumerateOptmisationSteps(); + std::map stepsAndIndices = enumerateOptimisationSteps(); BOOST_TEST(stepsAndIndices.size() == stepsAndAbbreviations.size()); std::set stepsSoFar; diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index fa7fbe274c95..6d182782701e 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -59,7 +59,7 @@ std::ostream& operator<<(std::ostream& _stream, Program const& _program); } Program::Program(Program const& program): - m_ast(std::make_unique(std::get(ASTCopier{}(program.m_ast->root())))), + m_ast(std::make_unique(program.m_dialect, std::get(ASTCopier{}(program.m_ast->root())))), m_dialect{program.m_dialect}, m_nameDispenser(program.m_nameDispenser) { @@ -106,12 +106,12 @@ void Program::optimise(std::vector const& _optimisationSteps) std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { - return _stream << AsmPrinter()(_program.m_ast->root()); + return _stream << AsmPrinter::format(*_program.m_ast); } std::string Program::toJson() const { - Json serializedAst = AsmJsonConverter(0)(m_ast->root()); + Json serializedAst = AsmJsonConverter(m_dialect, 0)(m_ast->root()); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); } @@ -150,7 +150,7 @@ std::variant, ErrorList> Program::parseObject(Dialect const // The public API of the class does not provide access to the smart pointer so it won't be hard // to switch to shared_ptr if the copying turns out to be an issue (though it would be better // to refactor ObjectParser and Object to use unique_ptr instead). - auto astCopy = std::make_unique(std::get(ASTCopier{}(selectedObject->code()->root()))); + auto astCopy = std::make_unique(_dialect, std::get(ASTCopier{}(selectedObject->code()->root()))); return std::variant, ErrorList>(std::move(astCopy)); } @@ -179,7 +179,7 @@ std::unique_ptr Program::disambiguateAST( std::set const externallyUsedIdentifiers = {}; Disambiguator disambiguator(_dialect, _analysisInfo, externallyUsedIdentifiers); - return std::make_unique(std::get(disambiguator(_ast.root()))); + return std::make_unique(_dialect, std::get(disambiguator(_ast.root()))); } std::unique_ptr Program::applyOptimisationSteps( @@ -203,7 +203,7 @@ std::unique_ptr Program::applyOptimisationSteps( for (std::string const& step: _optimisationSteps) OptimiserSuite::allSteps().at(step)->run(context, astRoot); - return std::make_unique(std::move(astRoot)); + return std::make_unique(_dialect, std::move(astRoot)); } size_t Program::computeCodeSize(Block const& _ast, CodeWeights const& _weights) diff --git a/tools/yulPhaser/Program.h b/tools/yulPhaser/Program.h index be4bf582d665..7ac7f3aad157 100644 --- a/tools/yulPhaser/Program.h +++ b/tools/yulPhaser/Program.h @@ -43,7 +43,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; -struct Dialect; +class Dialect; struct CodeWeights; }