diff --git a/.circleci/config.yml b/.circleci/config.yml index 6e076322f8b1..9067057ddab5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -155,7 +155,7 @@ commands: ) echo "export FOUNDRY_REPO=$FOUNDRY_REPO" >> "$BASH_ENV" echo "export FOUNDRY_VERSION=$FOUNDRY_VERSION" >> "$BASH_ENV" - echo "export FOUNDRY_RELEASE_TAG='nightly-${FOUNDRY_RELEASE_SHA}'" >> "$BASH_ENV" + echo "export FOUNDRY_RELEASE_TAG='${FOUNDRY_VERSION}'" >> "$BASH_ENV" # Save commit sha for caching echo "$FOUNDRY_RELEASE_SHA" > /tmp/workspace/foundry-release-sha - restore_cache: @@ -220,11 +220,18 @@ commands: command: .circleci/soltest.sh run_soltest_all: + parameters: + # NOTE: If not specified, soltest_all.sh will use the default values as specified in the script. + # In other words, it will execute for all EVM versions that are not marked as deprecated. + evm_versions: + description: "List of EVM versions (separated by space)." + type: string + default: "" steps: - run: name: soltest_all no_output_timeout: 30m - command: .circleci/soltest_all.sh + command: .circleci/soltest_all.sh "<< parameters.evm_versions >>" run_cmdline_tests: steps: @@ -242,6 +249,13 @@ commands: # -------------------------------------------------------------------------- # Artifact Commands + remove_signature_from_universal_binary: + description: Remove signature from universal binary + steps: + - run: + name: Remove signature from universal binary + command: codesign --remove-signature build/solc/solc + store_artifacts_solc: description: Store compiled solc executable as artifact steps: @@ -498,7 +512,6 @@ defaults: TERM: xterm MAKEFLAGS: -j5 CPUs: 5 - ETH_EVMONE: /usr/local/lib/libevmone.dylib - base_python_small: &base_python_small docker: @@ -716,11 +729,14 @@ defaults: image: cimg/node:14.20 python2: true - - job_native_test_ext_gnosis: &job_native_test_ext_gnosis + - job_native_compile_ext_gnosis: &job_native_compile_ext_gnosis <<: *requires_b_ubu_static - name: t_native_test_ext_gnosis + name: t_native_compile_ext_gnosis project: gnosis binary_type: native + # NOTE: We are disabling the gnosis test suite due to version discrepancies that are difficult to fix. + # Check again after (and if) https://github.com/safe-global/safe-contracts/pull/644 is merged. + compile_only: 1 image: cimg/node:18.16 - job_native_test_ext_zeppelin: &job_native_test_ext_zeppelin @@ -738,18 +754,24 @@ defaults: binary_type: native image: cimg/node:18.16 - - job_native_test_ext_trident: &job_native_test_ext_trident + - job_native_compile_ext_trident: &job_native_compile_ext_trident <<: *requires_b_ubu_static - name: t_native_test_ext_trident + name: t_native_compile_ext_trident project: trident 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 image: cimg/node:18.16 - - job_native_test_ext_euler: &job_native_test_ext_euler + - job_native_compile_ext_euler: &job_native_compile_ext_euler <<: *requires_b_ubu_static - name: t_native_test_ext_euler + 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 @@ -759,18 +781,24 @@ defaults: binary_type: native image: cimg/node:18.16 - - job_native_test_ext_bleeps: &job_native_test_ext_bleeps + - job_native_compile_ext_bleeps: &job_native_compile_ext_bleeps <<: *requires_b_ubu_static - name: t_native_test_ext_bleeps + name: t_native_compile_ext_bleeps project: bleeps 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_pool_together: &job_native_test_ext_pool_together + - job_native_compile_ext_pool_together: &job_native_compile_ext_pool_together <<: *requires_b_ubu_static - name: t_native_test_ext_pool_together + name: t_native_compile_ext_pool_together project: pool-together 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 image: cimg/node:18.16 - job_native_test_ext_perpetual_pools: &job_native_test_ext_perpetual_pools @@ -810,19 +838,24 @@ defaults: binary_type: native image: cimg/node:18.16 - - job_native_test_ext_chainlink: &job_native_test_ext_chainlink + - job_native_compile_ext_chainlink: &job_native_compile_ext_chainlink <<: *requires_b_ubu_static - name: t_native_test_ext_chainlink + name: t_native_compile_ext_chainlink project: chainlink binary_type: native - image: cimg/node:18.16 + # NOTE: test suite disabled due to dependence on a specific version of Hardhat + # which does not support shanghai EVM. + compile_only: 1 + image: cimg/node:16.20 resource_class: large # Tests run out of memory on a smaller machine - - job_native_test_ext_gp2: &job_native_test_ext_gp2 + - job_native_compile_ext_gp2: &job_native_compile_ext_gp2 <<: *requires_b_ubu_static - name: t_native_test_ext_gp2 + name: t_native_compile_ext_gp2 project: gp2 binary_type: native + # NOTE: test suite disabled due to constant failures. + compile_only: 1 image: cimg/node:18.16 - job_b_ubu_asan_clang: &job_b_ubu_asan_clang @@ -969,9 +1002,16 @@ jobs: <<: *base_ubuntu2204_small steps: - checkout + - run: + # TODO: Add these to the base image + name: Install gas_diff_stats.py dependencies + command: python3 -m pip install --user parsec tabulate - run: name: Python unit tests command: python3 test/pyscriptTests.py + - run: + name: Smoke test for gas_diff_stats.py + command: scripts/gas_diff_stats.py - matrix_notify_failure_unless_pr t_win_pyscripts: @@ -979,6 +1019,9 @@ jobs: steps: - run: git config --global core.autocrlf false - checkout + - run: + name: Install dependencies + command: python -m pip install --user requests parsec tabulate - run: name: Python unit tests command: python.exe test/pyscriptTests.py @@ -1155,6 +1198,7 @@ jobs: - checkout - install_dependencies_osx - run_build + - remove_signature_from_universal_binary - store_artifacts_solc - store_artifacts_yul_phaser - persist_executables_to_workspace_osx @@ -1232,6 +1276,20 @@ jobs: steps: - soltest_all + t_ubu_soltest_deprecated_evm_versions: &t_ubu_soltest_deprecated_evm_versions + <<: *base_ubuntu2204_large + parallelism: 50 + steps: + - checkout + - attach_workspace: + at: build + - run_soltest_all: + evm_versions: homestead byzantium + - store_test_results: + path: test_results/ + - store_artifacts_test_results + - matrix_notify_failure_unless_pr + t_ubu_lsp: &t_ubu_lsp <<: *base_ubuntu2204_small steps: @@ -1370,7 +1428,7 @@ jobs: t_ems_ext_hardhat: <<: *base_node_small docker: - - image: cimg/node:18.16 + - image: cimg/rust:1.74.0-node environment: <<: *base_node_small_env HARDHAT_TESTS_SOLC_PATH: /tmp/workspace/soljson.js @@ -1378,7 +1436,28 @@ jobs: - checkout - attach_workspace: at: /tmp/workspace - - run: git clone --depth 1 https://github.com/nomiclabs/hardhat.git + - run: + name: Ensure pnpm is installed if npm is present + command: sudo npm install -g pnpm + - run: + name: Retrieve Hardhat latest release tag + command: | + # Make authenticated requests when the Github token is available + if [[ -n "$GITHUB_ACCESS_TOKEN" ]]; then + EXTRA_HEADERS=(--header "Authorization: Bearer ${GITHUB_ACCESS_TOKEN}") + fi + HARDHAT_LATEST_RELEASE_TAG=$( + curl \ + --silent \ + --location \ + --fail \ + --show-error \ + "${EXTRA_HEADERS[@]}" \ + https://api.github.com/repos/nomiclabs/hardhat/releases/latest \ + | jq --raw-output .tag_name \ + ) + echo "export HARDHAT_LATEST_RELEASE_TAG='${HARDHAT_LATEST_RELEASE_TAG}'" >> "$BASH_ENV" + - run: git clone --depth 1 https://github.com/nomiclabs/hardhat.git --branch "$HARDHAT_LATEST_RELEASE_TAG" - run: name: Install dependencies command: | @@ -1392,6 +1471,9 @@ jobs: # NOTE: This is expected to work without running `pnpm build` first. cd hardhat/packages/hardhat-core + # TODO: temporarily set hardhat stack traces tests to use cancun hardfork + # Remove this when hardhat switch to cancun by default: https://github.com/NomicFoundation/hardhat/issues/4851 + sed -i 's/hardfork: "shanghai",/hardfork: "cancun",/' test/internal/hardhat-network/stack-traces/execution.ts pnpm test - matrix_notify_failure_unless_pr @@ -1689,8 +1771,12 @@ jobs: # platforms so line ending conversions must absolutely be disabled. - run: git config --global core.autocrlf false - checkout - # Ensure windows has python3 alias required by prepare_bytecode_report - - run: ln -s /c/tools/miniconda3/python /c/tools/miniconda3/python3 + - run: + name: Force install python3.12.2 + command: choco install python3 --pre --force --version=3.12.2 + - run: + name: Create a symlink for python3 + command: ln -s /c/ProgramData/chocolatey/bin/python3.12 /c/ProgramData/chocolatey/bin/python3 - attach_workspace: at: build - prepare_bytecode_report: @@ -1828,9 +1914,7 @@ workflows: - t_ext: *job_ems_compile_ext_colony - # NOTE: We are disabling the gnosis test suite due to version discrepancies that are difficult to fix. - # Check again after (and if) https://github.com/safe-global/safe-contracts/pull/644 is merged. - #- t_ext: *job_native_test_ext_gnosis + - t_ext: *job_native_compile_ext_gnosis - t_ext: *job_native_test_ext_zeppelin - t_ext: *job_native_test_ext_ens - t_ext: *job_native_test_ext_yield_liquidator @@ -1839,23 +1923,20 @@ workflows: - t_ext: *job_native_test_ext_prb_math - t_ext: *job_native_test_ext_elementfi - t_ext: *job_native_test_ext_brink - # NOTE: We are disabling gp2 tests due to constant failures. - # - t_ext: *job_native_test_ext_gp2 - # NOTE: The external tests below were commented because they - # depend on a specific version of hardhat which does not support shanghai EVM. - #- t_ext: *job_native_test_ext_trident - #- t_ext: *job_native_test_ext_euler - #- t_ext: *job_native_test_ext_bleeps - #- t_ext: *job_native_test_ext_pool_together - #- t_ext: *job_native_test_ext_chainlink + - t_ext: *job_native_compile_ext_gp2 + - t_ext: *job_native_compile_ext_euler + - t_ext: *job_native_compile_ext_pool_together + # TODO: Dropping the external tests below since they are based on old forks and + # fail after update the default evm version to cancun. + #- t_ext: *job_native_compile_ext_trident + #- t_ext: *job_native_compile_ext_chainlink + #- t_ext: *job_native_compile_ext_bleeps - c_ext_benchmarks: <<: *requires_nothing requires: - t_ems_compile_ext_colony - # NOTE: We are disabling the gnosis test suite due to version discrepancies that are difficult to fix. - # Check again after (and if) https://github.com/safe-global/safe-contracts/pull/644 is merged. - #- t_native_test_ext_gnosis + - t_native_compile_ext_gnosis - t_native_test_ext_zeppelin - t_native_test_ext_ens - t_native_test_ext_yield_liquidator @@ -1863,18 +1944,17 @@ workflows: - t_native_test_ext_uniswap - t_native_test_ext_elementfi - t_native_test_ext_brink - # NOTE: We are disabling gp2 tests due to constant failures. - #- t_native_test_ext_gp2 + - t_native_compile_ext_gp2 # TODO: Dropping prb-math from the benchmarks since it is not implemented yet # in the new Foundry external testing infrastructure. # - t_native_test_ext_prb_math - # NOTE: The external tests below were commented because they - # depend on a specific version of hardhat which does not support shanghai EVM. - #- t_native_test_ext_trident - #- t_native_test_ext_euler - #- t_native_test_ext_bleeps - #- t_native_test_ext_pool_together - #- t_native_test_ext_chainlink + - t_native_compile_ext_euler + - t_native_compile_ext_pool_together + # TODO: Dropping the external tests below since they are based on old forks and + # fail after update the default evm version to cancun. + #- t_native_compile_ext_trident + #- t_native_compile_ext_chainlink + #- t_native_compile_ext_bleeps # Windows build and tests - b_win: *requires_nothing diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 1e941731dac3..009852710e51 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,9 +31,12 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" -EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin london paris shanghai cancun) -DEFAULT_EVM=shanghai -[[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]] +DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun) +# 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) # Run for ABI encoder v1, without SMTChecker tests. diff --git a/CMakeLists.txt b/CMakeLists.txt index f6a905e39aa8..18af34d26bf0 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.24") +set(PROJECT_VERSION "0.8.25") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index e8fc3e59744f..f72a654a530a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,20 @@ +### 0.8.25 (2023-03-14) + +Compiler Features: + * Code Generator: Use ``MCOPY`` instead of ``MLOAD``/``MSTORE`` loop when copying byte arrays. + * EVM: Set default EVM version to ``cancun``. + * Yul Analyzer: Emit transient storage warning only for the first occurrence of ``tstore``. + + +Bugfixes: + * Assembler: Prevent incorrect calculation of tag sizes. + * Commandline Interface: Do not run IR pipeline when ``--via-ir`` is used but no output that depends on the IR is requested. + * EVM Assembly Import: Fix handling of missing source locations during import. + * SMTChecker: Ensure query is properly flushed to a file before calling solver when using SMT-LIB interface. + * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. + * SMTChecker: Run Eldarica only when explicitly requested with `--model-checker-solvers eld`, even when it is present on the system. + + ### 0.8.24 (2024-01-25) Language Features: @@ -10,10 +27,11 @@ Language Features: Compiler Features: -* EVM: Support for the EVM Version "Cancun". -* SMTChecker: Support `bytes.concat` except when string literals are passed as arguments. -* Standard JSON Interface: Add experimental support to import EVM assembly in the format used by ``--asm-json``. -* TypeChecker: Comparison of internal function pointers now yields a warning, as it can produce unexpected results with the legacy pipeline enabled. + * EVM: Support for the EVM Version "Cancun". + * SMTChecker: Support `bytes.concat` except when string literals are passed as arguments. + * SMTChecker: Print a message that function parameter name was used instead of a concrete value in a counterexample when the concrete value found by the solver is too long to print. + * Standard JSON Interface: Add experimental support to import EVM assembly in the format used by ``--asm-json``. + * TypeChecker: Comparison of internal function pointers now yields a warning, as it can produce unexpected results with the legacy pipeline enabled. Bugfixes: diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 167417a95d1a..5db731cfc591 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -50,7 +50,7 @@ At least a day before the release: ### Create the Release - [ ] Create a [release on GitHub](https://github.com/ethereum/solidity/releases/new). Set the target to the ``develop`` branch and the tag to the new version, e.g. ``v0.8.5``. - Include the following warning: ``**The release is still in progress and the binaries may not yet be available from all sources.**``. + Include the following warning: ``**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**``. Do not publish it yet - click the ``Save draft`` button instead. - [ ] Thank voluntary contributors in the GitHub release notes. Use ``scripts/list_contributors.sh v`` to get initial list of names. @@ -68,6 +68,7 @@ At least a day before the release: - [ ] Take the ``github-binaries.tar`` tarball from ``c_release_binaries`` run of the tagged commit in circle-ci and add all binaries from it to the release page. Make sure it contains four binaries: ``solc-windows.exe``, ``solc-macos``, ``solc-static-linux`` and ``soljson.js``. - [ ] Take the ``solc-bin-binaries.tar`` tarball from ``c_release_binaries`` run of the tagged commit in circle-ci and add all binaries from it to solc-bin. + - [ ] Run ``npm install`` if you've got a clean checkout of the solc-bin repo. - [ ] Run ``npm run update -- --reuse-hashes`` in ``solc-bin`` and verify that the script has updated ``list.js``, ``list.txt`` and ``list.json`` files correctly and that symlinks to the new release have been added in ``solc-bin/wasm/`` and ``solc-bin/emscripten-wasm32/``. - [ ] Create a pull request in solc-bin and merge. diff --git a/docs/bugs.rst b/docs/bugs.rst index 350b1e7a48e8..f7f18e9a7f86 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -7,7 +7,7 @@ List of Known Bugs ################## Below, you can find a JSON-formatted list of some of the known security-relevant bugs in the -Solidity compiler. The file itself is hosted in the `Github repository +Solidity compiler. The file itself is hosted in the `GitHub repository `_. The list stretches back as far as version 0.3.0, bugs known to be present only in versions preceding that are not listed. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 156b846d012d..7022635fde1a 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1890,6 +1890,10 @@ "bugs": [], "released": "2024-01-25" }, + "0.8.25": { + "bugs": [], + "released": "2023-03-14" + }, "0.8.3": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 2b68d7311982..bc678c647d54 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -118,7 +118,7 @@ Contract-related - ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` or ``address payable`` - ``super``: a contract one level higher in the inheritance hierarchy -- ``selfdestruct(address payable recipient)``: destroy the current contract, sending its funds to the given address +- ``selfdestruct(address payable recipient)``: send all funds to the given address and (only on EVMs before Cancun or when invoked within the transaction creating the contract) destroy the contract. .. index:: type;name, type;creationCode, type;runtimeCode, type;interfaceId, type;min, type;max @@ -159,7 +159,7 @@ Modifiers - ``pure`` for functions: Disallows modification or access of state. - ``view`` for functions: Disallows modification of state. - ``payable`` for functions: Allows them to receive Ether together with a call. -- ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot. +- ``constant`` for state variables: Disallows assignment (except initialization), does not occupy storage slot. - ``immutable`` for state variables: Allows assignment at construction time and is constant when deployed. Is stored in code. - ``anonymous`` for events: Does not store event signature as topic. - ``indexed`` for event parameters: Stores the parameter as topic. diff --git a/docs/contracts/function-modifiers.rst b/docs/contracts/function-modifiers.rst index 454e12ab65cf..2fd0357db054 100644 --- a/docs/contracts/function-modifiers.rst +++ b/docs/contracts/function-modifiers.rst @@ -19,7 +19,6 @@ if they are marked ``virtual``. For details, please see // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1 <0.9.0; - // This will report a warning due to deprecated selfdestruct contract owned { constructor() { owner = payable(msg.sender); } @@ -41,16 +40,6 @@ if they are marked ``virtual``. For details, please see } } - contract destructible is owned { - // This contract inherits the `onlyOwner` modifier from - // `owned` and applies it to the `destroy` function, which - // causes that calls to `destroy` only have an effect if - // they are made by the stored owner. - function destroy() public onlyOwner { - selfdestruct(owner); - } - } - contract priced { // Modifiers can receive arguments: modifier costs(uint price) { @@ -60,7 +49,7 @@ if they are marked ``virtual``. For details, please see } } - contract Register is priced, destructible { + contract Register is priced, owned { mapping(address => bool) registeredAddresses; uint price; @@ -73,6 +62,9 @@ if they are marked ``virtual``. For details, please see registeredAddresses[msg.sender] = true; } + // This contract inherits the `onlyOwner` modifier from + // the `owned` contract. As a result, calls to `changePrice` will + // only take effect if they are made by the stored owner. function changePrice(uint price_) public onlyOwner { price = price_; } diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index c787c5af6a90..fccfee609587 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -40,27 +40,27 @@ Details are given in the following example. // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct contract Owned { - constructor() { owner = payable(msg.sender); } address payable owner; + constructor() { owner = payable(msg.sender); } } - // Use `is` to derive from another contract. Derived // contracts can access all non-private members including // internal functions and state variables. These cannot be // accessed externally via `this`, though. - contract Destructible is Owned { + contract Emittable is Owned { + event Emitted(); + // The keyword `virtual` means that the function can change // its behavior in derived classes ("overriding"). - function destroy() virtual public { - if (msg.sender == owner) selfdestruct(owner); + function emitEvent() virtual public { + if (msg.sender == owner) + emit Emitted(); } } - // These abstract contracts are only provided to make the // interface known to the compiler. Note the function // without body. If a contract does not implement all @@ -69,37 +69,35 @@ Details are given in the following example. function lookup(uint id) public virtual returns (address adr); } - abstract contract NameReg { function register(bytes32 name) public virtual; function unregister() public virtual; } - // Multiple inheritance is possible. Note that `Owned` is - // also a base class of `Destructible`, yet there is only a single + // also a base class of `Emittable`, yet there is only a single // instance of `Owned` (as for virtual inheritance in C++). - contract Named is Owned, Destructible { + contract Named is Owned, Emittable { constructor(bytes32 name) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).register(name); } // Functions can be overridden by another function with the same name and - // the same number/types of inputs. If the overriding function has different + // the same number/types of inputs. If the overriding function has different // types of output parameters, that causes an error. // Both local and message-based function calls take these overrides // into account. // If you want the function to override, you need to use the // `override` keyword. You need to specify the `virtual` keyword again // if you want this function to be overridden again. - function destroy() public virtual override { + function emitEvent() public virtual override { if (msg.sender == owner) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).unregister(); // It is still possible to call a specific // overridden function. - Destructible.destroy(); + Emittable.emitEvent(); } } } @@ -108,93 +106,132 @@ Details are given in the following example. // If a constructor takes an argument, it needs to be // provided in the header or modifier-invocation-style at // the constructor of the derived contract (see below). - contract PriceFeed is Owned, Destructible, Named("GoldFeed") { + contract PriceFeed is Owned, Emittable, Named("GoldFeed") { + uint info; + function updateInfo(uint newInfo) public { if (msg.sender == owner) info = newInfo; } // Here, we only specify `override` and not `virtual`. // This means that contracts deriving from `PriceFeed` - // cannot change the behavior of `destroy` anymore. - function destroy() public override(Destructible, Named) { Named.destroy(); } + // cannot change the behavior of `emitEvent` anymore. + function emitEvent() public override(Emittable, Named) { Named.emitEvent(); } function get() public view returns(uint r) { return info; } - - uint info; } -Note that above, we call ``Destructible.destroy()`` to "forward" the -destruction request. The way this is done is problematic, as +Note that above, we call ``Emittable.emitEvent()`` to "forward" the +emit event request. The way this is done is problematic, as seen in the following example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract owned { - constructor() { owner = payable(msg.sender); } + contract Owned { address payable owner; + constructor() { owner = payable(msg.sender); } } - contract Destructible is owned { - function destroy() public virtual { - if (msg.sender == owner) selfdestruct(owner); + contract Emittable is Owned { + event Emitted(); + + function emitEvent() virtual public { + if (msg.sender == owner) { + emit Emitted(); + } } } - contract Base1 is Destructible { - function destroy() public virtual override { /* do cleanup 1 */ Destructible.destroy(); } + contract Base1 is Emittable { + event Base1Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base1 logic */ + emit Base1Emitted(); + Emittable.emitEvent(); + } } - contract Base2 is Destructible { - function destroy() public virtual override { /* do cleanup 2 */ Destructible.destroy(); } + contract Base2 is Emittable { + event Base2Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base2 logic */ + emit Base2Emitted(); + Emittable.emitEvent(); + } } contract Final is Base1, Base2 { - function destroy() public override(Base1, Base2) { Base2.destroy(); } + event FinalEmitted(); + function emitEvent() public override(Base1, Base2) { + /* Here, we emit an event to simulate some Final logic */ + emit FinalEmitted(); + Base2.emitEvent(); + } } -A call to ``Final.destroy()`` will call ``Base2.destroy`` because we specify it +A call to ``Final.emitEvent()`` will call ``Base2.emitEvent`` because we specify it explicitly in the final override, but this function will bypass -``Base1.destroy``. The way around this is to use ``super``: +``Base1.emitEvent``, resulting in the following sequence of events: +``FinalEmitted -> Base2Emitted -> Emitted``, instead of the expected sequence: +``FinalEmitted -> Base2Emitted -> Base1Emitted -> Emitted``. +The way around this is to use ``super``: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract owned { - constructor() { owner = payable(msg.sender); } + contract Owned { address payable owner; + constructor() { owner = payable(msg.sender); } } - contract Destructible is owned { - function destroy() virtual public { - if (msg.sender == owner) selfdestruct(owner); + contract Emittable is Owned { + event Emitted(); + + function emitEvent() virtual public { + if (msg.sender == owner) { + emit Emitted(); + } } } - contract Base1 is Destructible { - function destroy() public virtual override { /* do cleanup 1 */ super.destroy(); } + contract Base1 is Emittable { + event Base1Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base1 logic */ + emit Base1Emitted(); + super.emitEvent(); + } } - contract Base2 is Destructible { - function destroy() public virtual override { /* do cleanup 2 */ super.destroy(); } + contract Base2 is Emittable { + event Base2Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base2 logic */ + emit Base2Emitted(); + super.emitEvent(); + } } contract Final is Base1, Base2 { - function destroy() public override(Base1, Base2) { super.destroy(); } + event FinalEmitted(); + function emitEvent() public override(Base1, Base2) { + /* Here, we emit an event to simulate some Final logic */ + emit FinalEmitted(); + super.emitEvent(); + } } -If ``Base2`` calls a function of ``super``, it does not simply +If ``Final`` calls a function of ``super``, it does not simply call this function on one of its base contracts. Rather, it calls this function on the next base contract in the final -inheritance graph, so it will call ``Base1.destroy()`` (note that +inheritance graph, so it will call ``Base1.emitEvent()`` (note that the final inheritance sequence is -- starting with the most -derived contract: Final, Base2, Base1, Destructible, owned). +derived contract: Final, Base2, Base1, Emittable, Owned). The actual function that is called when using super is not known in the context of the class where it is used, although its type is known. This is similar for ordinary @@ -398,7 +435,7 @@ Constructors A constructor is an optional function declared with the ``constructor`` keyword which is executed upon contract creation, and where you can run contract -initialisation code. +initialization code. Before the constructor code is executed, state variables are initialised to their specified value if you initialise them inline, or their :ref:`default value` if you do not. diff --git a/docs/contributing.rst b/docs/contributing.rst index ac4e2375ebdc..8ce402680bb1 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -128,7 +128,7 @@ for the ``evmone`` shared object can be specified via the ``ETH_EVMONE`` environ If you do not have it installed, you can skip these tests by passing the ``--no-semantic-tests`` flag to ``scripts/soltest.sh``. -The ``evmone`` library should both end with the file name +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 @@ -552,7 +552,7 @@ topics, issues or feature implementations are debated in detail. The invitation We are also sharing feedback surveys and other content that is relevant to language design in the forum. -If you want to know where the team is standing in terms or implementing new features, you can follow the implementation status in the `Solidity Github project `_. +If you want to know where the team is standing in terms or implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. Issues in the design backlog need further specification and will either be discussed in a language design call or in a regular team call. You can see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index 50f28005bfd6..c3aef0d653da 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -55,7 +55,7 @@ as it provides a number of other security benefits. What to Sign ------------ -For a contract that fulfils payments, the signed message must include: +For a contract that fulfills payments, the signed message must include: 1. The recipient's address. 2. The amount to be transferred. @@ -80,6 +80,10 @@ the contract's address itself will be accepted. You can find an example of this in the first two lines of the ``claimPayment()`` function of the full contract at the end of this section. +Furthermore, instead of destroying the contract by calling ``selfdestruct``, +which is currently deprecated, we will disable the contract's functionalities by freezing it, +resulting in the reversion of any call after it being frozen. + Packing arguments ----------------- @@ -144,30 +148,54 @@ The full contract // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract ReceiverPays { - address owner = msg.sender; + contract Owned { + address payable owner; + constructor() { + owner = payable(msg.sender); + } + } + + contract Freezable is Owned { + bool private _frozen = false; + + modifier notFrozen() { + require(!_frozen, "Inactive Contract."); + _; + } + + function freeze() internal { + if (msg.sender == owner) + _frozen = true; + } + } + + contract ReceiverPays is Freezable { mapping(uint256 => bool) usedNonces; constructor() payable {} - function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) external { + function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) + external + notFrozen + { require(!usedNonces[nonce]); usedNonces[nonce] = true; // this recreates the message that was signed on the client bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this))); - require(recoverSigner(message, signature) == owner); - payable(msg.sender).transfer(amount); } - /// destroy the contract and reclaim the leftover funds. - function shutdown() external { + /// freeze the contract and reclaim the leftover funds. + function shutdown() + external + notFrozen + { require(msg.sender == owner); - selfdestruct(payable(msg.sender)); + freeze(); + payable(msg.sender).transfer(address(this).balance); } /// signature methods. @@ -196,7 +224,6 @@ The full contract returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); - return ecrecover(message, v, r, s); } @@ -305,7 +332,7 @@ Closing the Payment Channel When Bob is ready to receive his funds, it is time to close the payment channel by calling a ``close`` function on the smart contract. Closing the channel pays the recipient the Ether they are owed and -destroys the contract, sending any remaining Ether back to Alice. To +deactivates the contract by freezing it, sending any remaining Ether back to Alice. To close the channel, Bob needs to provide a message signed by Alice. The smart contract must verify that the message contains a valid signature from the sender. @@ -320,7 +347,7 @@ they could provide a message with a lower amount and cheat the recipient out of The function verifies the signed message matches the given parameters. If everything checks out, the recipient is sent their portion of the Ether, -and the sender is sent the rest via a ``selfdestruct``. +and the sender is sent the remaining funds via a ``transfer``. You can see the ``close`` function in the full contract. Channel Expiration @@ -342,11 +369,24 @@ The full contract // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract SimplePaymentChannel { - address payable public sender; // The account sending payments. - address payable public recipient; // The account receiving the payments. - uint256 public expiration; // Timeout in case the recipient never closes. + + contract Frozeable { + bool private _frozen = false; + + modifier notFrozen() { + require(!_frozen, "Inactive Contract."); + _; + } + + function freeze() internal { + _frozen = true; + } + } + + contract SimplePaymentChannel is Frozeable { + address payable public sender; // The account sending payments. + address payable public recipient; // The account receiving the payments. + uint256 public expiration; // Timeout in case the recipient never closes. constructor (address payable recipientAddress, uint256 duration) payable @@ -359,16 +399,23 @@ The full contract /// the recipient can close the channel at any time by presenting a /// signed amount from the sender. the recipient will be sent that amount, /// and the remainder will go back to the sender - function close(uint256 amount, bytes memory signature) external { + function close(uint256 amount, bytes memory signature) + external + notFrozen + { require(msg.sender == recipient); require(isValidSignature(amount, signature)); recipient.transfer(amount); - selfdestruct(sender); + freeze(); + sender.transfer(address(this).balance); } /// the sender can extend the expiration at any time - function extend(uint256 newExpiration) external { + function extend(uint256 newExpiration) + external + notFrozen + { require(msg.sender == sender); require(newExpiration > expiration); @@ -377,9 +424,13 @@ The full contract /// if the timeout is reached without the recipient closing the channel, /// then the Ether is released back to the sender. - function claimTimeout() external { + function claimTimeout() + external + notFrozen + { require(block.timestamp >= expiration); - selfdestruct(sender); + freeze(); + sender.transfer(address(this).balance); } function isValidSignature(uint256 amount, bytes memory signature) @@ -388,14 +439,12 @@ The full contract returns (bool) { bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount))); - // check that the signature is from the payment sender return recoverSigner(message, signature) == sender; } /// All functions below this are just taken from the chapter /// 'creating and verifying signatures' chapter. - function splitSignature(bytes memory sig) internal pure @@ -411,7 +460,6 @@ The full contract // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } - return (v, r, s); } @@ -421,7 +469,6 @@ The full contract returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); - return ecrecover(message, v, r, s); } diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index 4a756029c2ef..c46cefd2fa34 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -337,7 +337,14 @@ userDefinableOperator: * Using directive to attach library functions and free functions to types. * Can occur within contracts and libraries and at the file level. */ -usingDirective: Using (identifierPath | (LBrace identifierPath (As userDefinableOperator)? (Comma identifierPath (As userDefinableOperator)?)* RBrace)) For (Mul | typeName) Global? Semicolon; +usingDirective: + Using ( + identifierPath + | (LBrace usingAliases (Comma usingAliases)* RBrace) + ) For (Mul | typeName) Global? Semicolon; + +usingAliases: identifierPath (As userDefinableOperator)?; + /** * A type name can be an elementary type, a function type, a mapping type, a user-defined type * (e.g. a contract or struct) or an array type. diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 2f048fe3c104..8d5b421d3a19 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -83,14 +83,20 @@ and runs it in a new container, passing the ``--help`` argument. docker run ethereum/solc:stable --help -For example, You can specify release build versions in the tag for the 0.5.4 release. +You can specify release build versions in the tag. For example: .. code-block:: bash - docker run ethereum/solc:0.5.4 --help + docker run ethereum/solc:stable --help + +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. 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. +local folder for input and output, and specify the contract to compile. For example: .. code-block:: bash @@ -183,7 +189,7 @@ If you need a specific version of Solidity you can install a Homebrew formula directly from Github. View -`solidity.rb commits on Github `_. +`solidity.rb commits on GitHub `_. Copy the commit hash of the version you want and check it out on your machine. @@ -224,8 +230,8 @@ out-of-the-box but it is also meant to be friendly to third-party tools: (via git, HTTPS, IPFS or just have it cached locally) and verify hashes of the binaries after downloading them, you do not have to use HTTPS for the binaries themselves. -The same binaries are in most cases available on the `Solidity release page on Github`_. The -difference is that we do not generally update old releases on the Github release page. This means +The same binaries are in most cases available on the `Solidity release page on GitHub`_. The +difference is that we do not generally update old releases on the GitHub release page. This means that we do not rename them if the naming convention changes and we do not add builds for platforms that were not supported at the time of release. This only happens in ``solc-bin``. @@ -301,7 +307,7 @@ This means that: .. _IPFS: https://ipfs.io .. _Swarm: https://swarm-gateways.net/bzz:/swarm.eth .. _solc-bin: https://github.com/ethereum/solc-bin/ -.. _Solidity release page on github: https://github.com/ethereum/solidity/releases +.. _Solidity release page on GitHub: https://github.com/ethereum/solidity/releases .. _sha3sum: https://github.com/maandree/sha3sum .. _keccak256() function from ethereumjs-util: https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/modules/_hash_.md#const-keccak256 .. _WebAssembly builds: https://emscripten.org/docs/compiling/WebAssembly.html @@ -461,11 +467,11 @@ you should fork Solidity and add your personal fork as a second remote: This method will result in a pre-release build leading to e.g. a flag being set in each bytecode produced by such a compiler. If you want to re-build a released Solidity compiler, then - please use the source tarball on the github release page: + please use the source tarball on the GitHub release page: https://github.com/ethereum/solidity/releases/download/v0.X.Y/solidity_0.X.Y.tar.gz - (not the "Source code" provided by github). + (not the "Source code" provided by GitHub). Command-Line Build ------------------ diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index 70896333c2bc..4588cb48358c 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -298,7 +298,7 @@ The following transformation steps are the main components: - SSA Transform - Common Subexpression Eliminator - Expression Simplifier -- Redundant Assign Eliminator +- Unused Assign Eliminator - Full Inliner .. _optimizer-steps: @@ -335,11 +335,11 @@ Abbreviation Full name ``T`` :ref:`literal-rematerialiser` ``L`` :ref:`load-resolver` ``M`` :ref:`loop-invariant-code-motion` -``r`` :ref:`redundant-assign-eliminator` ``m`` :ref:`rematerialiser` ``V`` :ref:`SSA-reverser` ``a`` :ref:`SSA-transform` ``t`` :ref:`structural-simplifier` +``r`` :ref:`unused-assign-eliminator` ``p`` :ref:`unused-function-parameter-pruner` ``S`` :ref:`unused-store-eliminator` ``u`` :ref:`unused-pruner` @@ -482,7 +482,7 @@ is transformed to } This eases the rest of the optimization process because we can ignore -the complicated scoping rules of the for loop initialisation block. +the complicated scoping rules of the for loop initialization block. .. _var-decl-initializer: @@ -652,7 +652,7 @@ the block, a new SSA variable will be created at the location where control flow this includes the beginning of loop post/body block and the location right after If/Switch/ForLoop/Block statement. -After this stage, the Redundant Assign Eliminator is recommended to remove the unnecessary +After this stage, the Unused Assign Eliminator is recommended to remove the unnecessary intermediate assignments. This stage provides best results if the Expression Splitter and the Common Subexpression Eliminator @@ -660,10 +660,10 @@ are run right before it, because then it does not generate excessive amounts of On the other hand, the Common Subexpression Eliminator could be more efficient if run after the SSA transform. -.. _redundant-assign-eliminator: +.. _unused-assign-eliminator: -RedundantAssignEliminator -^^^^^^^^^^^^^^^^^^^^^^^^^ +UnusedAssignEliminator +^^^^^^^^^^^^^^^^^^^^^^ The SSA transform always generates an assignment of the form ``a := a_i``, even though these might be unnecessary in many cases, like the following example: @@ -691,7 +691,7 @@ The SSA transform converts this snippet to the following: sstore(a_3, 1) } -The Redundant Assign Eliminator removes all the three assignments to ``a``, because +The Unused Assign Eliminator removes all the three assignments to ``a``, because the value of ``a`` is not used and thus turn this snippet into strict SSA form: @@ -704,7 +704,7 @@ snippet into strict SSA form: sstore(a_3, 1) } -Of course the intricate parts of determining whether an assignment is redundant or not +Of course the intricate parts of determining whether an assignment is unused or not are connected to joining control flow. The component works as follows in detail: @@ -829,7 +829,7 @@ current value if the value is an identifier. The combination of the two rules above allow to compute a local value numbering, which means that if two variables have the same value, one of them will always be unused. The Unused Pruner or the -Redundant Assign Eliminator will then be able to fully eliminate such +Unused Assign Eliminator will then be able to fully eliminate such variables. This step is especially efficient if the expression splitter is run @@ -1217,7 +1217,7 @@ The FullInliner replaces certain calls of certain functions by the function's body. This is not very helpful in most cases, because it just increases the code size but does not have a benefit. Furthermore, code is usually very expensive and we would often rather have shorter -code than more efficient code. In same cases, though, inlining a function +code than more efficient code. In some cases, though, inlining a function can have positive effects on subsequent optimizer steps. This is the case if one of the function arguments is a constant, for example. diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 48768cb8bfed..ded46814dc21 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -156,7 +156,7 @@ creates a public state variable, but it is a more complex datatype. The :ref:`mapping ` type maps addresses to :ref:`unsigned integers `. Mappings can be seen as `hash tables `_ which are -virtually initialised such that every possible key exists from the start and is mapped to a +virtually initialized such that every possible key exists from the start and is mapped to a value whose byte-representation is all zeros. However, it is neither possible to obtain a list of all keys of a mapping, nor a list of all values. Record what you added to the mapping, or use it in a context where this is not needed. Or @@ -304,7 +304,7 @@ These blocks form a linear sequence in time, and that is where the word "blockch Blocks are added to the chain at regular intervals, although these intervals may be subject to change in the future. For the most up-to-date information, it is recommended to monitor the network, for example, on `Etherscan `_. -As part of the "order selection mechanism" (which is called "mining") it may happen that +As part of the "order selection mechanism", which is called `attestation `_, it may happen that blocks are reverted from time to time, but only at the "tip" of the chain. The more blocks are added on top of a particular block, the less likely this block will be reverted. So it might be that your transactions are reverted and even removed from the blockchain, but the longer you wait, the less @@ -563,9 +563,23 @@ idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost. .. warning:: - From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a - deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behavior - as stated in `EIP-6049 `_. + From ``EVM >= Cancun`` onwards, ``selfdestruct`` will **only** send all Ether in the account to the given recipient and not destroy the contract. + However, when ``selfdestruct`` is called in the same transaction that creates the contract calling it, + the behaviour of ``selfdestruct`` before Cancun hardfork (i.e., ``EVM <= Shanghai``) is preserved and will destroy the current contract, + deleting any data, including storage keys, code and the account itself. + See `EIP-6780 `_ for more details. + + The new behaviour is the result of a network-wide change that affects all contracts present on + the Ethereum mainnet and testnets. + It is important to note that this change is dependent on the EVM version of the chain on which + the contract is deployed. + The ``--evm-version`` setting used when compiling the contract has no bearing on it. + + Also, note that the ``selfdestruct`` opcode has been deprecated in Solidity version 0.8.18, + as recommended by `EIP-6049 `_. + The deprecation is still in effect and the compiler will still emit warnings on its use. + 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:: Even if a contract is removed by ``selfdestruct``, it is still part of the diff --git a/docs/metadata.rst b/docs/metadata.rst index ede16a73fd8e..a44d9875388a 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -175,9 +175,9 @@ explanatory purposes. }, // Required: Compilation source files/source units, keys are file paths "sources": { - "destructible": { + "settable": { // Required (unless "url" is used): literal contents of the source file - "content": "contract destructible is owned { function destroy() { if (msg.sender == owner) selfdestruct(owner); } }", + "content": "contract settable is owned { uint256 private x = 0; function set(uint256 _x) public { if (msg.sender == owner) x = _x; } }", // Required: keccak256 hash of the source file "keccak256": "0x234..." }, diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index 0265fef3e689..f92958b90c02 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -115,10 +115,10 @@ in the same way as if it were tagged with ``@notice``. =============== ====================================================================================== ============================= Tag Context =============== ====================================================================================== ============================= -``@title`` A title that should describe the contract/interface contract, library, interface -``@author`` The name of the author contract, library, interface -``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event -``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event +``@title`` A title that should describe the contract/interface contract, library, interface, struct, enum +``@author`` The name of the author contract, library, interface, struct, enum +``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event, struct, enum +``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event, struct, enum ``@param`` Documents a parameter just like in Doxygen (must be followed by parameter name) function, event ``@return`` Documents the return variables of a contract's function function, public state variable ``@inheritdoc`` Copies all missing tags from the base function (must be followed by the contract name) function, public state variable diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index f8085b63de6f..dfdcf465198b 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -944,7 +944,7 @@ the arguments. |complex) | | +-----------------------------------+--------------------------------------+ |external functions without |BMC: Erase state knowledge and assume | -|implementation |result is nondeterminisc. | +|implementation |result is nondeterministic. | | |CHC: Nondeterministic summary. | | |Try to infer invariants that hold | | |after the call returns. | diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 427ede5ee3da..0ac890cb3478 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -662,10 +662,11 @@ Yes: return balanceOf[from]; } - function shutdown() public onlyOwner { - selfdestruct(owner); + function increment(uint x) public onlyOwner pure returns (uint) { + return x + 1; } + No: .. code-block:: solidity @@ -674,8 +675,8 @@ No: return balanceOf[from]; } - function shutdown() onlyOwner public { - selfdestruct(owner); + function increment(uint x) onlyOwner public pure returns (uint) { + return x + 1; } For long function declarations, it is recommended to drop each argument onto diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index d44d2fd70ad8..12fcb0b171d6 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -415,14 +415,6 @@ Members: .. note:: Prior to version 0.8.0, ``byte`` used to be an alias for ``bytes1``. -Dynamically-sized byte array ----------------------------- - -``bytes``: - Dynamically-sized byte array, see :ref:`arrays`. Not a value-type! -``string``: - Dynamically-sized UTF-8-encoded string, see :ref:`arrays`. Not a value-type! - .. index:: address, ! literal;address .. _address_literals: diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index ebd66d91cd37..fc582be07cff 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -338,9 +338,23 @@ Contract-related Furthermore, all functions of the current contract are callable directly including the current function. .. warning:: - From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a - deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behavior - as stated in `EIP-6049 `_. + From ``EVM >= Cancun`` onwards, ``selfdestruct`` will **only** send all Ether in the account to the given recipient and not destroy the contract. + However, when ``selfdestruct`` is called in the same transaction that creates the contract calling it, + the behaviour of ``selfdestruct`` before Cancun hardfork (i.e., ``EVM <= Shanghai``) is preserved and will destroy the current contract, + deleting any data, including storage keys, code and the account itself. + See `EIP-6780 `_ for more details. + + The new behaviour is the result of a network-wide change that affects all contracts present on + the Ethereum mainnet and testnets. + It is important to note that this change is dependent on the EVM version of the chain on which + the contract is deployed. + The ``--evm-version`` setting used when compiling the contract has no bearing on it. + + Also, note that the ``selfdestruct`` opcode has been deprecated in Solidity version 0.8.18, + as recommended by `EIP-6049 `_. + The deprecation is still in effect and the compiler will still emit warnings on its use. + 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. .. note:: Prior to version 0.5.0, there was a function called ``suicide`` with the same diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 97abbdba9df6..875c15b09d6d 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -174,9 +174,9 @@ at each version. Backward compatibility is not guaranteed between each version. - The block's base fee (`EIP-3198 `_ and `EIP-1559 `_) can be accessed via the global ``block.basefee`` or ``basefee()`` in inline assembly. - ``paris`` - Introduces ``prevrandao()`` and ``block.prevrandao``, and changes the semantics of the now deprecated ``block.difficulty``, disallowing ``difficulty()`` in inline assembly (see `EIP-4399 `_). -- ``shanghai`` (**default**) +- ``shanghai`` - Smaller code size and gas savings due to the introduction of ``push0`` (see `EIP-3855 `_). -- ``cancun`` +- ``cancun`` (**default**) - The block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) can be accessed via the global ``block.blobbasefee`` or ``blobbasefee()`` in inline assembly. - Introduces ``blobhash()`` in inline assembly and a corresponding global function to retrieve versioned hashes of blobs associated with the transaction (see `EIP-4844 `_). - Opcode ``mcopy`` is available in assembly (see `EIP-5656 `_). @@ -236,12 +236,12 @@ Input Description // `--allow-paths `. ] }, - "destructible": + "settable": { // Optional: keccak256 hash of the source file "keccak256": "0x234...", // Required (unless "urls" is used): literal contents of the source file - "content": "contract destructible is owned { function shutdown() { if (msg.sender == owner) selfdestruct(owner); } }" + "content": "contract settable is owned { uint256 private x = 0; function set(uint256 _x) public { if (msg.sender == owner) x = _x; } }" }, "myFile.sol_json.ast": { @@ -344,8 +344,8 @@ Input Description // Version of the EVM to compile for. // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris or shanghai (default) - "evmVersion": "shanghai", + // petersburg, istanbul, berlin, london, paris, shanghai or cancun (default) + "evmVersion": "cancun", // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. "viaIR": true, diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index b6e4d0006c57..067e230343d0 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -125,8 +124,10 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std: solRequire(!name.empty(), AssemblyImportException, "Member 'name' is empty."); SourceLocation location; - location.start = get(_json["begin"]); - location.end = get(_json["end"]); + if (_json.isMember("begin")) + location.start = get(_json["begin"]); + if (_json.isMember("end")) + location.end = get(_json["end"]); int srcIndex = getOrDefault(_json["source"], -1); size_t modifierDepth = static_cast(getOrDefault(_json["modifierDepth"], 0)); std::string value = getOrDefault(_json["value"], ""); @@ -180,7 +181,7 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std: if (c_instructions.count(name)) { - AssemblyItem item{c_instructions.at(name), location}; + AssemblyItem item{c_instructions.at(name), langutil::DebugData::create(location)}; if (!jumpType.empty()) { if (item.instruction() == Instruction::JUMP || item.instruction() == Instruction::JUMPI) @@ -555,7 +556,7 @@ std::pair, std::vector> Assembly::fromJSO result->importAssemblyItemsFromJSON(_json[".code"], _level == 0 ? parsedSourceList : _sourceList); - if (_json[".auxdata"]) + if (_json.isMember(".auxdata")) { solRequire(_json[".auxdata"].isString(), AssemblyImportException, "Optional member '.auxdata' is not a string."); result->m_auxiliaryData = fromHex(_json[".auxdata"].asString()); @@ -862,8 +863,8 @@ LinkerObject const& Assembly::assemble() const immutableReferencesBySub = linkerObject.immutableReferences; } for (size_t tagPos: sub->m_tagPositionsInBytecode) - if (tagPos != std::numeric_limits::max() && tagPos > subTagSize) - subTagSize = tagPos; + if (tagPos != std::numeric_limits::max() && numberEncodingSize(tagPos) > subTagSize) + subTagSize = numberEncodingSize(tagPos); } bool setsImmutables = false; @@ -891,6 +892,18 @@ LinkerObject const& Assembly::assemble() const std::multimap subRef; std::vector sizeRef; ///< Pointers to code locations where the size of the program is inserted unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode); + // Adjust bytesPerTag for references to sub assemblies. + for (AssemblyItem const& i: m_items) + if (i.type() == PushTag) + { + auto [subId, tagId] = i.splitForeignPushTag(); + if (subId == std::numeric_limits::max()) + continue; + assertThrow(subId < m_subs.size(), AssemblyException, "Invalid sub id"); + auto subTagPosition = m_subs[subId]->m_tagPositionsInBytecode.at(tagId); + assertThrow(subTagPosition != std::numeric_limits::max(), AssemblyException, "Reference to tag without position."); + bytesPerTag = std::max(bytesPerTag, numberEncodingSize(subTagPosition)); + } uint8_t tagPush = static_cast(pushInstruction(bytesPerTag)); unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1 + static_cast(m_auxiliaryData.size()); diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 93be394733ca..c2b3603c6352 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -24,7 +24,8 @@ #include #include -#include +#include +#include #include #include #include @@ -64,16 +65,16 @@ class AssemblyItem public: enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; - AssemblyItem(u256 _push, langutil::SourceLocation _location = langutil::SourceLocation()): - AssemblyItem(Push, std::move(_push), std::move(_location)) { } - AssemblyItem(Instruction _i, langutil::SourceLocation _location = langutil::SourceLocation()): + AssemblyItem(u256 _push, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): + AssemblyItem(Push, std::move(_push), std::move(_debugData)) { } + AssemblyItem(Instruction _i, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): m_type(Operation), m_instruction(_i), - m_location(std::move(_location)) + m_debugData(std::move(_debugData)) {} - AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::SourceLocation _location = langutil::SourceLocation()): + AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): m_type(_type), - m_location(std::move(_location)) + m_debugData(std::move(_debugData)) { if (m_type == Operation) m_instruction = Instruction(uint8_t(_data)); @@ -83,7 +84,8 @@ class AssemblyItem explicit AssemblyItem(bytes _verbatimData, size_t _arguments, size_t _returnVariables): m_type(VerbatimBytecode), m_instruction{}, - m_verbatimBytecode{{_arguments, _returnVariables, std::move(_verbatimData)}} + m_verbatimBytecode{{_arguments, _returnVariables, std::move(_verbatimData)}}, + m_debugData{langutil::DebugData::create()} {} AssemblyItem(AssemblyItem const&) = default; @@ -170,8 +172,29 @@ class AssemblyItem /// @returns true if the assembly item can be used in a functional context. bool canBeFunctional() const; - void setLocation(langutil::SourceLocation const& _location) { m_location = _location; } - langutil::SourceLocation const& location() const { return m_location; } + void setLocation(langutil::SourceLocation const& _location) + { + solAssert(m_debugData); + m_debugData = langutil::DebugData::create( + _location, + m_debugData->originLocation, + m_debugData->astID + ); + } + + langutil::SourceLocation const& location() const + { + solAssert(m_debugData); + return m_debugData->nativeLocation; + } + + void setDebugData(langutil::DebugData::ConstPtr _debugData) + { + solAssert(_debugData); + m_debugData = std::move(_debugData); + } + + langutil::DebugData::ConstPtr debugData() const { return m_debugData; } void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; } static std::optional parseJumpType(std::string const& _jumpType); @@ -196,7 +219,7 @@ class AssemblyItem /// If m_type == VerbatimBytecode, this holds number of arguments, number of /// return variables and verbatim bytecode. std::optional> m_verbatimBytecode; - langutil::SourceLocation m_location; + langutil::DebugData::ConstPtr m_debugData; JumpType m_jumpType = JumpType::Ordinary; /// Pushed value for operations with data to be determined during assembly stage, /// e.g. PushSubSize, PushTag, PushSub, etc. diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index de1e5a364aca..cb4eaebff3ce 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -29,6 +29,7 @@ #include #include +#include using namespace solidity; using namespace solidity::evmasm; @@ -57,9 +58,9 @@ std::vector CommonSubexpressionEliminator::getOptimizedItems() if (!m_state.stackElements().empty()) minHeight = std::min(minHeight, m_state.stackElements().begin()->first); for (int height = minHeight; height <= m_initialState.stackHeight(); ++height) - initialStackContents[height] = m_initialState.stackElement(height, SourceLocation()); + initialStackContents[height] = m_initialState.stackElement(height, langutil::DebugData::create()); for (int height = minHeight; height <= m_state.stackHeight(); ++height) - targetStackContents[height] = m_state.stackElement(height, SourceLocation()); + targetStackContents[height] = m_state.stackElement(height, langutil::DebugData::create()); AssemblyItems items = CSECodeGenerator(m_state.expressionClasses(), m_storeOperations).generateCode( m_initialState.sequenceNumber(), @@ -87,23 +88,24 @@ void CommonSubexpressionEliminator::optimizeBreakingItem() ExpressionClasses& classes = m_state.expressionClasses(); SourceLocation const& itemLocation = m_breakingItem->location(); + langutil::DebugData::ConstPtr debugData{langutil::DebugData::create(itemLocation)}; if (*m_breakingItem == AssemblyItem(Instruction::JUMPI)) { AssemblyItem::JumpType jumpType = m_breakingItem->getJumpType(); - Id condition = m_state.stackElement(m_state.stackHeight() - 1, itemLocation); + Id condition = m_state.stackElement(m_state.stackHeight() - 1, debugData); if (classes.knownNonZero(condition)) { - feedItem(AssemblyItem(Instruction::SWAP1, itemLocation), true); - feedItem(AssemblyItem(Instruction::POP, itemLocation), true); + feedItem(AssemblyItem(Instruction::SWAP1, debugData), true); + feedItem(AssemblyItem(Instruction::POP, debugData), true); - AssemblyItem item(Instruction::JUMP, itemLocation); + AssemblyItem item(Instruction::JUMP, debugData); item.setJumpType(jumpType); m_breakingItem = classes.storeItem(item); } else if (classes.knownZero(condition)) { - AssemblyItem it(Instruction::POP, itemLocation); + AssemblyItem it(Instruction::POP, debugData); feedItem(it, true); feedItem(it, true); m_breakingItem = nullptr; @@ -111,12 +113,12 @@ void CommonSubexpressionEliminator::optimizeBreakingItem() } else if (*m_breakingItem == AssemblyItem(Instruction::RETURN)) { - Id size = m_state.stackElement(m_state.stackHeight() - 1, itemLocation); + Id size = m_state.stackElement(m_state.stackHeight() - 1, debugData); if (classes.knownZero(size)) { - feedItem(AssemblyItem(Instruction::POP, itemLocation), true); - feedItem(AssemblyItem(Instruction::POP, itemLocation), true); - AssemblyItem item(Instruction::STOP, itemLocation); + feedItem(AssemblyItem(Instruction::POP, debugData), true); + feedItem(AssemblyItem(Instruction::POP, debugData), true); + AssemblyItem item(Instruction::STOP, debugData); m_breakingItem = classes.storeItem(item); } } @@ -181,16 +183,16 @@ AssemblyItems CSECodeGenerator::generateCode( assertThrow(!m_classPositions[targetItem.second].empty(), OptimizerException, ""); if (m_classPositions[targetItem.second].count(targetItem.first)) continue; - SourceLocation sourceLocation; + langutil::DebugData::ConstPtr debugData; if (m_expressionClasses.representative(targetItem.second).item) - sourceLocation = m_expressionClasses.representative(targetItem.second).item->location(); + debugData = m_expressionClasses.representative(targetItem.second).item->debugData(); int position = classElementPosition(targetItem.second); if (position < targetItem.first) // it is already at its target, we need another copy - appendDup(position, sourceLocation); + appendDup(position, debugData); else - appendOrRemoveSwap(position, sourceLocation); - appendOrRemoveSwap(targetItem.first, sourceLocation); + appendOrRemoveSwap(position, debugData); + appendOrRemoveSwap(targetItem.first, debugData); } // remove surplus elements @@ -263,7 +265,7 @@ void CSECodeGenerator::addDependencies(Id _c) case Instruction::KECCAK256: { Id length = expr.arguments.at(1); - AssemblyItem offsetInstr(Instruction::SUB, expr.item->location()); + AssemblyItem offsetInstr(Instruction::SUB, expr.item->debugData()); Id offsetToStart = m_expressionClasses.find(offsetInstr, {slot, slotToLoadFrom}); u256 const* o = m_expressionClasses.knownConstant(offsetToStart); u256 const* l = m_expressionClasses.knownConstant(length); @@ -334,7 +336,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) for (Id arg: arguments | ranges::views::reverse) generateClassElement(arg); - SourceLocation const& itemLocation = expr.item->location(); + langutil::DebugData::ConstPtr itemDebugData = expr.item->debugData(); // The arguments are somewhere on the stack now, so it remains to move them at the correct place. // This is quite difficult as sometimes, the values also have to removed in this process // (if canBeRemoved() returns true) and the two arguments can be equal. For now, this is @@ -342,42 +344,42 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) if (arguments.size() == 1) { if (canBeRemoved(arguments[0], _c)) - appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation); + appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData); else - appendDup(classElementPosition(arguments[0]), itemLocation); + appendDup(classElementPosition(arguments[0]), itemDebugData); } else if (arguments.size() == 2) { if (canBeRemoved(arguments[1], _c)) { - appendOrRemoveSwap(classElementPosition(arguments[1]), itemLocation); + appendOrRemoveSwap(classElementPosition(arguments[1]), itemDebugData); if (arguments[0] == arguments[1]) - appendDup(m_stackHeight, itemLocation); + appendDup(m_stackHeight, itemDebugData); else if (canBeRemoved(arguments[0], _c)) { - appendOrRemoveSwap(m_stackHeight - 1, itemLocation); - appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation); + appendOrRemoveSwap(m_stackHeight - 1, itemDebugData); + appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData); } else - appendDup(classElementPosition(arguments[0]), itemLocation); + appendDup(classElementPosition(arguments[0]), itemDebugData); } else { if (arguments[0] == arguments[1]) { - appendDup(classElementPosition(arguments[0]), itemLocation); - appendDup(m_stackHeight, itemLocation); + appendDup(classElementPosition(arguments[0]), itemDebugData); + appendDup(m_stackHeight, itemDebugData); } else if (canBeRemoved(arguments[0], _c)) { - appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation); - appendDup(classElementPosition(arguments[1]), itemLocation); - appendOrRemoveSwap(m_stackHeight - 1, itemLocation); + appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData); + appendDup(classElementPosition(arguments[1]), itemDebugData); + appendOrRemoveSwap(m_stackHeight - 1, itemDebugData); } else { - appendDup(classElementPosition(arguments[1]), itemLocation); - appendDup(classElementPosition(arguments[0]), itemLocation); + appendDup(classElementPosition(arguments[1]), itemDebugData); + appendDup(classElementPosition(arguments[0]), itemDebugData); } } } @@ -398,7 +400,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) !m_generatedItems.empty() && m_generatedItems.back() == AssemblyItem(Instruction::SWAP1)) // this will not append a swap but remove the one that is already there - appendOrRemoveSwap(m_stackHeight - 1, itemLocation); + appendOrRemoveSwap(m_stackHeight - 1, itemDebugData); for (size_t i = 0; i < arguments.size(); ++i) { m_classPositions[m_stack[m_stackHeight - static_cast(i)]].erase(m_stackHeight - static_cast(i)); @@ -467,18 +469,18 @@ bool CSECodeGenerator::removeStackTopIfPossible() return true; } -void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _location) +void CSECodeGenerator::appendDup(int _fromPosition, langutil::DebugData::ConstPtr _debugData) { assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); int instructionNum = 1 + m_stackHeight - _fromPosition; assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); - appendItem(AssemblyItem(dupInstruction(static_cast(instructionNum)), _location)); + appendItem(AssemblyItem(dupInstruction(static_cast(instructionNum)), std::move(_debugData))); m_stack[m_stackHeight] = m_stack[_fromPosition]; m_classPositions[m_stack[m_stackHeight]].insert(m_stackHeight); } -void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location) +void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, langutil::DebugData::ConstPtr _debugData) { assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); if (_fromPosition == m_stackHeight) @@ -486,7 +488,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation cons int instructionNum = m_stackHeight - _fromPosition; assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); - appendItem(AssemblyItem(swapInstruction(static_cast(instructionNum)), _location)); + appendItem(AssemblyItem(swapInstruction(static_cast(instructionNum)), std::move(_debugData))); if (m_stack[m_stackHeight] != m_stack[_fromPosition]) { diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index b0810a9a1dd0..3e963838a4cc 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -142,10 +142,10 @@ class CSECodeGenerator bool removeStackTopIfPossible(); /// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position. - void appendDup(int _fromPosition, langutil::SourceLocation const& _location); + void appendDup(int _fromPosition, langutil::DebugData::ConstPtr _debugData); /// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position. /// @note this might also remove the last item if it exactly the same swap instruction. - void appendOrRemoveSwap(int _fromPosition, langutil::SourceLocation const& _location); + void appendOrRemoveSwap(int _fromPosition, langutil::DebugData::ConstPtr _debugData); /// Appends the given assembly item. void appendItem(AssemblyItem const& _item); diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index b491fb00422f..139e263ba369 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -70,7 +70,7 @@ class ConstantOptimisationMethod virtual ~ConstantOptimisationMethod() = default; virtual bigint gasNeeded() const = 0; /// Executes the method, potentially appending to the assembly and returns a vector of - /// assembly items the constant should be relpaced with in one sweep. + /// assembly items the constant should be replaced with in one sweep. /// If the vector is empty, the constants will not be deleted. virtual AssemblyItems execute(Assembly& _assembly) const = 0; diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index 9d2927ed9ca4..5b73fb6d5b21 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -275,7 +275,7 @@ void ControlFlowGraph::gatherKnowledge() //@todo in the case of JUMPI, add knowledge about the condition to the state // (for both values of the condition) std::set tags = state->tagsInExpression( - state->stackElement(state->stackHeight(), langutil::SourceLocation{}) + state->stackElement(state->stackHeight(), langutil::DebugData::create()) ); state->feedItem(m_items.at(pc++)); diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index dd66eea32840..74de0ae3f402 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -33,6 +33,7 @@ #include #include #include +#include using namespace solidity; using namespace solidity::evmasm; @@ -134,11 +135,11 @@ void ExpressionClasses::forceEqual( m_expressions.insert(exp); } -ExpressionClasses::Id ExpressionClasses::newClass(SourceLocation const& _location) +ExpressionClasses::Id ExpressionClasses::newClass(langutil::DebugData::ConstPtr _debugData) { Expression exp; exp.id = static_cast(m_representatives.size()); - exp.item = storeItem(AssemblyItem(UndefinedItem, (u256(1) << 255) + exp.id, _location)); + exp.item = storeItem(AssemblyItem(UndefinedItem, (u256(1) << 255) + exp.id, std::move(_debugData))); m_representatives.push_back(exp); m_expressions.insert(exp); return exp.id; @@ -226,7 +227,7 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr) std::cout << "to " << match->action().toString() << std::endl; } - return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->location())); + return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->debugData())); } return std::numeric_limits::max(); diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h index 8d4159fc7be1..510302e4c70c 100644 --- a/libevmasm/ExpressionClasses.h +++ b/libevmasm/ExpressionClasses.h @@ -92,7 +92,7 @@ class ExpressionClasses void forceEqual(Id _id, AssemblyItem const& _item, Ids const& _arguments, bool _copyItem = true); /// @returns the id of a new class which is different to all other classes. - Id newClass(langutil::SourceLocation const& _location); + Id newClass(langutil::DebugData::ConstPtr _debugData); /// @returns true if the values of the given classes are known to be different (on every input). /// @note that this function might still return false for some different inputs. diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 33f8792164e0..866b5d66f2fa 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -310,18 +310,20 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer switch (instructionInfo(_instruction, _evmVersion).gasPriceTier) { - case Tier::Zero: return GasCosts::tier0Gas; - case Tier::Base: return GasCosts::tier1Gas; - case Tier::VeryLow: return GasCosts::tier2Gas; - case Tier::Low: return GasCosts::tier3Gas; - case Tier::Mid: return GasCosts::tier4Gas; - case Tier::High: return GasCosts::tier5Gas; - case Tier::Ext: return GasCosts::tier6Gas; - case Tier::WarmAccess: return GasCosts::warmStorageReadCost; - default: break; + case Tier::Zero: return GasCosts::tier0Gas; + case Tier::Base: return GasCosts::tier1Gas; + case Tier::VeryLow: return GasCosts::tier2Gas; + case Tier::Low: return GasCosts::tier3Gas; + case Tier::Mid: return GasCosts::tier4Gas; + case Tier::High: return GasCosts::tier5Gas; + case Tier::BlockHash: return GasCosts::tier6Gas; + case Tier::WarmAccess: return GasCosts::warmStorageReadCost; + + case Tier::Special: + case Tier::Invalid: + assertThrow(false, OptimizerException, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); } - assertThrow(false, OptimizerException, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); - return 0; + util::unreachable(); } u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersion _evmVersion) diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index ec1946644787..c91e0f0971c9 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -43,32 +43,34 @@ class KnownState; namespace GasCosts { + /// NOTE: The GAS_... constants referenced by comments are defined for each EVM version in the Execution Specs: + /// https://ethereum.github.io/execution-specs/autoapi/ethereum//vm/gas/index.html + static unsigned const stackLimit = 1024; - static unsigned const tier0Gas = 0; - static unsigned const tier1Gas = 2; - static unsigned const tier2Gas = 3; - static unsigned const tier3Gas = 5; - static unsigned const tier4Gas = 8; - static unsigned const tier5Gas = 10; - static unsigned const tier6Gas = 20; - static unsigned const tier7Gas = 0; - static unsigned const expGas = 10; + static unsigned const tier0Gas = 0; // GAS_ZERO (in Execution Specs) + static unsigned const tier1Gas = 2; // GAS_BASE + static unsigned const tier2Gas = 3; // GAS_VERY_LOW + static unsigned const tier3Gas = 5; // GAS_LOW / GAS_FAST_STEP + static unsigned const tier4Gas = 8; // GAS_MID + static unsigned const tier5Gas = 10; // GAS_HIGH + static unsigned const tier6Gas = 20; // GAS_BLOCK_HASH + static unsigned const expGas = 10; // GAS_EXPONENTIATION inline unsigned expByteGas(langutil::EVMVersion _evmVersion) { - return _evmVersion >= langutil::EVMVersion::spuriousDragon() ? 50 : 10; + return _evmVersion >= langutil::EVMVersion::spuriousDragon() ? 50 : 10; // GAS_EXPONENTIATION_PER_BYTE } - static unsigned const keccak256Gas = 30; - static unsigned const keccak256WordGas = 6; + static unsigned const keccak256Gas = 30; // GAS_KECCAK256 + static unsigned const keccak256WordGas = 6; // GAS_KECCAK256_WORD /// Corresponds to ACCESS_LIST_ADDRESS_COST from EIP-2930 static unsigned const accessListAddressCost = 2400; /// Corresponds to ACCESS_LIST_STORAGE_COST from EIP-2930 static unsigned const accessListStorageKeyCost = 1900; /// Corresponds to COLD_SLOAD_COST from EIP-2929 - static unsigned const coldSloadCost = 2100; + static unsigned const coldSloadCost = 2100; // GAS_COLD_SLOAD /// Corresponds to COLD_ACCOUNT_ACCESS_COST from EIP-2929 - static unsigned const coldAccountAccessCost = 2600; + static unsigned const coldAccountAccessCost = 2600; // GAS_COLD_ACCOUNT_ACCESS /// Corresponds to WARM_STORAGE_READ_COST from EIP-2929 - static unsigned const warmStorageReadCost = 100; + static unsigned const warmStorageReadCost = 100; // GAS_WARM_ACCESS inline unsigned sloadGas(langutil::EVMVersion _evmVersion) { if (_evmVersion >= langutil::EVMVersion::berlin()) @@ -81,7 +83,7 @@ namespace GasCosts return 50; } /// Corresponds to SSTORE_SET_GAS - static unsigned const sstoreSetGas = 20000; + static unsigned const sstoreSetGas = 20000; // GAS_STORAGE_SET /// Corresponds to SSTORE_RESET_GAS from EIP-2929 static unsigned const sstoreResetGas = 5000 - coldSloadCost; /// Corresponds to SSTORE_CLEARS_SCHEDULE from EIP-2200 @@ -130,11 +132,11 @@ namespace GasCosts else return 20; } - static unsigned const jumpdestGas = 1; - static unsigned const logGas = 375; - static unsigned const logDataGas = 8; - static unsigned const logTopicGas = 375; - static unsigned const createGas = 32000; + static unsigned const jumpdestGas = 1; // GAS_JUMPDEST + static unsigned const logGas = 375; // GAS_LOG + static unsigned const logDataGas = 8; // GAS_LOG_DATA + static unsigned const logTopicGas = 375; // GAS_LOG_TOPIC + static unsigned const createGas = 32000; // GAS_CREATE inline unsigned callGas(langutil::EVMVersion _evmVersion) { if (_evmVersion >= langutil::EVMVersion::berlin()) @@ -144,10 +146,10 @@ namespace GasCosts else return 40; } - static unsigned const callStipend = 2300; - static unsigned const callValueTransferGas = 9000; - static unsigned const callNewAccountGas = 25000; - inline unsigned selfdestructGas(langutil::EVMVersion _evmVersion) + static unsigned const callStipend = 2300; // GAS_CALL_STIPEND + static unsigned const callValueTransferGas = 9000; // GAS_CALL_VALUE + static unsigned const callNewAccountGas = 25000; // GAS_NEW_ACCOUNT / GAS_SELF_DESTRUCT_NEW_ACCOUNT + inline unsigned selfdestructGas(langutil::EVMVersion _evmVersion) // GAS_SELF_DESTRUCT { if (_evmVersion >= langutil::EVMVersion::berlin()) return coldAccountAccessCost; @@ -164,9 +166,9 @@ namespace GasCosts else return 24000; } - static unsigned const memoryGas = 3; + static unsigned const memoryGas = 3; // GAS_MEMORY / GAS_COPY / GAS_RETURN_DATA_COPY static unsigned const quadCoeffDiv = 512; - static unsigned const createDataGas = 200; + static unsigned const createDataGas = 200; // GAS_CODE_DEPOSIT static unsigned const txGas = 21000; static unsigned const txCreateGas = 53000; static unsigned const txDataZeroGas = 4; @@ -214,7 +216,7 @@ class GasMeter /// @returns an upper bound on the gas consumed by the given instruction and updates /// the state. - /// @param _inculdeExternalCosts if true, include costs caused by other contracts in calls. + /// @param _includeExternalCosts if true, include costs caused by other contracts in calls. GasConsumption estimateMax(AssemblyItem const& _item, bool _includeExternalCosts = true); u256 const& largestMemoryAccess() const { return m_largestMemoryAccess; } diff --git a/libevmasm/Inliner.cpp b/libevmasm/Inliner.cpp index ded5172ddc3a..67918e558bc3 100644 --- a/libevmasm/Inliner.cpp +++ b/libevmasm/Inliner.cpp @@ -44,7 +44,7 @@ using namespace solidity::evmasm; namespace { -/// @returns an estimation of the runtime gas cost of the AsssemblyItems in @a _itemRange. +/// @returns an estimation of the runtime gas cost of the AssemblyItems in @a _itemRange. template u256 executionCost(RangeType const& _itemRange, langutil::EVMVersion _evmVersion) { diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 90611d48cabd..bc2ad5e5cce8 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -227,7 +227,7 @@ static std::map const c_instructionInfo = { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } }, { Instruction::KECCAK256, { "KECCAK256", 0, 2, 1, true, Tier::Special } }, { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false, Tier::Base } }, - { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, Tier::Balance } }, + { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, Tier::Special } }, { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false, Tier::Base } }, { Instruction::CALLER, { "CALLER", 0, 0, 1, false, Tier::Base } }, { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false, Tier::Base } }, @@ -237,13 +237,13 @@ static std::map const c_instructionInfo = { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false, Tier::Base } }, { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true, Tier::VeryLow } }, { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false, Tier::Base } }, - { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, Tier::ExtCode } }, - { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::ExtCode } }, - { Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } }, - { Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } }, + { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, Tier::Special } }, + { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::Special } }, + { Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } }, + { Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } }, { Instruction::MCOPY, { "MCOPY", 0, 3, 0, true, Tier::VeryLow } }, - { Instruction::EXTCODEHASH, { "EXTCODEHASH", 0, 1, 1, false, Tier::Balance } }, - { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::Ext } }, + { Instruction::EXTCODEHASH, { "EXTCODEHASH", 0, 1, 1, false, Tier::Special } }, + { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::BlockHash } }, { Instruction::BLOBHASH, { "BLOBHASH", 0, 1, 1, false, Tier::VeryLow } }, { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } }, { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index bf6fb790edcf..5dd51f8d46d5 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -304,20 +304,23 @@ inline Instruction logInstruction(unsigned _number) return Instruction(unsigned(Instruction::LOG0) + _number); } +/// Gas price tiers representing static cost of an instruction. +/// Opcodes whose cost is dynamic or depends on EVM version should use the `Special` tier and need +/// dedicated logic in GasMeter (especially in estimateMax()). +/// The tiers loosely follow opcode groups originally defined in the Yellow Paper. enum class Tier { - Zero = 0, // 0, Zero - Base, // 2, Quick - VeryLow, // 3, Fastest - Low, // 5, Fast - Mid, // 8, Mid - High, // 10, Slow - Ext, // 20, Ext - WarmAccess, // 100, Warm Access - ExtCode, // 700, Extcode - Balance, // 400, Balance - Special, // multiparam or otherwise special - Invalid // Invalid. + // NOTE: Tiers should be ordered by cost, since we sometimes perform comparisons between them. + Zero = 0, // 0, Zero + Base, // 2, Quick + VeryLow, // 3, Fastest + Low, // 5, Fast + Mid, // 8, Mid + High, // 10, Slow + BlockHash, // 20 + WarmAccess, // 100, Warm Access + Special, // multiparam or otherwise special + Invalid, // Invalid. }; /// Information structure for a particular instruction. diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 91f798bf3890..3878ae0fdd75 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -27,6 +27,7 @@ #include #include +#include using namespace solidity; using namespace solidity::evmasm; @@ -114,7 +115,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool for (size_t i = 0; i < _item.returnValues(); ++i) setStackElement( m_stackHeight - static_cast(i), - m_expressionClasses->newClass(_item.location()) + m_expressionClasses->newClass(_item.debugData()) ); } else if (_item.type() != Operation) @@ -137,44 +138,44 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool m_stackHeight + 1, stackElement( m_stackHeight - static_cast(instruction) + static_cast(Instruction::DUP1), - _item.location() + _item.debugData() ) ); else if (SemanticInformation::isSwapInstruction(_item)) swapStackElements( m_stackHeight, m_stackHeight - 1 - static_cast(instruction) + static_cast(Instruction::SWAP1), - _item.location() + _item.debugData() ); else if (instruction != Instruction::POP) { std::vector arguments(static_cast(info.args)); for (size_t i = 0; i < static_cast(info.args); ++i) - arguments[i] = stackElement(m_stackHeight - static_cast(i), _item.location()); + arguments[i] = stackElement(m_stackHeight - static_cast(i), _item.debugData()); switch (_item.instruction()) { case Instruction::SSTORE: - op = storeInStorage(arguments[0], arguments[1], _item.location()); + op = storeInStorage(arguments[0], arguments[1], _item.debugData()); break; case Instruction::SLOAD: setStackElement( m_stackHeight + static_cast(_item.deposit()), - loadFromStorage(arguments[0], _item.location()) + loadFromStorage(arguments[0], _item.debugData()) ); break; case Instruction::MSTORE: - op = storeInMemory(arguments[0], arguments[1], _item.location()); + op = storeInMemory(arguments[0], arguments[1], _item.debugData()); break; case Instruction::MLOAD: setStackElement( m_stackHeight + static_cast(_item.deposit()), - loadFromMemory(arguments[0], _item.location()) + loadFromMemory(arguments[0], _item.debugData()) ); break; case Instruction::KECCAK256: setStackElement( m_stackHeight + static_cast(_item.deposit()), - applyKeccak256(arguments.at(0), arguments.at(1), _item.location()) + applyKeccak256(arguments.at(0), arguments.at(1), _item.debugData()) ); break; default: @@ -276,18 +277,18 @@ bool KnownState::operator==(KnownState const& _other) const return (thisIt == m_stackElements.cend() && otherIt == _other.m_stackElements.cend()); } -ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation const& _location) +ExpressionClasses::Id KnownState::stackElement(int _stackHeight, langutil::DebugData::ConstPtr _debugData) { if (m_stackElements.count(_stackHeight)) return m_stackElements.at(_stackHeight); // Stack element not found (not assigned yet), create new unknown equivalence class. return m_stackElements[_stackHeight] = - m_expressionClasses->find(AssemblyItem(UndefinedItem, _stackHeight, _location)); + m_expressionClasses->find(AssemblyItem(UndefinedItem, _stackHeight, std::move(_debugData))); } -KnownState::Id KnownState::relativeStackElement(int _stackOffset, SourceLocation const& _location) +KnownState::Id KnownState::relativeStackElement(int _stackOffset, langutil::DebugData::ConstPtr _debugData) { - return stackElement(m_stackHeight + _stackOffset, _location); + return stackElement(m_stackHeight + _stackOffset, std::move(_debugData)); } void KnownState::clearTagUnions() @@ -307,13 +308,13 @@ void KnownState::setStackElement(int _stackHeight, Id _class) void KnownState::swapStackElements( int _stackHeightA, int _stackHeightB, - SourceLocation const& _location + langutil::DebugData::ConstPtr _debugData ) { assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements."); // ensure they are created - stackElement(_stackHeightA, _location); - stackElement(_stackHeightB, _location); + stackElement(_stackHeightA, _debugData); + stackElement(_stackHeightB, _debugData); std::swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]); } @@ -321,7 +322,8 @@ void KnownState::swapStackElements( KnownState::StoreOperation KnownState::storeInStorage( Id _slot, Id _value, - SourceLocation const& _location) + langutil::DebugData::ConstPtr _debugData +) { if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value) // do not execute the storage if we know that the value is already there @@ -336,7 +338,7 @@ KnownState::StoreOperation KnownState::storeInStorage( storageContents.insert(storageItem); m_storageContent = std::move(storageContents); - AssemblyItem item(Instruction::SSTORE, _location); + AssemblyItem item(Instruction::SSTORE, std::move(_debugData)); Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber); StoreOperation operation{StoreOperation::Storage, _slot, m_sequenceNumber, id}; m_storageContent[_slot] = _value; @@ -346,16 +348,16 @@ KnownState::StoreOperation KnownState::storeInStorage( return operation; } -ExpressionClasses::Id KnownState::loadFromStorage(Id _slot, SourceLocation const& _location) +ExpressionClasses::Id KnownState::loadFromStorage(Id _slot, langutil::DebugData::ConstPtr _debugData) { if (m_storageContent.count(_slot)) return m_storageContent.at(_slot); - AssemblyItem item(Instruction::SLOAD, _location); + AssemblyItem item(Instruction::SLOAD, std::move(_debugData)); return m_storageContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber); } -KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, SourceLocation const& _location) +KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, langutil::DebugData::ConstPtr _debugData) { if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value) // do not execute the store if we know that the value is already there @@ -368,7 +370,7 @@ KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, Source memoryContents.insert(memoryItem); m_memoryContent = std::move(memoryContents); - AssemblyItem item(Instruction::MSTORE, _location); + AssemblyItem item(Instruction::MSTORE, std::move(_debugData)); Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber); StoreOperation operation{StoreOperation::Memory, _slot, m_sequenceNumber, id}; m_memoryContent[_slot] = _value; @@ -377,22 +379,22 @@ KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, Source return operation; } -ExpressionClasses::Id KnownState::loadFromMemory(Id _slot, SourceLocation const& _location) +ExpressionClasses::Id KnownState::loadFromMemory(Id _slot, langutil::DebugData::ConstPtr _debugData) { if (m_memoryContent.count(_slot)) return m_memoryContent.at(_slot); - AssemblyItem item(Instruction::MLOAD, _location); + AssemblyItem item(Instruction::MLOAD, std::move(_debugData)); return m_memoryContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber); } KnownState::Id KnownState::applyKeccak256( Id _start, Id _length, - SourceLocation const& _location + langutil::DebugData::ConstPtr _debugData ) { - AssemblyItem keccak256Item(Instruction::KECCAK256, _location); + AssemblyItem keccak256Item(Instruction::KECCAK256, _debugData); // Special logic if length is a short constant, otherwise we cannot tell. u256 const* l = m_expressionClasses->knownConstant(_length); // unknown or too large length @@ -403,10 +405,10 @@ KnownState::Id KnownState::applyKeccak256( for (unsigned i = 0; i < length; i += 32) { Id slot = m_expressionClasses->find( - AssemblyItem(Instruction::ADD, _location), + AssemblyItem(Instruction::ADD, _debugData), {_start, m_expressionClasses->find(u256(i))} ); - arguments.push_back(loadFromMemory(slot, _location)); + arguments.push_back(loadFromMemory(slot, _debugData)); } if (m_knownKeccak256Hashes.count({arguments, length})) return m_knownKeccak256Hashes.at({arguments, length}); @@ -418,7 +420,7 @@ KnownState::Id KnownState::applyKeccak256( for (Id a: arguments) data += toBigEndian(*m_expressionClasses->knownConstant(a)); data.resize(length); - v = m_expressionClasses->find(AssemblyItem(u256(util::keccak256(data)), _location)); + v = m_expressionClasses->find(AssemblyItem(u256(util::keccak256(data)), _debugData)); } else v = m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber); @@ -443,7 +445,7 @@ KnownState::Id KnownState::tagUnion(std::set _tags) return m_tagUnions.right.at(_tags); else { - Id id = m_expressionClasses->newClass(SourceLocation()); + Id id = m_expressionClasses->newClass(langutil::DebugData::create()); m_tagUnions.right.insert(make_pair(_tags, id)); return id; } diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h index 9cc22710fabe..79426c36f4dd 100644 --- a/libevmasm/KnownState.h +++ b/libevmasm/KnownState.h @@ -134,9 +134,9 @@ class KnownState /// Retrieves the current equivalence class for the given stack element (or generates a new /// one if it does not exist yet). - Id stackElement(int _stackHeight, langutil::SourceLocation const& _location); + Id stackElement(int _stackHeight, langutil::DebugData::ConstPtr _debugData); /// @returns the stackElement relative to the current stack height. - Id relativeStackElement(int _stackOffset, langutil::SourceLocation const& _location = {}); + Id relativeStackElement(int _stackOffset, langutil::DebugData::ConstPtr _debugData = {}); /// @returns its set of tags if the given expression class is a known tag union; returns a set /// containing the tag if it is a PushTag expression and the empty set otherwise. @@ -155,22 +155,22 @@ class KnownState /// Assigns a new equivalence class to the next sequence number of the given stack element. void setStackElement(int _stackHeight, Id _class); /// Swaps the given stack elements in their next sequence number. - void swapStackElements(int _stackHeightA, int _stackHeightB, langutil::SourceLocation const& _location); + void swapStackElements(int _stackHeightA, int _stackHeightB, langutil::DebugData::ConstPtr _debugData); /// Increments the sequence number, deletes all storage information that might be overwritten /// and stores the new value at the given slot. /// @returns the store operation, which might be invalid if storage was not modified - StoreOperation storeInStorage(Id _slot, Id _value, langutil::SourceLocation const& _location); + StoreOperation storeInStorage(Id _slot, Id _value,langutil::DebugData::ConstPtr _debugData); /// Retrieves the current value at the given slot in storage or creates a new special sload class. - Id loadFromStorage(Id _slot, langutil::SourceLocation const& _location); + Id loadFromStorage(Id _slot, langutil::DebugData::ConstPtr _debugData); /// Increments the sequence number, deletes all memory information that might be overwritten /// and stores the new value at the given slot. /// @returns the store operation, which might be invalid if memory was not modified - StoreOperation storeInMemory(Id _slot, Id _value, langutil::SourceLocation const& _location); + StoreOperation storeInMemory(Id _slot, Id _value, langutil::DebugData::ConstPtr _debugData); /// Retrieves the current value at the given slot in memory or creates a new special mload class. - Id loadFromMemory(Id _slot, langutil::SourceLocation const& _location); + Id loadFromMemory(Id _slot, langutil::DebugData::ConstPtr _debugData); /// Finds or creates a new expression that applies the Keccak-256 hash function to the contents in memory. - Id applyKeccak256(Id _start, Id _length, langutil::SourceLocation const& _location); + Id applyKeccak256(Id _start, Id _length, langutil::DebugData::ConstPtr _debugData); /// @returns a new or already used Id representing the given set of tags. Id tagUnion(std::set _tags); diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index e9231c0a56b0..257a3727c01d 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -119,7 +119,7 @@ struct OpPop: SimplePeepholeOptimizerMethod if (instructionInfo(instr, langutil::EVMVersion()).ret == 1 && !instructionInfo(instr, langutil::EVMVersion()).sideEffects) { for (int j = 0; j < instructionInfo(instr, langutil::EVMVersion()).args; j++) - *_out = {Instruction::POP, _op.location()}; + *_out = {Instruction::POP, _op.debugData()}; return true; } } @@ -142,13 +142,13 @@ struct OpStop: SimplePeepholeOptimizerMethod Instruction instr = _op.instruction(); if (!instructionInfo(instr, langutil::EVMVersion()).sideEffects) { - *_out = {Instruction::STOP, _op.location()}; + *_out = {Instruction::STOP, _op.debugData()}; return true; } } else if (_op.type() == Push) { - *_out = {Instruction::STOP, _op.location()}; + *_out = {Instruction::STOP, _op.debugData()}; return true; } } @@ -208,7 +208,7 @@ struct DoublePush: SimplePeepholeOptimizerMethod if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data()) { *_out = _push1; - *_out = {Instruction::DUP1, _push2.location()}; + *_out = {Instruction::DUP1, _push2.debugData()}; return true; } else @@ -334,7 +334,7 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod _jumpi == Instruction::JUMPI ) { - *_out = AssemblyItem(Instruction::SUB, _eq.location()); + *_out = AssemblyItem(Instruction::SUB, _eq.debugData()); *_out = _pushTag; *_out = _jumpi; return true; @@ -365,7 +365,7 @@ struct DoubleJump: SimplePeepholeOptimizerMethod _pushTag1.data() == _tag1.data() ) { - *_out = AssemblyItem(Instruction::ISZERO, _jumpi.location()); + *_out = AssemblyItem(Instruction::ISZERO, _jumpi.debugData()); *_out = _pushTag2; *_out = _jumpi; *_out = _tag1; @@ -393,7 +393,7 @@ struct JumpToNext: SimplePeepholeOptimizerMethod ) { if (_jump == Instruction::JUMPI) - *_out = AssemblyItem(Instruction::POP, _jump.location()); + *_out = AssemblyItem(Instruction::POP, _jump.debugData()); *_out = _tag; return true; } diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index f972e81c0060..dc672e02c412 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -87,8 +87,8 @@ std::vector SemanticInformation::readWriteOperat case Instruction::LOG4: { assertThrow(storage(_instruction) == Effect::None, OptimizerException, ""); - assertThrow(transientStorage(_instruction) == Effect::None, OptimizerException, ""); assertThrow(memory(_instruction) == Effect::Read, OptimizerException, ""); + assertThrow(transientStorage(_instruction) == Effect::None, OptimizerException, ""); Operation op; op.effect = memory(_instruction); op.location = Location::Memory; @@ -126,6 +126,7 @@ std::vector SemanticInformation::readWriteOperat { assertThrow(memory(_instruction) != Effect::None, OptimizerException, ""); assertThrow(storage(_instruction) == Effect::None, OptimizerException, ""); + assertThrow(transientStorage(_instruction) == Effect::None, OptimizerException, ""); Operation readOperation; readOperation.effect = Read; diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index ef2d68c7fdaa..5085b2c3c8f7 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -126,12 +126,12 @@ bool Pattern::matches(Expression const& _expr, ExpressionClasses const& _classes return true; } -AssemblyItem Pattern::toAssemblyItem(SourceLocation const& _location) const +AssemblyItem Pattern::toAssemblyItem(langutil::DebugData::ConstPtr _debugData) const { if (m_type == Operation) - return AssemblyItem(m_instruction, _location); + return AssemblyItem(m_instruction, std::move(_debugData)); else - return AssemblyItem(m_type, data(), _location); + return AssemblyItem(m_type, data(), std::move(_debugData)); } std::string Pattern::toString() const @@ -199,7 +199,7 @@ u256 const& Pattern::data() const return *m_data; } -ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location) +ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, langutil::DebugData::ConstPtr const& _debugData) { if (_pattern.matchGroup()) { @@ -209,10 +209,10 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation c else { hasId = false; - item = _pattern.toAssemblyItem(_location); + item = _pattern.toAssemblyItem(_debugData); } for (auto const& arg: _pattern.arguments()) - arguments.emplace_back(arg, _location); + arguments.emplace_back(arg, _debugData); } std::string ExpressionTemplate::toString() const diff --git a/libevmasm/SimplificationRules.h b/libevmasm/SimplificationRules.h index b3f8da3c7f7c..fadad3608492 100644 --- a/libevmasm/SimplificationRules.h +++ b/libevmasm/SimplificationRules.h @@ -111,7 +111,7 @@ class Pattern unsigned matchGroup() const { return m_matchGroup; } bool matches(Expression const& _expr, ExpressionClasses const& _classes) const; - AssemblyItem toAssemblyItem(langutil::SourceLocation const& _location) const; + AssemblyItem toAssemblyItem(langutil::DebugData::ConstPtr _debugData) const; std::vector arguments() const { return m_arguments; } /// @returns the id of the matched expression if this pattern is part of a match group. @@ -149,7 +149,7 @@ struct ExpressionTemplate { using Expression = ExpressionClasses::Expression; using Id = ExpressionClasses::Id; - explicit ExpressionTemplate(Pattern const& _pattern, langutil::SourceLocation const& _location); + explicit ExpressionTemplate(Pattern const& _pattern, langutil::DebugData::ConstPtr const& _debugData); std::string toString() const; bool hasId = false; /// Id of the matched expression, if available. diff --git a/liblangutil/CMakeLists.txt b/liblangutil/CMakeLists.txt index 53be57e79d58..054d01d91881 100644 --- a/liblangutil/CMakeLists.txt +++ b/liblangutil/CMakeLists.txt @@ -3,6 +3,7 @@ set(sources Common.h CharStream.cpp CharStream.h + DebugData.h DebugInfoSelection.cpp DebugInfoSelection.h ErrorReporter.cpp diff --git a/liblangutil/DebugData.h b/liblangutil/DebugData.h new file mode 100644 index 000000000000..70259bd039f3 --- /dev/null +++ b/liblangutil/DebugData.h @@ -0,0 +1,70 @@ +/* + 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::langutil +{ + +struct DebugData +{ + typedef typename std::shared_ptr ConstPtr; + + explicit DebugData( + langutil::SourceLocation _nativeLocation = {}, + langutil::SourceLocation _originLocation = {}, + std::optional _astID = {} + ): + nativeLocation(std::move(_nativeLocation)), + originLocation(std::move(_originLocation)), + astID(_astID) + {} + + static DebugData::ConstPtr create( + langutil::SourceLocation _nativeLocation, + langutil::SourceLocation _originLocation = {}, + std::optional _astID = {} + ) + { + return std::make_shared( + std::move(_nativeLocation), + std::move(_originLocation), + _astID + ); + } + + static DebugData::ConstPtr create() + { + static DebugData::ConstPtr emptyDebugData = create({}); + return emptyDebugData; + } + + /// Location in the Yul code. + langutil::SourceLocation nativeLocation; + /// Location in the original source that the Yul code was produced from. + /// Optional. Only present if the Yul source contains location annotations. + langutil::SourceLocation originLocation; + /// ID in the (Solidity) source AST. + std::optional astID; +}; + +} // namespace solidity::langutil diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 992933a898bf..58b54f3dcaa7 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -119,7 +119,7 @@ class EVMVersion: EVMVersion(Version _version): m_version(_version) {} - Version m_version = Version::Shanghai; + Version m_version = Version::Cancun; }; } diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp index 298e4f630f10..bf10483aa5a2 100644 --- a/liblangutil/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -23,6 +23,7 @@ #include #include +#include #include using namespace solidity; @@ -81,6 +82,16 @@ bool ErrorReporter::hasExcessiveErrors() const return m_errorCount > c_maxErrorsAllowed; } +bool ErrorReporter::hasError(ErrorId _errorId) const +{ + auto errorMatch = [&](std::shared_ptr const& error) -> bool { + solAssert(error.get()); + return error->errorId() == _errorId; + }; + + return ranges::find_if(m_errorList, errorMatch) != ranges::end(m_errorList); +} + bool ErrorReporter::checkForExcessiveErrors(Error::Type _type) { if (_type == Error::Type::Warning) diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index 6901e87b94f8..c78b6f498d2e 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -137,6 +137,9 @@ class ErrorReporter // @returns true if the maximum error count has been reached. bool hasExcessiveErrors() const; + /// @returns true if there is at least one occurrence of error + bool hasError(ErrorId _errorId) const; + class ErrorWatcher { public: diff --git a/liblangutil/Token.h b/liblangutil/Token.h index eb42ddb66fa0..e1c38f0c7332 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -279,6 +279,7 @@ namespace solidity::langutil K(Itself, "itself", 0) \ K(StaticAssert, "static_assert", 0) \ K(Builtin, "__builtin", 0) \ + K(ForAll, "forall", 0) \ T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \ \ /* Illegal token - not able to scan. */ \ diff --git a/libsmtutil/SolverInterface.h b/libsmtutil/SolverInterface.h index 4a21f18410b8..82f81113358a 100644 --- a/libsmtutil/SolverInterface.h +++ b/libsmtutil/SolverInterface.h @@ -124,7 +124,7 @@ class Expression explicit Expression(std::string _name, std::vector _arguments, SortPointer _sort): name(std::move(_name)), arguments(std::move(_arguments)), sort(std::move(_sort)) {} Expression(size_t _number): Expression(std::to_string(_number), {}, SortProvider::uintSort) {} - Expression(u256 const& _number): Expression(_number.str(), {}, SortProvider::sintSort) {} + Expression(u256 const& _number): Expression(_number.str(), {}, SortProvider::uintSort) {} Expression(s256 const& _number): Expression( _number >= 0 ? _number.str() : "-", _number >= 0 ? diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 94d0568118b9..642e87a53b3e 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -703,11 +703,34 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio solAssert(m_currentScope && m_scopes.count(m_currentScope), "No current scope."); solAssert(m_currentScope == _declaration.scope(), "Unexpected current scope."); - // Register declaration as inactive if we are in block scope. - bool inactive = - (dynamic_cast(m_currentScope) || dynamic_cast(m_currentScope)); + // Functions defined inside quantifiers should be visible in the scope containing the quantifier + // TODO: Turn it into a more generic mechanism in the same vein as Scopable and ScopeOpener if + // it turns out we need more special-casing here. + auto const* quantifier = dynamic_cast(m_currentScope); + auto const* functionDefinition = dynamic_cast(&_declaration); + if (quantifier && functionDefinition) + { + solAssert(quantifier->scope()); + solAssert( + // forall quantifiers cannot be used in block scope so the declaration is always active. + !dynamic_cast(quantifier->scope()) && + !dynamic_cast(quantifier->scope()) + ); - registerDeclaration(*m_scopes[m_currentScope], _declaration, nullptr, nullptr, inactive, m_errorReporter); + // 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 + // 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); + } + else + { + // Register declaration as inactive if we are in block scope. + bool inactive = + (dynamic_cast(m_currentScope) || dynamic_cast(m_currentScope)); + + registerDeclaration(*m_scopes[m_currentScope], _declaration, nullptr, nullptr, inactive, m_errorReporter); + } solAssert(_declaration.annotation().scope == m_currentScope, ""); solAssert(_declaration.annotation().contract == m_currentContract, ""); diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 96439684589b..502d0b2f8632 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -2627,6 +2627,38 @@ class Builtin: public Expression SourceLocation m_nameParameterLocation; }; +// TODO: NatSpec used on the quantifier should be recognized as applying to the function. +class ForAllQuantifier: public ASTNode, public Scopable, public ScopeOpener +{ +public: + ForAllQuantifier( + int64_t _id, + SourceLocation _location, + ASTPointer _typeVariableDeclarations, + ASTPointer _quantifiedDeclaration + ): + ASTNode(_id, std::move(_location)), + m_typeVariableDeclarations(std::move(_typeVariableDeclarations)), + m_quantifiedDeclaration(std::move(_quantifiedDeclaration)) + { + solAssert(m_typeVariableDeclarations); + solAssert(m_quantifiedDeclaration); + } + + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; + ForAllQuantifierAnnotation& annotation() const override { return initAnnotation(); } + + bool experimentalSolidityOnly() const override { return true; } + + ParameterList const& typeVariableDeclarations() const { return *m_typeVariableDeclarations; } + FunctionDefinition const& quantifiedDeclaration() const { return *m_quantifiedDeclaration; } + +private: + ASTPointer m_typeVariableDeclarations; + ASTPointer m_quantifiedDeclaration; +}; + /// @} } diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index e68614f464c0..f7519250a3a8 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -350,6 +350,10 @@ struct FunctionCallAnnotation: ExpressionAnnotation struct TypeClassDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocumentedAnnotation { }; + +struct ForAllQuantifierAnnotation: StatementAnnotation, ScopableAnnotation +{ +}; /// @} } diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h index f7c3d60237d7..b8a3a4ae0057 100644 --- a/libsolidity/ast/ASTForward.h +++ b/libsolidity/ast/ASTForward.h @@ -106,6 +106,7 @@ class TypeClassInstantiation; class TypeClassName; class TypeDefinition; class Builtin; +class ForAllQuantifier; /// @} class VariableScope; diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h index f9196d6b95c8..f985a449019a 100644 --- a/libsolidity/ast/ASTVisitor.h +++ b/libsolidity/ast/ASTVisitor.h @@ -116,6 +116,7 @@ class ASTVisitor virtual bool visit(TypeDefinition& _node) { return visitNode(_node); } virtual bool visit(TypeClassName& _node) { return visitNode(_node); } virtual bool visit(Builtin& _node) { return visitNode(_node); } + virtual bool visit(ForAllQuantifier& _node) { return visitNode(_node); } /// @} virtual void endVisit(SourceUnit& _node) { endVisitNode(_node); } @@ -180,6 +181,7 @@ class ASTVisitor virtual void endVisit(TypeDefinition& _node) { endVisitNode(_node); } virtual void endVisit(TypeClassName& _node) { endVisitNode(_node); } virtual void endVisit(Builtin& _node) { endVisitNode(_node); } + virtual void endVisit(ForAllQuantifier& _node) { endVisitNode(_node); } /// @} protected: @@ -266,6 +268,7 @@ class ASTConstVisitor virtual bool visit(TypeDefinition const& _node) { return visitNode(_node); } virtual bool visit(TypeClassName const& _node) { return visitNode(_node); } virtual bool visit(Builtin const& _node) { return visitNode(_node); } + virtual bool visit(ForAllQuantifier const& _node) { return visitNode(_node); } /// @} virtual void endVisit(SourceUnit const& _node) { endVisitNode(_node); } @@ -330,6 +333,7 @@ class ASTConstVisitor virtual void endVisit(TypeDefinition const& _node) { endVisitNode(_node); } virtual void endVisit(TypeClassName const& _node) { endVisitNode(_node); } virtual void endVisit(Builtin const& _node) { endVisitNode(_node); } + virtual void endVisit(ForAllQuantifier const& _node) { endVisitNode(_node); } /// @} protected: diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h index be9de64db7a2..55ebe2a78c61 100644 --- a/libsolidity/ast/AST_accept.h +++ b/libsolidity/ast/AST_accept.h @@ -1140,6 +1140,26 @@ void Builtin::accept(ASTConstVisitor& _visitor) const _visitor.visit(*this); _visitor.endVisit(*this); } + +void ForAllQuantifier::accept(ASTVisitor& _visitor) +{ + if (_visitor.visit(*this)) + { + m_typeVariableDeclarations->accept(_visitor); + m_quantifiedDeclaration->accept(_visitor); + } + _visitor.endVisit(*this); +} + +void ForAllQuantifier::accept(ASTConstVisitor& _visitor) const +{ + if (_visitor.visit(*this)) + { + m_typeVariableDeclarations->accept(_visitor); + m_quantifiedDeclaration->accept(_visitor); + } + _visitor.endVisit(*this); +} /// @} } diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 2b1efad4f60c..992630988761 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -88,34 +88,36 @@ std::string YulUtilFunctions::copyToMemoryFunction(bool _fromCalldata, bool _cle "_to_memory"s + (_cleanup ? "_with_cleanup"s : ""s); - return m_functionCollector.createFunction(functionName, [&]() { + return m_functionCollector.createFunction(functionName, [&](std::vector& _args, std::vector&) { + _args = {"src", "dst", "length"}; + if (_fromCalldata) - { return Whiskers(R"( - function (src, dst, length) { - calldatacopy(dst, src, length) - mstore(add(dst, length), 0) - } + calldatacopy(dst, src, length) + mstore(add(dst, length), 0) )") - ("functionName", functionName) ("cleanup", _cleanup) .render(); - } else { - return Whiskers(R"( - function (src, dst, length) { + if (m_evmVersion.hasMcopy()) + return Whiskers(R"( + mcopy(dst, src, length) + mstore(add(dst, length), 0) + )") + ("cleanup", _cleanup) + .render(); + else + return Whiskers(R"( let i := 0 for { } lt(i, length) { i := add(i, 32) } { mstore(add(dst, i), mload(add(src, i))) } mstore(add(dst, length), 0) - } - )") - ("functionName", functionName) - ("cleanup", _cleanup) - .render(); + )") + ("cleanup", _cleanup) + .render(); } }); } @@ -3866,7 +3868,7 @@ std::string YulUtilFunctions::cleanupFunction(Type const& _type) } case Type::Category::Enum: { - // Out of range enums cannot be truncated unambigiously and therefore it should be an error. + // Out of range enums cannot be truncated unambiguously and therefore it should be an error. templ("body", "cleaned := value " + validatorFunction(_type, false) + "(value)"); break; } diff --git a/libsolidity/experimental/analysis/TypeInference.cpp b/libsolidity/experimental/analysis/TypeInference.cpp index acfdaf89dbc1..b80aa1c425c7 100644 --- a/libsolidity/experimental/analysis/TypeInference.cpp +++ b/libsolidity/experimental/analysis/TypeInference.cpp @@ -33,6 +33,7 @@ #include #include + #include using namespace solidity; @@ -128,6 +129,19 @@ bool TypeInference::analyze(SourceUnit const& _sourceUnit) return !m_errorReporter.hasErrors(); } +bool TypeInference::visit(ForAllQuantifier const& _quantifier) +{ + solAssert(m_expressionContext == ExpressionContext::Term); + + { + ScopedSaveAndRestore expressionContext{m_expressionContext, ExpressionContext::Type}; + _quantifier.typeVariableDeclarations().accept(*this); + } + + _quantifier.quantifiedDeclaration().accept(*this); + return false; +} + bool TypeInference::visit(FunctionDefinition const& _functionDefinition) { solAssert(m_expressionContext == ExpressionContext::Term); @@ -166,6 +180,13 @@ bool TypeInference::visit(FunctionDefinition const& _functionDefinition) return false; } +void TypeInference::endVisit(FunctionDefinition const& _functionDefinition) +{ + solAssert(m_expressionContext == ExpressionContext::Term); + + m_env->fixTypeVars(TypeEnvironmentHelpers{*m_env}.typeVars(type(_functionDefinition))); +} + void TypeInference::endVisit(Return const& _return) { solAssert(m_currentFunctionType); @@ -204,6 +225,8 @@ bool TypeInference::visit(TypeClassDefinition const& _typeClassDefinition) solAssert(m_analysis.annotation(_typeClassDefinition).typeClass.has_value()); TypeClass typeClass = m_analysis.annotation(_typeClassDefinition).typeClass.value(); Type typeVar = m_typeSystem.typeClassVariable(typeClass); + unify(type(_typeClassDefinition.typeVariable()), typeVar, _typeClassDefinition.location()); + auto& typeMembersAnnotation = annotation().members[typeConstructor(&_typeClassDefinition)]; for (auto subNode: _typeClassDefinition.subNodes()) @@ -235,7 +258,6 @@ bool TypeInference::visit(TypeClassDefinition const& _typeClassDefinition) m_errorReporter.typeError(1807_error, _typeClassDefinition.location(), "Function " + functionName + " depends on invalid type variable."); } - unify(type(_typeClassDefinition.typeVariable()), m_typeSystem.freshTypeVariable({{typeClass}}), _typeClassDefinition.location()); for (auto instantiation: m_analysis.annotation(_typeClassDefinition).instantiations | ranges::views::values) // TODO: recursion-safety? Order of instantiation? instantiation->accept(*this); @@ -558,9 +580,11 @@ bool TypeInference::visit(Identifier const& _identifier) solAssert(false); break; case ExpressionContext::Type: - // TODO: register free type variable name! + m_errorReporter.typeError(5934_error, _identifier.location(), "Undeclared type variable."); + + // Assign it a fresh variable anyway just so that we can continue analysis. identifierAnnotation.type = m_typeSystem.freshTypeVariable({}); - return false; + break; case ExpressionContext::Sort: // TODO: error handling solAssert(false); @@ -621,45 +645,33 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation) if (instantiationAnnotation.type) return false; instantiationAnnotation.type = m_voidType; - std::optional typeClass = std::visit(util::GenericVisitor{ - [&](ASTPointer _typeClassName) -> std::optional { - if (auto const* typeClassDefinition = dynamic_cast(_typeClassName->annotation().referencedDeclaration)) - { - // visiting the type class will re-visit this instantiation - typeClassDefinition->accept(*this); - // TODO: more error handling? Should be covered by the visit above. - solAssert(m_analysis.annotation(*typeClassDefinition).typeClass.has_value()); - return m_analysis.annotation(*typeClassDefinition).typeClass.value(); - } - else - { - m_errorReporter.typeError(9817_error, _typeClassInstantiation.typeClass().location(), "Expected type class."); - return std::nullopt; - } + TypeClass typeClass = std::visit(util::GenericVisitor{ + [&](ASTPointer _typeClassName) -> TypeClass { + auto const* typeClassDefinition = dynamic_cast(_typeClassName->annotation().referencedDeclaration); + solAssert(typeClassDefinition); + + // visiting the type class will re-visit this instantiation + typeClassDefinition->accept(*this); + // TODO: more error handling? Should be covered by the visit above. + solAssert(m_analysis.annotation(*typeClassDefinition).typeClass.has_value()); + return m_analysis.annotation(*typeClassDefinition).typeClass.value(); }, - [&](Token _token) -> std::optional { - if (auto builtinClass = builtinClassFromToken(_token)) - if (auto typeClass = util::valueOrNullptr(annotation().builtinClasses, *builtinClass)) - return *typeClass; - m_errorReporter.typeError(2658_error, _typeClassInstantiation.location(), "Invalid type class name."); - return std::nullopt; + [&](Token _token) -> TypeClass { + std::optional builtinClass = builtinClassFromToken(_token); + solAssert(builtinClass.has_value()); + solAssert(annotation().builtinClasses.count(*builtinClass) != 0); + return annotation().builtinClasses.at(*builtinClass); } }, _typeClassInstantiation.typeClass().name()); - if (!typeClass) - return false; // TODO: _typeClassInstantiation.typeConstructor().accept(*this); ? auto typeConstructor = m_analysis.annotation(_typeClassInstantiation.typeConstructor()).typeConstructor; - if (!typeConstructor) - { - m_errorReporter.typeError(2138_error, _typeClassInstantiation.typeConstructor().location(), "Invalid type constructor."); - return false; - } + solAssert(typeConstructor); std::vector arguments; Arity arity{ {}, - *typeClass + typeClass }; { @@ -675,6 +687,7 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation) }) | ranges::to>; } } + m_env->fixTypeVars(arguments); Type instanceType{TypeConstant{*typeConstructor, arguments}}; @@ -692,14 +705,10 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation) if (auto error = m_typeSystem.instantiateClass(instanceType, arity)) m_errorReporter.typeError(5094_error, _typeClassInstantiation.location(), *error); - auto const& classFunctions = annotation().typeClassFunctions.at(*typeClass); + auto const& classFunctions = annotation().typeClassFunctions.at(typeClass); - TypeEnvironment newEnv = m_env->clone(); - if (!newEnv.unify(m_typeSystem.typeClassVariable(*typeClass), instanceType).empty()) - { - m_errorReporter.typeError(4686_error, _typeClassInstantiation.location(), "Unification of class and instance variable failed."); - return false; - } + solAssert(std::holds_alternative(m_typeSystem.typeClassVariable(typeClass))); + TypeVariable classVar = std::get(m_typeSystem.typeClassVariable(typeClass)); for (auto [name, classFunctionType]: classFunctions) { @@ -708,11 +717,22 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation) m_errorReporter.typeError(6948_error, _typeClassInstantiation.location(), "Missing function: " + name); continue; } + Type instantiatedClassFunctionType = TypeEnvironmentHelpers{*m_env}.substitute(classFunctionType, classVar, instanceType); + Type instanceFunctionType = functionTypes.at(name); functionTypes.erase(name); - if (!newEnv.typeEquals(instanceFunctionType, classFunctionType)) - m_errorReporter.typeError(7428_error, _typeClassInstantiation.location(), "Type mismatch for function " + name + " " + TypeEnvironmentHelpers{newEnv}.typeToString(instanceFunctionType) + " != " + TypeEnvironmentHelpers{newEnv}.typeToString(classFunctionType)); + if (!m_env->typeEquals(instanceFunctionType, instantiatedClassFunctionType)) + m_errorReporter.typeError( + 7428_error, + _typeClassInstantiation.location(), + fmt::format( + "Instantiation function '{}' does not match the declaration in the type class ({} != {}).", + name, + TypeEnvironmentHelpers{*m_env}.typeToString(instanceFunctionType), + TypeEnvironmentHelpers{*m_env}.typeToString(instantiatedClassFunctionType) + ) + ); } if (!functionTypes.empty()) @@ -772,12 +792,21 @@ bool TypeInference::visit(TypeDefinition const& _typeDefinition) return false; if (_typeDefinition.arguments()) + { + ScopedSaveAndRestore expressionContext{m_expressionContext, ExpressionContext::Type}; _typeDefinition.arguments()->accept(*this); + } std::vector arguments; if (_typeDefinition.arguments()) - for (size_t i = 0; i < _typeDefinition.arguments()->parameters().size(); ++i) - arguments.emplace_back(m_typeSystem.freshTypeVariable({})); + for (ASTPointer argumentDeclaration: _typeDefinition.arguments()->parameters()) + { + solAssert(argumentDeclaration); + Type typeVar = type(*argumentDeclaration); + solAssert(std::holds_alternative(typeVar)); + arguments.emplace_back(typeVar); + } + m_env->fixTypeVars(arguments); Type definedType = type(&_typeDefinition, arguments); if (arguments.empty()) @@ -803,6 +832,9 @@ bool TypeInference::visit(TypeDefinition const& _typeDefinition) solAssert(newlyInserted, fmt::format("Members of type '{}' are already defined.", m_typeSystem.constructorInfo(constructor).name)); if (underlyingType) { + // Undeclared type variables are not allowed in type definitions and we fixed all the declared ones. + solAssert(!TypeEnvironmentHelpers{*m_env}.hasGenericTypeVars(*underlyingType)); + members->second.emplace("abs", TypeMember{helper.functionType(*underlyingType, definedType)}); members->second.emplace("rep", TypeMember{helper.functionType(definedType, *underlyingType)}); } diff --git a/libsolidity/experimental/analysis/TypeInference.h b/libsolidity/experimental/analysis/TypeInference.h index df9d0610a9a5..093236799555 100644 --- a/libsolidity/experimental/analysis/TypeInference.h +++ b/libsolidity/experimental/analysis/TypeInference.h @@ -56,7 +56,9 @@ class TypeInference: public ASTConstVisitor void endVisit(VariableDeclarationStatement const& _variableDeclarationStatement) override; bool visit(VariableDeclaration const& _variableDeclaration) override; + bool visit(ForAllQuantifier const& _forAllQuantifier) override; bool visit(FunctionDefinition const& _functionDefinition) override; + void endVisit(FunctionDefinition const& _functionDefinition) override; bool visit(ParameterList const&) override { return true; } void endVisit(ParameterList const& _parameterList) override; bool visit(SourceUnit const&) override { return true; } diff --git a/libsolidity/experimental/ast/TypeSystem.cpp b/libsolidity/experimental/ast/TypeSystem.cpp index 680edce845f6..059054dcdbce 100644 --- a/libsolidity/experimental/ast/TypeSystem.cpp +++ b/libsolidity/experimental/ast/TypeSystem.cpp @@ -50,18 +50,21 @@ std::vector TypeEnvironment::unify(Type _a, [&](TypeVariable _left, TypeVariable _right) { if (_left.index() == _right.index()) solAssert(_left.sort() == _right.sort()); + else if (isFixedTypeVar(_left) && isFixedTypeVar(_right)) + unificationFailure(); + else if (isFixedTypeVar(_left)) + failures += instantiate(_right, _left); + else if (isFixedTypeVar(_right)) + failures += instantiate(_left, _right); + else if (_left.sort() <= _right.sort()) + failures += instantiate(_left, _right); + else if (_right.sort() <= _left.sort()) + failures += instantiate(_right, _left); else { - if (_left.sort() <= _right.sort()) - failures += instantiate(_left, _right); - else if (_right.sort() <= _left.sort()) - failures += instantiate(_right, _left); - else - { - Type newVar = m_typeSystem.freshVariable(_left.sort() + _right.sort()); - failures += instantiate(_left, newVar); - failures += instantiate(_right, newVar); - } + Type newVar = m_typeSystem.freshVariable(_left.sort() + _right.sort()); + failures += instantiate(_left, newVar); + failures += instantiate(_right, newVar); } }, [&](TypeVariable _var, auto) { @@ -112,6 +115,23 @@ bool TypeEnvironment::typeEquals(Type _lhs, Type _rhs) const }, resolve(_lhs), resolve(_rhs)); } + +bool TypeEnvironment::isFixedTypeVar(Type const& _typeVar) const +{ + return + std::holds_alternative(_typeVar) && + m_fixedTypeVariables.count(std::get(_typeVar).index()) != 0; +} + +void TypeEnvironment::fixTypeVars(std::vector const& _typeVars) +{ + for (Type const& typeVar: _typeVars) + { + solAssert(std::holds_alternative(typeVar)); + m_fixedTypeVariables.insert(std::get(typeVar).index()); + } +} + TypeEnvironment TypeEnvironment::clone() const { TypeEnvironment result{m_typeSystem}; @@ -263,6 +283,7 @@ TypeConstructor TypeSystem::declareTypeConstructor(std::string _name, std::strin std::generate_n(std::back_inserter(argumentSorts), _arguments, [&](){ return Sort{{primitiveClass(PrimitiveClass::Type)}}; }); std::vector argumentTypes; std::generate_n(std::back_inserter(argumentTypes), _arguments, [&](){ return freshVariable({}); }); + m_globalTypeEnvironment.fixTypeVars(argumentTypes); auto error = instantiateClass(type(constructor, argumentTypes), Arity{argumentSorts, primitiveClass(PrimitiveClass::Type)}); solAssert(!error, *error); } @@ -281,6 +302,8 @@ std::variant TypeSystem::declareTypeClass(std::string _n Type typeVariable = (_primitive ? freshVariable({{typeClass}}) : freshTypeVariable({{typeClass}})); solAssert(std::holds_alternative(typeVariable)); + m_globalTypeEnvironment.fixTypeVars({typeVariable}); + m_typeClasses.emplace_back(TypeClassInfo{ typeVariable, _name, diff --git a/libsolidity/experimental/ast/TypeSystem.h b/libsolidity/experimental/ast/TypeSystem.h index cac0feb81fe2..c3aa5001a16d 100644 --- a/libsolidity/experimental/ast/TypeSystem.h +++ b/libsolidity/experimental/ast/TypeSystem.h @@ -74,6 +74,9 @@ class TypeEnvironment TypeSystem& typeSystem() { return m_typeSystem; } TypeSystem const& typeSystem() const { return m_typeSystem; } + bool isFixedTypeVar(Type const& _typeVar) const; + void fixTypeVars(std::vector const& _typeVars); + private: TypeEnvironment(TypeEnvironment&& _env): m_typeSystem(_env.m_typeSystem), @@ -83,7 +86,15 @@ class TypeEnvironment [[nodiscard]] std::vector instantiate(TypeVariable _variable, Type _type); TypeSystem& m_typeSystem; + + /// For each @a TypeVariable (identified by its index) stores the type is has been successfully + /// unified with. Used for type resolution. Note that @a Type may itself be a type variable + /// or may contain type variables so resolution must be recursive. std::map m_typeVariables; + + /// Type variables marked as fixed free type variables (as opposed to generic type variables). + /// Identified by their indices. + std::set m_fixedTypeVariables; }; class TypeSystem diff --git a/libsolidity/experimental/ast/TypeSystemHelper.cpp b/libsolidity/experimental/ast/TypeSystemHelper.cpp index bc7dd4fcc35a..9ad18e1608bc 100644 --- a/libsolidity/experimental/ast/TypeSystemHelper.cpp +++ b/libsolidity/experimental/ast/TypeSystemHelper.cpp @@ -25,6 +25,7 @@ #include +#include #include #include #include @@ -287,9 +288,46 @@ std::vector TypeEnvironmentHelpers::typeVars(Type _type) con }; typeVarsImpl(_type, typeVarsImpl); return typeVars; +} + +bool TypeEnvironmentHelpers::hasGenericTypeVars(Type const& _type) const +{ + return ranges::any_of( + TypeEnvironmentHelpers{*this}.typeVars(_type), + [&](Type const& _maybeTypeVar) { + solAssert(std::holds_alternative(_maybeTypeVar)); + return !env.isFixedTypeVar(_maybeTypeVar); + } + ); } +experimental::Type TypeEnvironmentHelpers::substitute( + Type const& _type, + Type const& _partToReplace, + Type const& _replacement +) const +{ + using ranges::views::transform; + using ranges::to; + + if (env.typeEquals(_type, _partToReplace)) + return _replacement; + + auto recurse = [&](Type const& _t) { return substitute(_t, _partToReplace, _replacement); }; + + return visit(util::GenericVisitor{ + [&](TypeConstant const& _typeConstant) -> Type { + return TypeConstant{ + _typeConstant.constructor, + _typeConstant.arguments | transform(recurse) | to>, + }; + }, + [&](auto const& _type) -> Type { + return _type; + }, + }, env.resolve(_type)); +} std::string TypeSystemHelpers::sortToString(Sort _sort) const { @@ -381,7 +419,7 @@ std::string TypeEnvironmentHelpers::typeToString(Type const& _type) const while (index /= 26) varName += static_cast('a' + (index%26)); reverse(varName.begin(), varName.end()); - stream << '\'' << varName; + stream << (env.isFixedTypeVar(_type) ? "'" : "?") << varName; switch (_type.sort().classes.size()) { case 0: diff --git a/libsolidity/experimental/ast/TypeSystemHelper.h b/libsolidity/experimental/ast/TypeSystemHelper.h index fd55c1bf842e..ba395ace3a62 100644 --- a/libsolidity/experimental/ast/TypeSystemHelper.h +++ b/libsolidity/experimental/ast/TypeSystemHelper.h @@ -55,6 +55,10 @@ struct TypeEnvironmentHelpers std::string typeToString(Type const& _type) const; std::string canonicalTypeName(Type _type) const; std::vector typeVars(Type _type) const; + + bool hasGenericTypeVars(Type const& _type) const; + + Type substitute(Type const& _type, Type const& _partToReplace, Type const& _replacement) const; }; } diff --git a/libsolidity/formal/ModelCheckerSettings.h b/libsolidity/formal/ModelCheckerSettings.h index b645f7c3b6e7..0cfa370c40c8 100644 --- a/libsolidity/formal/ModelCheckerSettings.h +++ b/libsolidity/formal/ModelCheckerSettings.h @@ -175,7 +175,7 @@ struct ModelCheckerSettings bool showUnsupported = false; smtutil::SMTSolverChoice solvers = smtutil::SMTSolverChoice::Z3(); ModelCheckerTargets targets = ModelCheckerTargets::Default(); - std::optional timeout; + std::optional timeout; // in milliseconds bool operator!=(ModelCheckerSettings const& _other) const noexcept { return !(*this == _other); } bool operator==(ModelCheckerSettings const& _other) const noexcept diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index 58a5a5a3e721..01316d75ff43 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -316,11 +316,14 @@ std::string Predicate::formatSummaryCall( auto const& params = fun->parameters(); solAssert(params.size() == functionArgsCex.size(), ""); + bool paramNameInsteadOfValue = false; for (unsigned i = 0; i < params.size(); ++i) if (params.at(i) && functionArgsCex.at(i)) functionArgs.emplace_back(*functionArgsCex.at(i)); - else + else { + paramNameInsteadOfValue = true; functionArgs.emplace_back(params[i]->name()); + } std::string fName = fun->isConstructor() ? "constructor" : fun->isFallback() ? "fallback" : @@ -335,7 +338,11 @@ std::string Predicate::formatSummaryCall( solAssert(fun->annotation().contract, ""); prefix = fun->annotation().contract->name() + "."; } - return prefix + fName + "(" + boost::algorithm::join(functionArgs, ", ") + ")" + txModel; + + std::string summary = prefix + fName + "(" + boost::algorithm::join(functionArgs, ", ") + ")" + txModel; + if (paramNameInsteadOfValue) + summary += " -- counterexample incomplete; parameter name used instead of value"; + return summary; } std::vector> Predicate::summaryStateValues(std::vector const& _args) const diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 45b872b3d0d9..350e18bdcf77 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -476,7 +476,7 @@ smtutil::Expression zeroValue(frontend::Type const* _type) if (isSupportedType(*_type)) { if (isNumber(*_type)) - return 0; + return isSigned(_type) ? smtutil::Expression(s256(0)) : smtutil::Expression(static_cast(0)); if (isBool(*_type)) return smtutil::Expression(false); if (isArray(*_type) || isMapping(*_type)) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index a7268cd5b566..705687d85e7c 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -654,7 +655,12 @@ bool CompilerStack::analyzeLegacy(bool _noErrorsSoFar) // m_modelCheckerSettings is spread to engines and solver interfaces, // so we need to check whether the enabled ones are available before building the classes. if (m_modelCheckerSettings.engine.any()) + { m_modelCheckerSettings.solvers = ModelChecker::checkRequestedSolvers(m_modelCheckerSettings.solvers, m_errorReporter); + if (auto* universalCallback = m_readFile.target()) + if (m_modelCheckerSettings.solvers.eld) + universalCallback->smtCommand().setEldarica(m_modelCheckerSettings.timeout); + } ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile); modelChecker.checkRequestedSourcesAndContracts(allSources); @@ -736,7 +742,7 @@ bool CompilerStack::compile(State _stopAfter) { try { - if (m_viaIR || m_generateIR) + if ((m_generateEvmBytecode && m_viaIR) || m_generateIR) generateIR(*contract); if (m_generateEvmBytecode) { @@ -1480,15 +1486,8 @@ void CompilerStack::compileContract( solAssert(!m_viaIR, ""); bytes cborEncodedMetadata = createCBORMetadata(compiledContract, /* _forIR */ false); - try - { - // Run optimiser and compile the contract. - compiler->compileContract(_contract, _otherCompilers, cborEncodedMetadata); - } - catch(evmasm::OptimizerException const&) - { - solAssert(false, "Optimizer exception during compilation"); - } + // Run optimiser and compile the contract. + compiler->compileContract(_contract, _otherCompilers, cborEncodedMetadata); _otherCompilers[compiledContract.contract] = compiler; diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 92e0485b84a7..8ef36cb75189 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -37,7 +37,17 @@ using solidity::util::errinfo_comment; namespace solidity::frontend { -SMTSolverCommand::SMTSolverCommand(std::string _solverCmd) : m_solverCmd(_solverCmd) {} +void SMTSolverCommand::setEldarica(std::optional timeoutInMilliseconds) +{ + m_arguments.clear(); + m_solverCmd = "eld"; + if (timeoutInMilliseconds) + { + unsigned int timeoutInSeconds = timeoutInMilliseconds.value() / 1000u; + timeoutInSeconds = timeoutInSeconds == 0 ? 1 : timeoutInSeconds; + m_arguments.push_back("-t:" + std::to_string(timeoutInSeconds)); + } +} ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::string const& _query) { @@ -46,23 +56,30 @@ ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::stri if (_kind != ReadCallback::kindString(ReadCallback::Kind::SMTQuery)) solAssert(false, "SMTQuery callback used as callback kind " + _kind); + if (m_solverCmd.empty()) + return ReadCallback::Result{false, "No solver set."}; + auto tempDir = solidity::util::TemporaryDirectory("smt"); util::h256 queryHash = util::keccak256(_query); auto queryFileName = tempDir.path() / ("query_" + queryHash.hex() + ".smt2"); auto queryFile = boost::filesystem::ofstream(queryFileName); - queryFile << _query; + queryFile << _query << std::flush; auto eldBin = boost::process::search_path(m_solverCmd); if (eldBin.empty()) return ReadCallback::Result{false, m_solverCmd + " binary not found."}; + auto args = m_arguments; + args.push_back(queryFileName.string()); + boost::process::ipstream pipe; boost::process::child eld( eldBin, - queryFileName, - boost::process::std_out > pipe + args, + boost::process::std_out > pipe, + boost::process::std_err >boost::process::null ); std::vector data; diff --git a/libsolidity/interface/SMTSolverCommand.h b/libsolidity/interface/SMTSolverCommand.h index 56a6ba171055..1d1201e49062 100644 --- a/libsolidity/interface/SMTSolverCommand.h +++ b/libsolidity/interface/SMTSolverCommand.h @@ -28,8 +28,6 @@ namespace solidity::frontend class SMTSolverCommand { public: - SMTSolverCommand(std::string _solverCmd); - /// Calls an SMT solver with the given query. frontend::ReadCallback::Result solve(std::string const& _kind, std::string const& _query); @@ -38,9 +36,12 @@ class SMTSolverCommand return [this](std::string const& _kind, std::string const& _query) { return solve(_kind, _query); }; } + void setEldarica(std::optional timeoutInMilliseconds); + private: /// The name of the solver's binary. - std::string const m_solverCmd; + std::string m_solverCmd; + std::vector m_arguments; }; } diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index 93cc73f3a7e2..03bdc7f12bd2 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -59,7 +59,7 @@ class StandardCompiler /// Sets all input parameters according to @a _input which conforms to the standardized input /// format, performs compilation and returns a standardized output. Json::Value compile(Json::Value const& _input) noexcept; - /// Parses input as JSON and peforms the above processing steps, returning a serialized JSON + /// Parses input as JSON and performs the above processing steps, returning a serialized JSON /// output. Parsing errors are returned as regular errors. std::string compile(std::string const& _input) noexcept; diff --git a/libsolidity/interface/UniversalCallback.h b/libsolidity/interface/UniversalCallback.h index 3fe74c65e48f..ef5450a1c5e4 100644 --- a/libsolidity/interface/UniversalCallback.h +++ b/libsolidity/interface/UniversalCallback.h @@ -34,22 +34,27 @@ class UniversalCallback m_solver{_solver} {} + ReadCallback::Result operator()(std::string const& _kind, std::string const& _data) + { + if (_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile)) + if (!m_fileReader) + return ReadCallback::Result{false, "No import callback."}; + else + return m_fileReader->readFile(_kind, _data); + else if (_kind == ReadCallback::kindString(ReadCallback::Kind::SMTQuery)) + return m_solver.solve(_kind, _data); + solAssert(false, "Unknown callback kind."); + } + frontend::ReadCallback::Callback callback() { - return [this](std::string const& _kind, std::string const& _data) -> ReadCallback::Result { - if (_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile)) - if (!m_fileReader) - return ReadCallback::Result{false, "No import callback."}; - else - return m_fileReader->readFile(_kind, _data); - else if (_kind == ReadCallback::kindString(ReadCallback::Kind::SMTQuery)) - return m_solver.solve(_kind, _data); - solAssert(false, "Unknown callback kind."); - }; + return *this; } void resetImportCallback() { m_fileReader = nullptr; } + SMTSolverCommand& smtCommand() { return m_solver; } + private: FileReader* m_fileReader; SMTSolverCommand& m_solver; diff --git a/libsolidity/lsp/Transport.h b/libsolidity/lsp/Transport.h index 3e94e0398119..e3b03bcc7f2f 100644 --- a/libsolidity/lsp/Transport.h +++ b/libsolidity/lsp/Transport.h @@ -122,7 +122,7 @@ class Transport /// the message body from the transport line. virtual std::string readBytes(size_t _byteCount) = 0; - // Mimmicks std::getline() on this Transport API. + // Mimics std::getline() on this Transport API. virtual std::string getline() = 0; /// Writes the given payload @p _data to transport. diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 7bdb496b1fee..d13ae7a43859 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -137,6 +137,9 @@ ASTPointer Parser::parse(CharStream& _charStream) case Token::Function: nodes.push_back(parseFunctionDefinition(true)); break; + case Token::ForAll: + nodes.push_back(parseQuantifiedFunctionDefinition()); + break; case Token::Event: nodes.push_back(parseEventDefinition()); break; @@ -627,7 +630,28 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari return result; } -ASTPointer Parser::parseFunctionDefinition(bool _freeFunction, bool _allowBody) +ASTPointer Parser::parseQuantifiedFunctionDefinition() +{ + solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit); + RecursionGuard recursionGuard(*this); + ASTNodeFactory nodeFactory(*this); + + expectToken(Token::ForAll); + ASTPointer typeVariableDeclarations = parseParameterList(); + nodeFactory.markEndPosition(); + + if (m_scanner->currentToken() != Token::Function) + fatalParserError(5709_error, "Expected a function definition."); + + ASTPointer quantifiedFunction = parseFunctionDefinition(true /* _freeFunction */, true /* _allowBody */); + + return nodeFactory.createNode( + std::move(typeVariableDeclarations), + std::move(quantifiedFunction) + ); +} + +ASTPointer Parser::parseFunctionDefinition(bool _freeFunction, bool _allowBody) { RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index d4c48c7a638a..8f0868ac1172 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -102,7 +102,8 @@ class Parser: public langutil::ParserBase ASTPointer parseOverrideSpecifier(); StateMutability parseStateMutability(); FunctionHeaderParserResult parseFunctionHeader(bool _isStateVariable); - ASTPointer parseFunctionDefinition(bool _freeFunction = false, bool _allowBody = true); + ASTPointer parseQuantifiedFunctionDefinition(); + ASTPointer parseFunctionDefinition(bool _freeFunction = false, bool _allowBody = true); ASTPointer parseStructDefinition(); ASTPointer parseEnumDefinition(); ASTPointer parseUserDefinedValueTypeDefinition(); @@ -222,10 +223,10 @@ class Parser: public langutil::ParserBase /// or an expression; IndexAccessedPath parseIndexAccessedPath(); /// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]", - /// or an empty pointer if an empty @a _pathAndIncides has been supplied. + /// or an empty pointer if an empty @a _pathAndIndices has been supplied. ASTPointer typeNameFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); /// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]", - /// or an empty pointer if an empty @a _pathAndIncides has been supplied. + /// or an empty pointer if an empty @a _pathAndIndices has been supplied. ASTPointer expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); ASTPointer expectIdentifierToken(); diff --git a/libsolutil/Assertions.h b/libsolutil/Assertions.h index 6735cda166be..4879299bf011 100644 --- a/libsolutil/Assertions.h +++ b/libsolutil/Assertions.h @@ -28,6 +28,7 @@ #include #include +#include namespace solidity::util { @@ -69,7 +70,7 @@ inline std::string stringOrDefault(std::string _string, std::string _defaultStri { // NOTE: Putting this in a function rather than directly in a macro prevents the string from // being evaluated multiple times if it's not just a literal. - return (!_string.empty() ? _string : _defaultString); + return (!_string.empty() ? std::move(_string) : std::move(_defaultString)); } } diff --git a/libsolutil/cxx20.h b/libsolutil/cxx20.h index c65b0454b89c..a21a73e681af 100644 --- a/libsolutil/cxx20.h +++ b/libsolutil/cxx20.h @@ -15,6 +15,7 @@ along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 +#pragma once #include diff --git a/libyul/AST.h b/libyul/AST.h index 71419d807faa..4e3e92de3dad 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include @@ -36,77 +36,43 @@ namespace solidity::yul using Type = YulString; -struct DebugData -{ - explicit DebugData( - langutil::SourceLocation _nativeLocation, - langutil::SourceLocation _originLocation = {}, - std::optional _astID = {} - ): - nativeLocation(std::move(_nativeLocation)), - originLocation(std::move(_originLocation)), - astID(std::move(_astID)) - {} - - static std::shared_ptr create( - langutil::SourceLocation _nativeLocation = {}, - langutil::SourceLocation _originLocation = {}, - std::optional _astID = {} - ) - { - return std::make_shared( - std::move(_nativeLocation), - std::move(_originLocation), - std::move(_astID) - ); - } - - /// Location in the Yul code. - langutil::SourceLocation nativeLocation; - /// Location in the original source that the Yul code was produced from. - /// Optional. Only present if the Yul source contains location annotations. - langutil::SourceLocation originLocation; - /// ID in the (Solidity) source AST. - std::optional astID; -}; - -struct TypedName { std::shared_ptr debugData; YulString name; Type type; }; +struct TypedName { langutil::DebugData::ConstPtr debugData; YulString name; Type type; }; using TypedNameList = std::vector; /// Literal number or string (up to 32 bytes) enum class LiteralKind { Number, Boolean, String }; -struct Literal { std::shared_ptr debugData; LiteralKind kind; YulString value; Type type; }; +struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; YulString value; Type type; }; /// External / internal identifier or label reference -struct Identifier { std::shared_ptr debugData; YulString name; }; +struct Identifier { langutil::DebugData::ConstPtr debugData; YulString name; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// /// Multiple assignment ("x, y := f()"), where the left hand side variables each occupy /// 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 { std::shared_ptr debugData; std::vector variableNames; std::unique_ptr value; }; -struct FunctionCall { std::shared_ptr debugData; Identifier functionName; std::vector arguments; }; +struct Assignment { langutil::DebugData::ConstPtr debugData; std::vector variableNames; std::unique_ptr value; }; +struct FunctionCall { langutil::DebugData::ConstPtr debugData; Identifier functionName; std::vector arguments; }; /// Statement that contains only a single expression -struct ExpressionStatement { std::shared_ptr debugData; Expression expression; }; +struct ExpressionStatement { langutil::DebugData::ConstPtr debugData; Expression expression; }; /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted -struct VariableDeclaration { std::shared_ptr debugData; TypedNameList variables; std::unique_ptr value; }; +struct VariableDeclaration { langutil::DebugData::ConstPtr debugData; TypedNameList variables; std::unique_ptr value; }; /// Block that creates a scope (frees declared stack variables) -struct Block { std::shared_ptr debugData; std::vector statements; }; +struct Block { langutil::DebugData::ConstPtr debugData; std::vector statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") -struct FunctionDefinition { std::shared_ptr debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; +struct FunctionDefinition { langutil::DebugData::ConstPtr debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; /// Conditional execution without "else" part. -struct If { std::shared_ptr debugData; std::unique_ptr condition; Block body; }; +struct If { langutil::DebugData::ConstPtr debugData; std::unique_ptr condition; Block body; }; /// Switch case or default case -struct Case { std::shared_ptr debugData; std::unique_ptr value; Block body; }; +struct Case { langutil::DebugData::ConstPtr debugData; std::unique_ptr value; Block body; }; /// Switch statement -struct Switch { std::shared_ptr debugData; std::unique_ptr expression; std::vector cases; }; -struct ForLoop { std::shared_ptr debugData; Block pre; std::unique_ptr condition; Block post; Block body; }; +struct Switch { langutil::DebugData::ConstPtr debugData; std::unique_ptr expression; std::vector cases; }; +struct ForLoop { langutil::DebugData::ConstPtr debugData; Block pre; std::unique_ptr condition; Block post; Block body; }; /// Break statement (valid within for loop) -struct Break { std::shared_ptr debugData; }; +struct Break { langutil::DebugData::ConstPtr debugData; }; /// Continue statement (valid within for loop) -struct Continue { std::shared_ptr debugData; }; +struct Continue { langutil::DebugData::ConstPtr debugData; }; /// Leave statement (valid within function) -struct Leave { std::shared_ptr debugData; }; +struct Leave { langutil::DebugData::ConstPtr debugData; }; /// Extracts the IR source location from a Yul node. template inline langutil::SourceLocation nativeLocationOf(T const& _node) @@ -133,13 +99,13 @@ template inline langutil::SourceLocation originLocationOf(std::v } /// Extracts the debug data from a Yul node. -template inline std::shared_ptr debugDataOf(T const& _node) +template inline langutil::DebugData::ConstPtr debugDataOf(T const& _node) { return _node.debugData; } /// Extracts the debug data from a Yul node. -template inline std::shared_ptr debugDataOf(std::variant const& _node) +template inline langutil::DebugData::ConstPtr debugDataOf(std::variant const& _node) { return std::visit([](auto const& _arg) { return debugDataOf(_arg); }, _node); } diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index 0e61c6ca1263..a4dc5be3f8eb 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -28,7 +28,6 @@ namespace solidity::yul { -struct DebugData; enum class LiteralKind; struct Literal; struct Label; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index cc811f75d182..1972d2674516 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -324,7 +324,8 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) ); else if ( m_evmVersion.supportsTransientStorage() && - _funCall.functionName.name == "tstore"_yulstring + _funCall.functionName.name == "tstore"_yulstring && + !m_errorReporter.hasError({2394}) ) m_errorReporter.warning( 2394_error, @@ -751,14 +752,11 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio else if (_instr == evmasm::Instruction::BLOBBASEFEE && !m_evmVersion.hasBlobBaseFee()) errorForVM(6679_error, "only available for Cancun-compatible"); else if (_instr == evmasm::Instruction::BLOBHASH && !m_evmVersion.hasBlobHash()) - // TODO: Change this assertion to an error, similar to the ones above, when Cancun becomes the default EVM version. - yulAssert(false); + errorForVM(8314_error, "only available for Cancun-compatible"); else if (_instr == evmasm::Instruction::MCOPY && !m_evmVersion.hasMcopy()) - // TODO: Change this assertion to an error, similar to the ones above, when Cancun becomes the default EVM version. - yulAssert(false); + errorForVM(7755_error, "only available for Cancun-compatible"); else if ((_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD) && !m_evmVersion.supportsTransientStorage()) - // TODO: Change this assertion to an error, similar to the ones above, when Cancun becomes the default EVM version. - yulAssert(false); + errorForVM(6243_error, "only available for Cancun-compatible"); else if (_instr == evmasm::Instruction::PC) m_errorReporter.error( 2450_error, diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 5d3ec84a4b97..3635b096af99 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -59,7 +59,7 @@ std::optional toInt(std::string const& _value) } -std::shared_ptr Parser::createDebugData() const +langutil::DebugData::ConstPtr Parser::createDebugData() const { switch (m_useSourceLocationFrom) { @@ -74,7 +74,7 @@ std::shared_ptr Parser::createDebugData() const } void Parser::updateLocationEndFrom( - std::shared_ptr& _debugData, + langutil::DebugData::ConstPtr& _debugData, SourceLocation const& _location ) const { @@ -286,7 +286,7 @@ std::optional>> Parser::parseASTI Block Parser::parseBlock() { RecursionGuard recursionGuard(*this); - Block block = createWithLocation(); + Block block = createWithDebugData(); expectToken(Token::LBrace); while (currentToken() != Token::RBrace) block.statements.emplace_back(parseStatement()); @@ -308,7 +308,7 @@ Statement Parser::parseStatement() return parseBlock(); case Token::If: { - If _if = createWithLocation(); + If _if = createWithDebugData(); advance(); _if.condition = std::make_unique(parseExpression()); _if.body = parseBlock(); @@ -317,7 +317,7 @@ Statement Parser::parseStatement() } case Token::Switch: { - Switch _switch = createWithLocation(); + Switch _switch = createWithDebugData(); advance(); _switch.expression = std::make_unique(parseExpression()); while (currentToken() == Token::Case) @@ -337,21 +337,21 @@ Statement Parser::parseStatement() return parseForLoop(); case Token::Break: { - Statement stmt{createWithLocation()}; + Statement stmt{createWithDebugData()}; checkBreakContinuePosition("break"); advance(); return stmt; } case Token::Continue: { - Statement stmt{createWithLocation()}; + Statement stmt{createWithDebugData()}; checkBreakContinuePosition("continue"); advance(); return stmt; } case Token::Leave: { - Statement stmt{createWithLocation()}; + Statement stmt{createWithDebugData()}; if (!m_insideFunction) m_errorReporter.syntaxError(8149_error, currentLocation(), "Keyword \"leave\" can only be used inside a function."); advance(); @@ -428,7 +428,7 @@ Statement Parser::parseStatement() Case Parser::parseCase() { RecursionGuard recursionGuard(*this); - Case _case = createWithLocation(); + Case _case = createWithDebugData(); if (currentToken() == Token::Default) advance(); else if (currentToken() == Token::Case) @@ -452,7 +452,7 @@ ForLoop Parser::parseForLoop() ForLoopComponent outerForLoopComponent = m_currentForLoopComponent; - ForLoop forLoop = createWithLocation(); + ForLoop forLoop = createWithDebugData(); expectToken(Token::For); m_currentForLoopComponent = ForLoopComponent::ForLoopPre; forLoop.pre = parseBlock(); @@ -559,7 +559,7 @@ std::variant Parser::parseLiteralOrIdentifier() VariableDeclaration Parser::parseVariableDeclaration() { RecursionGuard recursionGuard(*this); - VariableDeclaration varDecl = createWithLocation(); + VariableDeclaration varDecl = createWithDebugData(); expectToken(Token::Let); while (true) { @@ -595,7 +595,7 @@ FunctionDefinition Parser::parseFunctionDefinition() ForLoopComponent outerForLoopComponent = m_currentForLoopComponent; m_currentForLoopComponent = ForLoopComponent::None; - FunctionDefinition funDef = createWithLocation(); + FunctionDefinition funDef = createWithDebugData(); expectToken(Token::Function); funDef.name = expectAsmIdentifier(); expectToken(Token::LParen); @@ -657,7 +657,7 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) TypedName Parser::parseTypedName() { RecursionGuard recursionGuard(*this); - TypedName typedName = createWithLocation(); + TypedName typedName = createWithDebugData(); typedName.name = expectAsmIdentifier(); if (currentToken() == Token::Colon) { diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index da4f09ed2212..3e0af66acc10 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -118,15 +118,15 @@ class Parser: public langutil::ParserBase ); /// Creates a DebugData object with the correct source location set. - std::shared_ptr createDebugData() const; + langutil::DebugData::ConstPtr createDebugData() const; void updateLocationEndFrom( - std::shared_ptr& _debugData, + langutil::DebugData::ConstPtr& _debugData, langutil::SourceLocation const& _location ) const; - /// Creates an inline assembly node with the current source location. - template T createWithLocation() const + /// Creates an inline assembly node with the current debug data. + template T createWithDebugData() const { T r; r.debugData = createDebugData(); diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index bee213f8cafb..b27af037131b 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -305,7 +305,7 @@ std::string AsmPrinter::formatSourceLocation( return sourceLocation + (solidityCodeSnippet.empty() ? "" : " ") + solidityCodeSnippet; } -std::string AsmPrinter::formatDebugData(std::shared_ptr const& _debugData, bool _statement) +std::string AsmPrinter::formatDebugData(langutil::DebugData::ConstPtr const& _debugData, bool _statement) { if (!_debugData || m_debugInfoSelection.none()) return ""; diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 7c67c14acfdc..d3f80b9a09d5 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -30,7 +30,7 @@ #include #include -#include +#include #include @@ -93,7 +93,7 @@ class AsmPrinter private: std::string formatTypedName(TypedName _variable); std::string appendTypeName(YulString _type, bool _isBoolLiteral = false) const; - std::string formatDebugData(std::shared_ptr const& _debugData, bool _statement); + std::string formatDebugData(langutil::DebugData::ConstPtr const& _debugData, bool _statement); template std::string formatDebugData(T const& _node) { diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index a60d2b2f5601..280f50bf9b97 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include @@ -74,7 +74,7 @@ class RepresentationFinder RepresentationFinder( EVMDialect const& _dialect, GasMeter const& _meter, - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, std::map& _cache ): m_dialect(_dialect), @@ -100,7 +100,7 @@ class RepresentationFinder EVMDialect const& m_dialect; GasMeter const& m_meter; - std::shared_ptr m_debugData; + langutil::DebugData::ConstPtr m_debugData; /// Counter for the complexity of optimization, will stop when it reaches zero. size_t m_maxSteps = 10000; std::map& m_cache; diff --git a/libyul/backends/evm/ControlFlowGraph.h b/libyul/backends/evm/ControlFlowGraph.h index 853a9e705dc2..980787c52297 100644 --- a/libyul/backends/evm/ControlFlowGraph.h +++ b/libyul/backends/evm/ControlFlowGraph.h @@ -76,7 +76,7 @@ struct FunctionReturnLabelSlot struct VariableSlot { std::reference_wrapper variable; - std::shared_ptr debugData{}; + langutil::DebugData::ConstPtr debugData{}; bool operator==(VariableSlot const& _rhs) const { return &variable.get() == &_rhs.variable.get(); } bool operator<(VariableSlot const& _rhs) const { return &variable.get() < &_rhs.variable.get(); } static constexpr bool canBeFreelyGenerated = false; @@ -85,7 +85,7 @@ struct VariableSlot struct LiteralSlot { u256 value; - std::shared_ptr debugData{}; + langutil::DebugData::ConstPtr debugData{}; bool operator==(LiteralSlot const& _rhs) const { return value == _rhs.value; } bool operator<(LiteralSlot const& _rhs) const { return value < _rhs.value; } static constexpr bool canBeFreelyGenerated = true; @@ -132,7 +132,7 @@ struct CFG struct BuiltinCall { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; std::reference_wrapper builtin; std::reference_wrapper functionCall; /// Number of proper arguments with a position on the stack, excluding literal arguments. @@ -142,7 +142,7 @@ struct CFG }; struct FunctionCall { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; std::reference_wrapper function; std::reference_wrapper functionCall; /// True, if the call is recursive, i.e. entering the function involves a control flow path (potentially involving @@ -153,7 +153,7 @@ struct CFG }; struct Assignment { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; /// The variables being assigned to also occur as ``output`` in the ``Operation`` containing /// the assignment, but are also stored here for convenience. std::vector variables; @@ -176,25 +176,25 @@ struct CFG struct MainExit {}; struct ConditionalJump { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; StackSlot condition; BasicBlock* nonZero = nullptr; BasicBlock* zero = nullptr; }; struct Jump { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; BasicBlock* target = nullptr; /// The only backwards jumps are jumps from loop post to loop condition. bool backwards = false; }; struct FunctionReturn { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; CFG::FunctionInfo* info = nullptr; }; struct Terminated {}; - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; std::vector entries; std::vector operations; /// True, if the block is the beginning of a disconnected subgraph. That is, if no block that is reachable @@ -210,7 +210,7 @@ struct CFG struct FunctionInfo { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; Scope::Function const& function; FunctionDefinition const& functionDefinition; BasicBlock* entry = nullptr; @@ -238,7 +238,7 @@ struct CFG /// the switch case literals when transforming the control flow of a switch to a sequence of conditional jumps. std::list ghostCalls; - BasicBlock& makeBlock(std::shared_ptr _debugData) + BasicBlock& makeBlock(langutil::DebugData::ConstPtr _debugData) { return blocks.emplace_back(BasicBlock{std::move(_debugData), {}, {}}); } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 9a0a73b35fbf..4b0da1e80d91 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -333,7 +333,7 @@ void ControlFlowGraphBuilder::operator()(If const& _if) void ControlFlowGraphBuilder::operator()(Switch const& _switch) { yulAssert(m_currentBlock, ""); - std::shared_ptr preSwitchDebugData = debugDataOf(_switch); + langutil::DebugData::ConstPtr preSwitchDebugData = debugDataOf(_switch); auto ghostVariableId = m_graph.ghostVariables.size(); YulString ghostVariableName("GHOST[" + std::to_string(ghostVariableId) + "]"); @@ -393,7 +393,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) void ControlFlowGraphBuilder::operator()(ForLoop const& _loop) { - std::shared_ptr preLoopDebugData = debugDataOf(_loop); + langutil::DebugData::ConstPtr preLoopDebugData = debugDataOf(_loop); ScopedSaveAndRestore scopeRestore(m_scope, m_info.scopes.at(&_loop.pre).get()); (*this)(_loop.pre); @@ -608,7 +608,7 @@ Scope::Variable const& ControlFlowGraphBuilder::lookupVariable(YulString _name) } void ControlFlowGraphBuilder::makeConditionalJump( - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, StackSlot _condition, CFG::BasicBlock& _nonZero, CFG::BasicBlock& _zero @@ -627,7 +627,7 @@ void ControlFlowGraphBuilder::makeConditionalJump( } void ControlFlowGraphBuilder::jump( - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, CFG::BasicBlock& _target, bool backwards ) diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index ffe935b0dd72..5007d361089b 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -67,13 +67,13 @@ class ControlFlowGraphBuilder Scope::Variable const& lookupVariable(YulString _name) const; /// Resets m_currentBlock to enforce a subsequent explicit reassignment. void makeConditionalJump( - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, StackSlot _condition, CFG::BasicBlock& _nonZero, CFG::BasicBlock& _zero ); void jump( - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, CFG::BasicBlock& _target, bool _backwards = false ); diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 3df75bb88f50..a3052a542f64 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -237,7 +237,7 @@ void OptimizedEVMCodeTransform::validateSlot(StackSlot const& _slot, Expression }, _expression); } -void OptimizedEVMCodeTransform::createStackLayout(std::shared_ptr _debugData, Stack _targetStack) +void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr _debugData, Stack _targetStack) { static constexpr auto slotVariableName = [](StackSlot const& _slot) { return std::visit(util::GenericVisitor{ diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.h b/libyul/backends/evm/OptimizedEVMCodeTransform.h index ed03c1453015..7e648ca964bb 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.h +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.h @@ -83,7 +83,7 @@ class OptimizedEVMCodeTransform /// Shuffles m_stack to the desired @a _targetStack while emitting the shuffling code to m_assembly. /// Sets the source locations to the one in @a _debugData. - void createStackLayout(std::shared_ptr _debugData, Stack _targetStack); + void createStackLayout(langutil::DebugData::ConstPtr _debugData, Stack _targetStack); /// 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 diff --git a/libyul/optimiser/ConditionalSimplifier.cpp b/libyul/optimiser/ConditionalSimplifier.cpp index b08b113de0ca..7119091257d3 100644 --- a/libyul/optimiser/ConditionalSimplifier.cpp +++ b/libyul/optimiser/ConditionalSimplifier.cpp @@ -78,7 +78,7 @@ void ConditionalSimplifier::operator()(Block& _block) ) { YulString condition = std::get(*_if.condition).name; - std::shared_ptr debugData = _if.debugData; + langutil::DebugData::ConstPtr debugData = _if.debugData; return make_vector( std::move(_s), Assignment{ diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 771b4e86bfc7..10f479a421b4 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -37,7 +37,7 @@ namespace { ExpressionStatement makeDiscardCall( - std::shared_ptr const& _debugData, + langutil::DebugData::ConstPtr const& _debugData, BuiltinFunction const& _discardFunction, Expression&& _expression ) @@ -196,7 +196,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch yulAssert(_switchStmt.cases.size() == 1, "Expected only one case!"); auto& switchCase = _switchStmt.cases.front(); - std::shared_ptr debugData = debugDataOf(*_switchStmt.expression); + langutil::DebugData::ConstPtr debugData = debugDataOf(*_switchStmt.expression); YulString type = m_typeInfo.typeOf(*_switchStmt.expression); if (switchCase.value) { diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 986bcb097f33..6f0834d7760e 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -98,7 +98,7 @@ void ExpressionSplitter::outlineExpression(Expression& _expr) visit(_expr); - std::shared_ptr debugData = debugDataOf(_expr); + langutil::DebugData::ConstPtr debugData = debugDataOf(_expr); YulString var = m_nameDispenser.newName({}); YulString type = m_typeInfo.typeOf(_expr); m_statementsToPrefix.emplace_back(VariableDeclaration{ diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index 2dd0832c4288..33d8496f08b5 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -38,7 +38,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) !std::holds_alternative(*_forLoop.condition) ) { - std::shared_ptr debugData = debugDataOf(*_forLoop.condition); + langutil::DebugData::ConstPtr debugData = debugDataOf(*_forLoop.condition); _forLoop.body.statements.emplace( begin(_forLoop.body.statements), diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index 363ecdf0c02d..e2451bc6c6e9 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -54,7 +54,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) return; YulString iszero = m_dialect.booleanNegationFunction()->name; - std::shared_ptr debugData = debugDataOf(*firstStatement.condition); + langutil::DebugData::ConstPtr debugData = debugDataOf(*firstStatement.condition); if ( std::holds_alternative(*firstStatement.condition) && diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index 74a7701494d4..675d21acc343 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -84,7 +84,7 @@ void IntroduceSSA::operator()(Block& _block) // Replace "let a := v" by "let a_1 := v let a := a_1" // Replace "let a, b := v" by "let a_1, b_1 := v let a := a_1 let b := b_2" - std::shared_ptr debugData = varDecl.debugData; + langutil::DebugData::ConstPtr debugData = varDecl.debugData; std::vector statements; statements.emplace_back(VariableDeclaration{debugData, {}, std::move(varDecl.value)}); TypedNameList newVariables; @@ -111,7 +111,7 @@ void IntroduceSSA::operator()(Block& _block) // Replace "a := v" by "let a_1 := v a := v" // Replace "a, b := v" by "let a_1, b_1 := v a := a_1 b := b_2" - std::shared_ptr debugData = assignment.debugData; + langutil::DebugData::ConstPtr debugData = assignment.debugData; std::vector statements; statements.emplace_back(VariableDeclaration{debugData, {}, std::move(assignment.value)}); TypedNameList newVariables; diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index f8bbcf678a1c..7fe56026ac95 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -234,7 +234,7 @@ evmasm::Instruction Pattern::instruction() const return m_instruction; } -Expression Pattern::toExpression(std::shared_ptr const& _debugData, langutil::EVMVersion _evmVersion) const +Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const { if (matchGroup()) return ASTCopier().translate(matchGroupValue()); diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index e36730f05425..5e498bd5c9a4 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include @@ -42,6 +42,8 @@ struct Dialect; struct AssignedValue; class Pattern; +using DebugData = langutil::DebugData; + /** * Container for all simplification rules. */ @@ -131,7 +133,7 @@ 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(std::shared_ptr const& _debugData, langutil::EVMVersion _evmVersion) const; + Expression toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const; private: Expression const& matchGroupValue() const; diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 87a5e411c5e2..58552147a608 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -253,7 +253,7 @@ bool StackCompressor::run( _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - bool allowMSizeOptimzation = !MSizeFinder::containsMSize(_dialect, *_object.code); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, *_object.code); if (usesOptimizedCodeGenerator) { yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object); @@ -262,7 +262,7 @@ bool StackCompressor::run( _dialect, *_object.code, StackLayoutGenerator::reportStackTooDeep(*cfg), - allowMSizeOptimzation + allowMSizeOptimization ); } else @@ -275,7 +275,7 @@ bool StackCompressor::run( _dialect, *_object.code, stackSurplus, - allowMSizeOptimzation + allowMSizeOptimization ); } return false; diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index ab39669b2d9a..dedb5cd382ce 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -36,7 +36,7 @@ namespace { std::vector generateMemoryStore( Dialect const& _dialect, - std::shared_ptr const& _debugData, + langutil::DebugData::ConstPtr const& _debugData, YulString _mpos, Expression _value ) @@ -55,7 +55,7 @@ std::vector generateMemoryStore( return result; } -FunctionCall generateMemoryLoad(Dialect const& _dialect, std::shared_ptr const& _debugData, YulString _mpos) +FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, YulString _mpos) { BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType); yulAssert(memoryLoadFunction, ""); diff --git a/scripts/check_style.sh b/scripts/check_style.sh index 7bcd8cca36c9..3c9acf86ca74 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -39,6 +39,7 @@ NAMESPACE_STD_FREE_FILES=( libyul/backends/evm/* libyul/optimiser/* solc/* + test/* test/contracts/* test/libevmasm/* test/liblangutil/* @@ -50,6 +51,7 @@ NAMESPACE_STD_FREE_FILES=( test/libyul/* test/solc/* test/tools/yulInterpreter/* + test/yulPhaser/* ) ( diff --git a/scripts/error_codes.py b/scripts/error_codes.py index d4e9e5486665..27e7b1102bbe 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -202,7 +202,6 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "4591", # "There are more than 256 warnings. Ignoring the rest." # Due to 3805, the warning lists look different for different compiler builds. "1834", # Unimplemented feature error, as we do not test it anymore via cmdLineTests - "6679", # blobbasefee being used in inline assembly for EVMVersion < cancun "1180", # SMTChecker, covered by CL tests "2339", # SMTChecker, covered by CL tests "2961", # SMTChecker, covered by CL tests @@ -275,18 +274,15 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "1801", "1807", "2015", - "2138", "2345", "2399", "2599", "2655", - "2658", "2934", "3101", "3111", "3195", "3520", - "3570", "3573", "3654", "4316", @@ -329,8 +325,6 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "9282", "9603", "9658", - "9817", - "9831", "9988", } diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 3bca968a5aa5..8bc9bdf7bd40 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -22,7 +22,7 @@ set -e # Requires $REPO_ROOT to be defined and "${REPO_ROOT}/scripts/common.sh" to be included before. -CURRENT_EVM_VERSION=shanghai +CURRENT_EVM_VERSION=cancun AVAILABLE_PRESETS=( legacy-no-optimize @@ -106,25 +106,28 @@ function setup_solc function download_project { - local repo="$1" - local ref_type="$2" - local solcjs_ref="$3" - local test_dir="$4" - - [[ $ref_type == commit || $ref_type == branch || $ref_type == tag ]] || assertFail - - printLog "Cloning ${ref_type} ${solcjs_ref} of ${repo}..." - if [[ $ref_type == commit ]]; then - mkdir ext - cd ext - git init - git remote add origin "$repo" - git fetch --depth 1 origin "$solcjs_ref" - git reset --hard FETCH_HEAD - else - git clone --depth 1 "$repo" -b "$solcjs_ref" "$test_dir/ext" - cd ext + local repo_url="$1" + local ref="$2" + local test_dir="$3" + + printLog "Cloning ${repo_url}..." + # Clone the repo ignoring all blobs until needed by git. + # This allows access to commit history but with a fast initial clone + git clone --filter=blob:none "$repo_url" "$test_dir/ext" + cd "$test_dir/ext" + + # If the ref is '' try to use the latest tag as ref + # NOTE: Sadly this will not work with monorepos and may not always + # return the latest tag. + if [[ "$ref" == "" ]]; then + ref=$(git tag --sort=-v:refname | head --lines=1) fi + + [[ $ref != "" ]] || assertFail + + printLog "Using ref: ${ref}" + git checkout "$ref" + echo "Current commit hash: $(git rev-parse HEAD)" } @@ -329,12 +332,16 @@ function force_hardhat_compiler_settings echo "require('hardhat-gas-reporter');" echo "module.exports.gasReporter = ${gas_reporter_settings};" echo "module.exports.solidity = ${compiler_settings};" + echo "module.exports.networks.hardhat = module.exports.networks.hardhat || { hardfork: '${evm_version}' }" + echo "module.exports.networks.hardhat.hardfork = '${evm_version}'" else [[ $config_file == *\.ts ]] || assertFail [[ $config_var_name != "" ]] || assertFail echo 'import "hardhat-gas-reporter";' echo "${config_var_name}.gasReporter = ${gas_reporter_settings};" echo "${config_var_name}.solidity = {compilers: [${compiler_settings}]};" + echo "${config_var_name}.networks!.hardhat = ${config_var_name}.networks!.hardhat ?? { hardfork: '${evm_version}' };" + echo "${config_var_name}.networks!.hardhat!.hardfork = '${evm_version}'" fi >> "$config_file" } @@ -570,17 +577,15 @@ function gas_report_to_json cat - | "${REPO_ROOT}/scripts/externalTests/parse_eth_gas_report.py" | jq '{gas: .}' } -function detect_hardhat_artifact_dir +function detect_hardhat_artifact_dirs { - if [[ -e build/ && -e artifacts/ ]]; then - fail "Cannot determine Hardhat artifact location. Both build/ and artifacts/ exist" - elif [[ -e build/ ]]; then - echo -n build/artifacts - elif [[ -e artifacts/ ]]; then - echo -n artifacts - else - fail "Hardhat build artifacts not found." - fi + # NOTE: The artifacts path is a configured parameter in Hardhat, so the below may fail for new external tests + # See: https://hardhat.org/hardhat-runner/docs/config#path-configuration + local artifact_dir=() + [[ -e build/artifacts ]] && artifact_dir+=("build/artifacts") + [[ -e artifacts/ ]] && artifact_dir+=("artifacts") + (( ${#artifact_dir[@]} != 0 )) || assertFail + echo -n "${artifact_dir[@]}" } function bytecode_size_json_from_truffle_artifacts @@ -605,16 +610,17 @@ function bytecode_size_json_from_truffle_artifacts function bytecode_size_json_from_hardhat_artifacts { # NOTE: The output of this function is a series of concatenated JSON dicts rather than a list. - - for artifact in "$(detect_hardhat_artifact_dir)"/build-info/*.json; do - # Each artifact contains Standard JSON output under the `output` key. - # Process it into a dict of the form `{"": {"": }}`, - # Note that one Hardhat artifact often represents multiple input files. - jq '.output.contracts | to_entries[] | { - "\(.key)": .value | to_entries[] | { - "\(.key)": (.value.evm.bytecode.object | length / 2) - } - }' "$artifact" + for artifact_dir in $(detect_hardhat_artifact_dirs); do + for artifact in "$artifact_dir"/build-info/*.json; do + # Each artifact contains Standard JSON output under the `output` key. + # Process it into a dict of the form `{"": {"": }}`, + # Note that one Hardhat artifact often represents multiple input files. + jq '.output.contracts | to_entries[] | { + "\(.key)": .value | to_entries[] | { + "\(.key)": (.value.evm.bytecode.object | length / 2) + } + }' "$artifact" + done done } diff --git a/scripts/externalTests/runners/base.py b/scripts/externalTests/runners/base.py index a79ed53442e9..cd94fab6b80b 100644 --- a/scripts/externalTests/runners/base.py +++ b/scripts/externalTests/runners/base.py @@ -41,13 +41,12 @@ from test_helpers import settings_from_preset from test_helpers import SettingsPreset -CURRENT_EVM_VERSION: str = "shanghai" +CURRENT_EVM_VERSION: str = "cancun" @dataclass class TestConfig: name: str repo_url: str - ref_type: str ref: str compile_only_presets: List[SettingsPreset] = field(default_factory=list) settings_presets: List[SettingsPreset] = field(default_factory=lambda: list(SettingsPreset)) @@ -134,7 +133,7 @@ def run_test(runner: BaseRunner): print(f"Using compiler version {solc_version}") # Download project - download_project(runner.test_dir, runner.config.repo_url, runner.config.ref_type, runner.config.ref) + download_project(runner.test_dir, runner.config.repo_url, runner.config.ref) # Configure run environment runner.setup_environment() diff --git a/scripts/externalTests/test_helpers.py b/scripts/externalTests/test_helpers.py index 9a573d50adf0..576db4429b05 100644 --- a/scripts/externalTests/test_helpers.py +++ b/scripts/externalTests/test_helpers.py @@ -96,23 +96,29 @@ def parse_command_line(description: str, args: List[str]): return arg_parser.parse_args(args) -def download_project(test_dir: Path, repo_url: str, ref_type: str = "branch", ref: str = "master"): - assert ref_type in ("commit", "branch", "tag") - - print(f"Cloning {ref_type} {ref} of {repo_url}...") - if ref_type == "commit": - os.mkdir(test_dir) - os.chdir(test_dir) - subprocess.run(["git", "init"], check=True) - subprocess.run(["git", "remote", "add", "origin", repo_url], check=True) - subprocess.run(["git", "fetch", "--depth", "1", "origin", ref], check=True) - subprocess.run(["git", "reset", "--hard", "FETCH_HEAD"], check=True) - else: - os.chdir(test_dir.parent) - subprocess.run(["git", "clone", "--no-progress", "--depth", "1", repo_url, "-b", ref, test_dir.resolve()], check=True) - if not test_dir.exists(): - raise RuntimeError("Failed to clone the project.") - os.chdir(test_dir) +def download_project(test_dir: Path, repo_url: str, ref: str = ""): + print(f"Cloning {repo_url}...") + # Clone the repo ignoring all blobs until needed by git. + # This allows access to commit history but with a fast initial clone + subprocess.run(["git", "clone", "--filter", "blob:none", repo_url, test_dir.resolve()], check=True) + if not test_dir.exists(): + raise RuntimeError("Failed to clone the project.") + os.chdir(test_dir) + + # If the ref is '' try to use the latest tag as ref + # NOTE: Sadly this will not work with monorepos and may not always + # return the latest tag. + if ref == "": + tags = subprocess.check_output( + ["git", "tag", "--sort", "-v:refname"], + encoding="ascii" + ).strip().split('\n') + if len(tags) == 0: + raise RuntimeError("Failed to retrieve latest release tag.") + ref = tags[0] + + print(f"Using ref: {ref}") + subprocess.run(["git", "checkout", ref], check=True) if (test_dir / ".gitmodules").exists(): subprocess.run(["git", "submodule", "update", "--init"], check=True) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 234d42df0c0e..e593bb9a9746 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """A script to collect gas statistics and print it. Useful to summarize gas differences to semantic tests for a PR / branch. @@ -17,21 +18,26 @@ repository. The changes are compared against ``origin/develop``. """ + import subprocess +import sys from pathlib import Path from enum import Enum -from parsec import generate, ParseError, regex, string +from parsec import generate, ParseError, regex, string, optional from tabulate import tabulate class Kind(Enum): - IrOptimized = 1 - Legacy = 2 - LegacyOptimized = 3 + Ir = 1 + IrOptimized = 2 + Legacy = 3 + LegacyOptimized = 4 class Diff(Enum): Minus = 1 Plus = 2 +SEMANTIC_TEST_DIR = Path("test/libsolidity/semanticTests/") + minus = string("-").result(Diff.Minus) plus = string("+").result(Diff.Plus) @@ -39,9 +45,11 @@ class Diff(Enum): comment = string("//") colon = string(":") +gas_ir = string("gas ir").result(Kind.Ir) gas_ir_optimized = string("gas irOptimized").result(Kind.IrOptimized) gas_legacy_optimized = string("gas legacyOptimized").result(Kind.LegacyOptimized) gas_legacy = string("gas legacy").result(Kind.Legacy) +code_suffix = string("code") def number() -> int: """Parse number.""" @@ -59,7 +67,9 @@ def diff_string() -> (Kind, Diff, int): diff_kind = yield minus | plus yield comment yield space - codegen_kind = yield gas_ir_optimized ^ gas_legacy_optimized ^ gas_legacy + codegen_kind = yield gas_ir_optimized ^ gas_ir ^ gas_legacy_optimized ^ gas_legacy + yield optional(space) + yield optional(code_suffix) yield colon yield space val = yield number() @@ -77,14 +87,12 @@ def collect_statistics(lines) -> (int, int, int, int, int, int): if not lines: raise RuntimeError("Empty list") - def try_parse(line): - try: - return diff_string.parse(line) - except ParseError: - pass - return None - - out = [parsed for line in lines if (parsed := try_parse(line)) is not None] + out = [ + parsed + for line in lines + if line.startswith('+// gas ') or line.startswith('-// gas ') + if (parsed := diff_string.parse(line)) is not None + ] diff_kinds = [Diff.Minus, Diff.Plus] codegen_kinds = [Kind.IrOptimized, Kind.LegacyOptimized, Kind.Legacy] return tuple( @@ -99,42 +107,79 @@ def try_parse(line): def semantictest_statistics(): """Prints the tabulated statistics that can be pasted in github.""" - def try_parse_git_diff(fname): - try: - diff_output = subprocess.check_output( - "git diff --unified=0 origin/develop HEAD " + fname, - shell=True, - universal_newlines=True - ).splitlines() - if diff_output: - return collect_statistics(diff_output) - except subprocess.CalledProcessError as e: - print("Error in the git diff:") - print(e.output) - return None + def parse_git_diff(fname): + diff_output = subprocess.check_output( + ["git", "diff", "--unified=0", "origin/develop", "HEAD", fname], + universal_newlines=True + ).splitlines() + if len(diff_output) == 0: + return None + return collect_statistics(diff_output) + + def percent(old, new): + return (int(new) - int(old)) / int(old) * 100 if int(old) != 0 else None + + def percent_or_zero(old, new): + result = percent(old, new) + return result if result is not None else 0 + + def format_percent(percentage): + if percentage is None: + return '' + prefix = ( + # Distinguish actual zero from very small differences + '+' if round(percentage) == 0 and percentage > 0 else + '-' if round(percentage) == 0 and percentage < 0 else + '' + ) + return f'{prefix}{round(percentage)}%' + def stat(old, new): - return ((new - old) / old) * 100 if old else 0 + return format_percent(percent(old, new)) table = [] - for path in Path("test/libsolidity/semanticTests").rglob("*.sol"): + if not SEMANTIC_TEST_DIR.is_dir(): + sys.exit(f"Semantic tests not found. '{SEMANTIC_TEST_DIR.absolute()}' is missing or not a directory.") + + for path in SEMANTIC_TEST_DIR.rglob("*.sol"): fname = path.as_posix() - parsed = try_parse_git_diff(fname) + parsed = parse_git_diff(fname) if parsed is None: continue + assert len(parsed) == 6 ir_optimized = stat(parsed[0], parsed[3]) legacy_optimized = stat(parsed[1], parsed[4]) legacy = stat(parsed[2], parsed[5]) - fname = fname.split('/', 3)[-1] - table += [map(str, [fname, ir_optimized, legacy_optimized, legacy])] + fname = f"`{fname.split('/', 3)[-1]}`" + average = (( + percent_or_zero(parsed[0], parsed[3]) + + percent_or_zero(parsed[1], parsed[4]) + + percent_or_zero(parsed[2], parsed[5]) + ) / 3) + table += [[average, fname, ir_optimized, legacy_optimized, legacy]] + + sorted_table = [row[1:] for row in sorted(table, reverse=True)] if table: print("
Click for a table of gas differences\n") - table_header = ["File name", "IR-optimized (%)", "Legacy-Optimized (%)", "Legacy (%)"] - print(tabulate(table, headers=table_header, tablefmt="github")) + table_header = ["File name", "IR optimized", "Legacy optimized", "Legacy"] + print(tabulate(sorted_table, headers=table_header, tablefmt="github")) print("
") else: print("No differences found.") +def main(): + try: + semantictest_statistics() + except subprocess.CalledProcessError as exception: + sys.exit(f"Error in the git diff:\n{exception.output}") + except ParseError as exception: + sys.exit( + f"ParseError: {exception}\n\n" + f"{exception.text}\n" + f"{' ' * exception.index}^\n" + ) + if __name__ == "__main__": - semantictest_statistics() + main() diff --git a/scripts/tests.sh b/scripts/tests.sh index 9df40e385c1a..26eaf4b4b15b 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -115,7 +115,7 @@ do for vm in $EVM_VERSIONS do FORCE_ABIV1_RUNS="no" - if [[ "$vm" == "shanghai" ]] + if [[ "$vm" == "cancun" ]] then FORCE_ABIV1_RUNS="no yes" # run both in paris fi diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index f4d318b9c0e9..640dffa05683 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -43,9 +43,7 @@ #include -#include #include -#include #include #include diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 906b34d62b53..1fb4ac00bcb1 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -147,7 +147,7 @@ class CommandLineInterface std::ostream& m_serr; bool m_hasOutput = false; FileReader m_fileReader; - SMTSolverCommand m_solverCommand{"eld"}; + SMTSolverCommand m_solverCommand; UniversalCallback m_universalCallback{&m_fileReader, m_solverCommand}; std::optional m_standardJsonInput; std::unique_ptr m_compiler; diff --git a/test/Common.cpp b/test/Common.cpp index 6a3c5a2a00ad..ae725774c48a 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -32,8 +32,6 @@ namespace fs = boost::filesystem; namespace po = boost::program_options; -using namespace std; - namespace solidity::test { @@ -78,7 +76,10 @@ std::optional findInDefaultPath(std::string const& lib_name) fs::current_path() / ".." / "deps" / "lib", fs::current_path() / ".." / ".." / "deps", fs::current_path() / ".." / ".." / "deps" / "lib", - fs::current_path() + fs::current_path(), +#ifdef __APPLE__ + fs::current_path().root_path() / fs::path("usr") / "local" / "lib", +#endif }; for (auto const& basePath: searchPath) { @@ -143,18 +144,16 @@ void CommonOptions::validate() const "Selected batch has to be less than number of batches." ); - if (enforceGasTest) + if (!enforceGasTest) + std::cout << std::endl << "WARNING :: Gas cost expectations are not being enforced" << std::endl << std::endl; + else if (evmVersion() != langutil::EVMVersion{} || useABIEncoderV1) { - assertThrow( - evmVersion() == langutil::EVMVersion{}, - ConfigException, - "Gas costs can only be enforced on latest evm version." - ); - assertThrow( - useABIEncoderV1 == false, - ConfigException, - "Gas costs can only be enforced on abi encoder v2." - ); + std::cout << std::endl << "WARNING :: Enforcing gas cost expectations with non-standard settings:" << std::endl; + if (evmVersion() != langutil::EVMVersion{}) + std::cout << "- EVM version: " << evmVersion().name() << " (default: " << langutil::EVMVersion{}.name() << ")" << std::endl; + if (useABIEncoderV1) + std::cout << "- ABI coder: v1 (default: v2)" << std::endl; + std::cout << std::endl << "DO NOT COMMIT THE UPDATED EXPECTATIONS." << std::endl << std::endl; } } @@ -175,7 +174,7 @@ bool CommonOptions::parse(int argc, char const* const* argv) // Request as uint64_t, since uint8_t will be parsed as character by boost. uint64_t eofVersion = arguments["eof-version"].as(); if (eofVersion != 1) - BOOST_THROW_EXCEPTION(std::runtime_error("Invalid EOF version: " + to_string(eofVersion))); + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid EOF version: " + std::to_string(eofVersion))); m_eofVersion = 1; } @@ -212,18 +211,18 @@ bool CommonOptions::parse(int argc, char const* const* argv) return true; } -string CommonOptions::toString(vector const& _selectedOptions) const +std::string CommonOptions::toString(std::vector const& _selectedOptions) const { if (_selectedOptions.empty()) return ""; - auto boolToString = [](bool _value) -> string { return _value ? "true" : "false"; }; + auto boolToString = [](bool _value) -> std::string { return _value ? "true" : "false"; }; // Using std::map to avoid if-else/switch-case block - map optionValueMap = { + std::map optionValueMap = { {"evmVersion", evmVersion().name()}, {"optimize", boolToString(optimize)}, {"useABIEncoderV1", boolToString(useABIEncoderV1)}, - {"batch", to_string(selectedBatch + 1) + "/" + to_string(batches)}, + {"batch", std::to_string(selectedBatch + 1) + "/" + std::to_string(batches)}, {"enforceGasTest", boolToString(enforceGasTest)}, {"enforceGasTestMinValue", enforceGasTestMinValue.str()}, {"disableSemanticTests", boolToString(disableSemanticTests)}, @@ -232,18 +231,18 @@ string CommonOptions::toString(vector const& _selectedOptions) const {"showMetadata", boolToString(showMetadata)} }; - soltestAssert(ranges::all_of(_selectedOptions, [&optionValueMap](string const& _option) { return optionValueMap.count(_option) > 0; })); + soltestAssert(ranges::all_of(_selectedOptions, [&optionValueMap](std::string const& _option) { return optionValueMap.count(_option) > 0; })); - vector optionsWithValues = _selectedOptions | - ranges::views::transform([&optionValueMap](string const& _option) { return _option + "=" + optionValueMap.at(_option); }) | - ranges::to(); + std::vector optionsWithValues = _selectedOptions | + ranges::views::transform([&optionValueMap](std::string const& _option) { return _option + "=" + optionValueMap.at(_option); }) | + ranges::to(); return solidity::util::joinHumanReadable(optionsWithValues); } -void CommonOptions::printSelectedOptions(ostream& _stream, string const& _linePrefix, vector const& _selectedOptions) const +void CommonOptions::printSelectedOptions(std::ostream& _stream, std::string const& _linePrefix, std::vector const& _selectedOptions) const { - _stream << _linePrefix << "Run Settings: " << toString(_selectedOptions) << endl; + _stream << _linePrefix << "Run Settings: " << toString(_selectedOptions) << std::endl; } langutil::EVMVersion CommonOptions::evmVersion() const diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index 0dedd1fb043b..3cb908118ea2 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -34,7 +34,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::util::formatting; @@ -48,10 +47,10 @@ namespace fs = boost::filesystem; namespace { -int parseUnsignedInteger(string::iterator& _it, string::iterator _end) +int parseUnsignedInteger(std::string::iterator& _it, std::string::iterator _end) { if (_it == _end || !util::isDigit(*_it)) - BOOST_THROW_EXCEPTION(runtime_error("Invalid test expectation. Source location expected.")); + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid test expectation. Source location expected.")); int result = 0; while (_it != _end && util::isDigit(*_it)) { @@ -64,7 +63,7 @@ int parseUnsignedInteger(string::iterator& _it, string::iterator _end) } -CommonSyntaxTest::CommonSyntaxTest(string const& _filename, langutil::EVMVersion _evmVersion): +CommonSyntaxTest::CommonSyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion): EVMVersionRestrictedTestCase(_filename), m_sources(m_reader.sources()), m_expectations(parseExpectations(m_reader.stream())), @@ -72,7 +71,7 @@ CommonSyntaxTest::CommonSyntaxTest(string const& _filename, langutil::EVMVersion { } -TestCase::TestResult CommonSyntaxTest::run(ostream& _stream, string const& _linePrefix, bool _formatted) +TestCase::TestResult CommonSyntaxTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { parseCustomExpectations(m_reader.stream()); parseAndAnalyze(); @@ -80,7 +79,7 @@ TestCase::TestResult CommonSyntaxTest::run(ostream& _stream, string const& _line return conclude(_stream, _linePrefix, _formatted); } -TestCase::TestResult CommonSyntaxTest::conclude(ostream& _stream, string const& _linePrefix, bool _formatted) +TestCase::TestResult CommonSyntaxTest::conclude(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { if (expectationsMatch()) return TestResult::Success; @@ -89,16 +88,16 @@ TestCase::TestResult CommonSyntaxTest::conclude(ostream& _stream, string const& return TestResult::Failure; } -void CommonSyntaxTest::printExpectationAndError(ostream& _stream, string const& _linePrefix, bool _formatted) +void CommonSyntaxTest::printExpectationAndError(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - string nextIndentLevel = _linePrefix + " "; - util::AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl; + std::string nextIndentLevel = _linePrefix + " "; + util::AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << std::endl; printExpectedResult(_stream, nextIndentLevel, _formatted); - util::AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl; + util::AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << std::endl; printObtainedResult(_stream, nextIndentLevel, _formatted); } -void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, bool _formatted) const +void CommonSyntaxTest::printSource(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const { if (m_sources.sources.empty()) return; @@ -113,8 +112,8 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, continue; if (outputSourceNames) - _stream << _linePrefix << util::formatting::CYAN << "==== Source: " << name << " ====" << util::formatting::RESET << endl; - vector sourceFormatting(source.length(), util::formatting::RESET); + _stream << _linePrefix << util::formatting::CYAN << "==== Source: " << name << " ====" << util::formatting::RESET << std::endl; + std::vector sourceFormatting(source.length(), util::formatting::RESET); for (auto const& error: m_errorList) if (error.sourceName == name && error.locationStart >= 0 && error.locationEnd >= 0) { @@ -143,7 +142,7 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, _stream << source[i]; else { - _stream << util::formatting::RESET << endl; + _stream << util::formatting::RESET << std::endl; if (i + 1 < source.length()) _stream << _linePrefix << sourceFormatting[i]; } @@ -158,9 +157,9 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, } } -void CommonSyntaxTest::parseCustomExpectations(istream& _stream) +void CommonSyntaxTest::parseCustomExpectations(std::istream& _stream) { - string remainingExpectations = boost::trim_copy(readUntilEnd(_stream)); + std::string remainingExpectations = boost::trim_copy(readUntilEnd(_stream)); soltestAssert( remainingExpectations.empty(), "Found custom expectations not supported by the test case:\n" + remainingExpectations @@ -172,27 +171,27 @@ bool CommonSyntaxTest::expectationsMatch() return m_expectations == m_errorList; } -void CommonSyntaxTest::printExpectedResult(ostream& _stream, string const& _linePrefix, bool _formatted) const +void CommonSyntaxTest::printExpectedResult(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const { printErrorList(_stream, m_expectations, _linePrefix, _formatted); } -void CommonSyntaxTest::printObtainedResult(ostream& _stream, string const& _linePrefix, bool _formatted) const +void CommonSyntaxTest::printObtainedResult(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const { printErrorList(_stream, m_errorList, _linePrefix, _formatted); } void CommonSyntaxTest::printErrorList( - ostream& _stream, - vector const& _errorList, - string const& _linePrefix, + std::ostream& _stream, + std::vector const& _errorList, + std::string const& _linePrefix, bool _formatted ) { if (_errorList.empty()) { if (_formatted) - util::AnsiColorized(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << endl; + util::AnsiColorized(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << std::endl; } else for (auto const& error: _errorList) @@ -220,11 +219,11 @@ void CommonSyntaxTest::printErrorList( _stream << error.locationEnd; _stream << "): "; } - _stream << error.message << endl; + _stream << error.message << std::endl; } } -string CommonSyntaxTest::errorMessage(util::Exception const& _e) +std::string CommonSyntaxTest::errorMessage(util::Exception const& _e) { if (_e.comment() && !_e.comment()->empty()) return boost::replace_all_copy(*_e.comment(), "\n", "\\n"); @@ -232,13 +231,13 @@ string CommonSyntaxTest::errorMessage(util::Exception const& _e) return "NONE"; } -vector CommonSyntaxTest::parseExpectations(istream& _stream) +std::vector CommonSyntaxTest::parseExpectations(std::istream& _stream) { - static string const customExpectationsDelimiter("// ----"); + static std::string const customExpectationsDelimiter("// ----"); - vector expectations; - string line; - while (getline(_stream, line)) + std::vector expectations; + std::string line; + while (std::getline(_stream, line)) { auto it = line.begin(); @@ -254,17 +253,17 @@ vector CommonSyntaxTest::parseExpectations(istream& _stream) if (it == line.end()) continue; auto typeBegin = it; - while (it != line.end() && isalpha(*it, locale::classic())) + while (it != line.end() && isalpha(*it, std::locale::classic())) ++it; - string errorTypeStr(typeBegin, it); - optional errorType = Error::parseErrorType(errorTypeStr); + std::string errorTypeStr(typeBegin, it); + std::optional errorType = Error::parseErrorType(errorTypeStr); if (!errorType.has_value()) - BOOST_THROW_EXCEPTION(runtime_error("Invalid error type: " + errorTypeStr)); + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid error type: " + errorTypeStr)); skipWhitespace(it, line.end()); - optional errorId; + std::optional errorId; if (it != line.end() && util::isDigit(*it)) errorId = ErrorId{static_cast(parseUnsignedInteger(it, line.end()))}; @@ -295,7 +294,7 @@ vector CommonSyntaxTest::parseExpectations(istream& _stream) skipWhitespace(it, line.end()); - string errorMessage(it, line.end()); + std::string errorMessage(it, line.end()); expectations.emplace_back(SyntaxTestError{ errorType.value(), std::move(errorId), diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 7e05ceec3ecb..2243758356db 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -31,16 +31,15 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::test; using namespace evmc::literals; -evmc::VM& EVMHost::getVM(string const& _path) +evmc::VM& EVMHost::getVM(std::string const& _path) { static evmc::VM NullVM{nullptr}; - static map> vms; + static std::map> vms; if (vms.count(_path) == 0) { evmc_loader_error_code errorCode = {}; @@ -48,16 +47,16 @@ evmc::VM& EVMHost::getVM(string const& _path) if (vm && errorCode == EVMC_LOADER_SUCCESS) { if (vm.get_capabilities() & (EVMC_CAPABILITY_EVM1)) - vms[_path] = make_unique(evmc::VM(std::move(vm))); + vms[_path] = std::make_unique(evmc::VM(std::move(vm))); else - cerr << "VM loaded does not support EVM1" << endl; + std::cerr << "VM loaded does not support EVM1" << std::endl; } else { - cerr << "Error loading VM from " << _path; + std::cerr << "Error loading VM from " << _path; if (char const* errorMsg = evmc_last_error_msg()) - cerr << ":" << endl << errorMsg; - cerr << endl; + std::cerr << ":" << std::endl << errorMsg; + std::cerr << std::endl; } } @@ -67,7 +66,7 @@ evmc::VM& EVMHost::getVM(string const& _path) return NullVM; } -bool EVMHost::checkVmPaths(vector const& _vmPaths) +bool EVMHost::checkVmPaths(std::vector const& _vmPaths) { bool evmVmFound = false; for (auto const& path: _vmPaths) @@ -79,7 +78,7 @@ bool EVMHost::checkVmPaths(vector const& _vmPaths) if (vm.has_capability(EVMC_CAPABILITY_EVM1)) { if (evmVmFound) - BOOST_THROW_EXCEPTION(runtime_error("Multiple evm1 evmc vms defined. Please only define one evm1 evmc vm.")); + BOOST_THROW_EXCEPTION(std::runtime_error("Multiple evm1 evmc vms defined. Please only define one evm1 evmc vm.")); evmVmFound = true; } } @@ -92,7 +91,7 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): { if (!m_vm) { - cerr << "Unable to find evmone library" << endl; + std::cerr << "Unable to find evmone library" << std::endl; assertThrow(false, Exception, ""); } @@ -162,6 +161,8 @@ void EVMHost::reset() recorded_calls.clear(); // Clear EIP-2929 account access indicator recorded_account_accesses.clear(); + m_newlyCreatedAccounts.clear(); + m_totalCodeDepositGas = 0; // Mark all precompiled contracts as existing. Existing here means to have a balance (as per EIP-161). // NOTE: keep this in sync with `EVMHost::call` below. @@ -198,12 +199,13 @@ void EVMHost::newTransactionFrame() } // Process selfdestruct list for (auto& [address, _]: recorded_selfdestructs) - if (m_evmVersion < langutil::EVMVersion::cancun() || newlyCreatedAccounts.count(address)) + if (m_evmVersion < langutil::EVMVersion::cancun() || m_newlyCreatedAccounts.count(address)) // EIP-6780: If SELFDESTRUCT is executed in a transaction different from the one // in which it was created, we do NOT record it or clear any data. // Otherwise, the previous behavior (pre-Cancun) is maintained. accounts.erase(address); - newlyCreatedAccounts.clear(); + m_newlyCreatedAccounts.clear(); + m_totalCodeDepositGas = 0; recorded_selfdestructs.clear(); } @@ -319,7 +321,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept h160 createAddress(keccak256( bytes{static_cast(0xc0 + 21 + encodedNonce.size())} + bytes{0x94} + - bytes(begin(message.sender.bytes), end(message.sender.bytes)) + + bytes(std::begin(message.sender.bytes), std::end(message.sender.bytes)) + encodedNonce ), h160::AlignRight); @@ -332,8 +334,8 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept { h160 createAddress(keccak256( bytes{0xff} + - bytes(begin(message.sender.bytes), end(message.sender.bytes)) + - bytes(begin(message.create2_salt.bytes), end(message.create2_salt.bytes)) + + 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() ), h160::AlignRight); @@ -357,7 +359,8 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept auto& destination = accounts[message.recipient]; if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2) // Mark account as created if it is a CREATE or CREATE2 call - newlyCreatedAccounts.emplace(message.recipient); + // TODO: Should we roll changes back on failure like we do for `accounts`? + m_newlyCreatedAccounts.emplace(message.recipient); if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE) { @@ -393,15 +396,18 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2) { - result.gas_left -= static_cast(evmasm::GasCosts::createDataGas * result.output_size); + int64_t codeDepositGas = static_cast(evmasm::GasCosts::createDataGas * result.output_size); + result.gas_left -= codeDepositGas; if (result.gas_left < 0) { + m_totalCodeDepositGas += -result.gas_left; result.gas_left = 0; result.status_code = EVMC_OUT_OF_GAS; // TODO clear some fields? } else { + m_totalCodeDepositGas += codeDepositGas; result.create_address = message.recipient; destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size); destination.codehash = convertToEVMC(keccak256({result.output_data, result.output_size})); @@ -421,7 +427,7 @@ evmc::bytes32 EVMHost::get_block_hash(int64_t _number) const noexcept h160 EVMHost::convertFromEVMC(evmc::address const& _addr) { - return h160(bytes(begin(_addr.bytes), end(_addr.bytes))); + return h160(bytes(std::begin(_addr.bytes), std::end(_addr.bytes))); } evmc::address EVMHost::convertToEVMC(h160 const& _addr) @@ -434,7 +440,7 @@ evmc::address EVMHost::convertToEVMC(h160 const& _addr) h256 EVMHost::convertFromEVMC(evmc::bytes32 const& _data) { - return h256(bytes(begin(_data.bytes), end(_data.bytes))); + return h256(bytes(std::begin(_data.bytes), std::end(_data.bytes))); } evmc::bytes32 EVMHost::convertToEVMC(h256 const& _data) @@ -452,7 +458,7 @@ evmc::Result EVMHost::precompileECRecover(evmc_message const& _message) noexcept // Fixed cost of 3000 gas. constexpr int64_t gas_cost = 3000; - static map const inputOutput{ + static std::map const inputOutput{ { fromHex( "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c" @@ -509,7 +515,7 @@ evmc::Result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept return 600 + 120 * ((size + 31) / 32); }; - static map const inputOutput{ + static std::map const inputOutput{ { bytes{}, { @@ -628,7 +634,7 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex // Fixed 500 or 150 gas. int64_t gas_cost = (Revision < EVMC_ISTANBUL) ? 500 : 150; - static map const inputOutput{ + static std::map const inputOutput{ { fromHex( "0000000000000000000000000000000000000000000000000000000000000000" @@ -896,7 +902,7 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex // Fixed 40000 or 6000 gas. int64_t gas_cost = (Revision < EVMC_ISTANBUL) ? 40000 : 6000; - static map const inputOutput{ + static std::map const inputOutput{ { fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"), { @@ -990,7 +996,7 @@ evmc::Result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess }; // NOTE this is a partial implementation for some inputs. - static map const inputOutput{ + static std::map const inputOutput{ { fromHex( "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa9" @@ -1155,7 +1161,7 @@ evmc::Result EVMHost::precompileBlake2f(evmc_message const&) noexcept evmc::Result EVMHost::precompileGeneric( evmc_message const& _message, - map const& _inOut) noexcept + std::map const& _inOut) noexcept { bytes input(_message.input_data, _message.input_data + _message.input_size); if (_inOut.count(input)) @@ -1202,7 +1208,7 @@ StorageMap const& EVMHost::get_address_storage(evmc::address const& _addr) return accounts[_addr].storage; } -string EVMHostPrinter::state() +std::string EVMHostPrinter::state() { // Print state and execution trace. if (m_host.account_exists(m_account)) @@ -1225,14 +1231,14 @@ void EVMHostPrinter::storage() << m_host.convertFromEVMC(slot) << ": " << m_host.convertFromEVMC(value.current) - << endl; + << std::endl; } void EVMHostPrinter::balance() { m_stateStream << "BALANCE " << m_host.convertFromEVMC(m_host.get_balance(m_account)) - << endl; + << std::endl; } void EVMHostPrinter::selfdestructRecords() @@ -1242,12 +1248,12 @@ void EVMHostPrinter::selfdestructRecords() m_stateStream << "SELFDESTRUCT" << " BENEFICIARY " << m_host.convertFromEVMC(beneficiary) - << endl; + << std::endl; } void EVMHostPrinter::callRecords() { - static auto constexpr callKind = [](evmc_call_kind _kind) -> string + static auto constexpr callKind = [](evmc_call_kind _kind) -> std::string { switch (_kind) { @@ -1270,5 +1276,5 @@ void EVMHostPrinter::callRecords() m_stateStream << callKind(record.kind) << " VALUE " << m_host.convertFromEVMC(record.value) - << endl; + << std::endl; } diff --git a/test/EVMHost.h b/test/EVMHost.h index 144596e05e38..121adbc15945 100644 --- a/test/EVMHost.h +++ b/test/EVMHost.h @@ -94,6 +94,8 @@ class EVMHost: public evmc::MockedHost /// @returns contents of storage at @param _addr. StorageMap const& get_address_storage(evmc::address const& _addr); + u256 totalCodeDepositGas() const { return m_totalCodeDepositGas; } + static Address convertFromEVMC(evmc::address const& _addr); static evmc::address convertToEVMC(Address const& _addr); static util::h256 convertFromEVMC(evmc::bytes32 const& _data); @@ -129,14 +131,19 @@ class EVMHost: public evmc::MockedHost static evmc::Result resultWithGas(int64_t gas_limit, int64_t gas_required, bytes const& _data) noexcept; static evmc::Result resultWithFailure() noexcept; - /// Store the accounts that have been created in the current transaction. - std::unordered_set newlyCreatedAccounts; - evmc::VM& m_vm; /// EVM version requested by the testing tool langutil::EVMVersion m_evmVersion; /// EVM version requested from EVMC (matches the above) evmc_revision m_evmRevision; + + /// Store the accounts that have been created in the current transaction. + std::unordered_set m_newlyCreatedAccounts; + + /// The part of the total cost of the current transaction that paid for the code deposits. + /// I.e. GAS_CODE_DEPOSIT times the total size of deployed code of all newly created contracts, + /// including the current contract itself if it was a creation transaction. + u256 m_totalCodeDepositGas; }; class EVMHostPrinter diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index a18a73de06b8..0081ba4a9d27 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -41,7 +41,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::test; @@ -52,7 +51,7 @@ ExecutionFramework::ExecutionFramework(): { } -ExecutionFramework::ExecutionFramework(langutil::EVMVersion _evmVersion, vector const& _vmPaths): +ExecutionFramework::ExecutionFramework(langutil::EVMVersion _evmVersion, std::vector const& _vmPaths): m_evmVersion(_evmVersion), m_optimiserSettings(solidity::frontend::OptimiserSettings::minimal()), m_showMessages(solidity::test::CommonOptions::get().showMessages), @@ -71,7 +70,7 @@ void ExecutionFramework::selectVM(evmc_capabilities _cap) evmc::VM& vm = EVMHost::getVM(path.string()); if (vm.has_capability(_cap)) { - m_evmcHost = make_unique(m_evmVersion, vm); + m_evmcHost = std::make_unique(m_evmVersion, vm); break; } } @@ -87,7 +86,7 @@ void ExecutionFramework::reset() EVMHost::convertToEVMC(u256(1) << 100); } -std::pair ExecutionFramework::compareAndCreateMessage( +std::pair ExecutionFramework::compareAndCreateMessage( bytes const& _result, bytes const& _expectation ) @@ -101,8 +100,8 @@ std::pair ExecutionFramework::compareAndCreateMessage( auto expectedHex = boost::replace_all_copy(util::toHex(_expectation), "0", "."); for (size_t i = 0; i < std::max(resultHex.size(), expectedHex.size()); i += 0x40) { - std::string result{i >= resultHex.size() ? string{} : resultHex.substr(i, 0x40)}; - std::string expected{i > expectedHex.size() ? string{} : expectedHex.substr(i, 0x40)}; + std::string result{i >= resultHex.size() ? std::string{} : resultHex.substr(i, 0x40)}; + std::string expected{i > expectedHex.size() ? std::string{} : expectedHex.substr(i, 0x40)}; message += (result == expected ? " " : " X ") + result + @@ -137,7 +136,7 @@ u256 ExecutionFramework::gasPrice() const u256 ExecutionFramework::blockHash(u256 const& _number) const { return u256{EVMHost::convertFromEVMC( - m_evmcHost->get_block_hash(static_cast(_number & numeric_limits::max())) + m_evmcHost->get_block_hash(static_cast(_number & std::numeric_limits::max())) )}; } @@ -153,12 +152,12 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 if (m_showMessages) { if (_isCreation) - cout << "CREATE " << m_sender.hex() << ":" << endl; + std::cout << "CREATE " << m_sender.hex() << ":" << std::endl; else - cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << endl; + std::cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << std::endl; if (_value > 0) - cout << " value: " << _value << endl; - cout << " in: " << util::toHex(_data) << endl; + std::cout << " value: " << _value << std::endl; + std::cout << " in: " << util::toHex(_data) << std::endl; } evmc_message message{}; message.input_data = _data.data(); @@ -189,19 +188,21 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 unsigned const refundRatio = (m_evmVersion >= langutil::EVMVersion::london() ? 5 : 2); auto const totalGasUsed = InitialGas - result.gas_left; - auto const gasRefund = min(u256(result.gas_refund), totalGasUsed / refundRatio); + auto const gasRefund = std::min(u256(result.gas_refund), totalGasUsed / refundRatio); m_gasUsed = totalGasUsed - gasRefund; + m_gasUsedForCodeDeposit = m_evmcHost->totalCodeDepositGas(); m_transactionSuccessful = (result.status_code == EVMC_SUCCESS); if (m_showMessages) { - cout << " out: " << util::toHex(m_output) << endl; - cout << " result: " << static_cast(result.status_code) << endl; - cout << " gas used: " << m_gasUsed.str() << endl; - cout << " gas used (without refund): " << totalGasUsed.str() << endl; - cout << " gas refund (total): " << result.gas_refund << endl; - cout << " gas refund (bound): " << gasRefund.str() << endl; + std::cout << " out: " << util::toHex(m_output) << std::endl; + std::cout << " result: " << static_cast(result.status_code) << std::endl; + std::cout << " gas used: " << m_gasUsed.str() << std::endl; + std::cout << " gas used (without refund): " << totalGasUsed.str() << std::endl; + std::cout << " code deposits only: " << m_gasUsedForCodeDeposit.str() << std::endl; + std::cout << " gas refund (total): " << result.gas_refund << std::endl; + std::cout << " gas refund (bound): " << gasRefund.str() << std::endl; } } @@ -211,9 +212,9 @@ void ExecutionFramework::sendEther(h160 const& _addr, u256 const& _amount) if (m_showMessages) { - cout << "SEND_ETHER " << m_sender.hex() << " -> " << _addr.hex() << ":" << endl; + std::cout << "SEND_ETHER " << m_sender.hex() << " -> " << _addr.hex() << ":" << std::endl; if (_amount > 0) - cout << " value: " << _amount << endl; + std::cout << " value: " << _amount << std::endl; } evmc_message message{}; message.sender = EVMHost::convertToEVMC(m_sender); @@ -294,14 +295,14 @@ bool ExecutionFramework::storageEmpty(h160 const& _addr) const return true; } -vector ExecutionFramework::recordedLogs() const +std::vector ExecutionFramework::recordedLogs() const { - vector logs; + std::vector logs; for (evmc::MockedHost::log_record const& logRecord: m_evmcHost->recorded_logs) logs.emplace_back( EVMHost::convertFromEVMC(logRecord.creator), bytes{logRecord.data.begin(), logRecord.data.end()}, - logRecord.topics | ranges::views::transform([](evmc::bytes32 _bytes) { return EVMHost::convertFromEVMC(_bytes); }) | ranges::to + logRecord.topics | ranges::views::transform([](evmc::bytes32 _bytes) { return EVMHost::convertFromEVMC(_bytes); }) | ranges::to ); return logs; } diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index de0fb9477bcb..33340c58d70d 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -306,7 +306,13 @@ class ExecutionFramework u256 const m_gasPrice = 10000 * sun; u256 const m_gas = 100000000; bytes m_output; + + /// Total gas used by the transaction, after refund. u256 m_gasUsed; + + /// The portion of @a m_gasUsed spent on code deposits of newly created contracts. + /// May exceed @a m_gasUsed in rare corner cases due to refunds. + u256 m_gasUsedForCodeDeposit; }; #define ABI_CHECK(result, expectation) do { \ diff --git a/test/FilesystemUtils.cpp b/test/FilesystemUtils.cpp index 7506d677ecfb..2d917485d631 100644 --- a/test/FilesystemUtils.cpp +++ b/test/FilesystemUtils.cpp @@ -22,11 +22,10 @@ #include -using namespace std; using namespace solidity; using namespace solidity::test; -void solidity::test::createFilesWithParentDirs(set const& _paths, string const& _content) +void solidity::test::createFilesWithParentDirs(std::set const& _paths, std::string const& _content) { for (boost::filesystem::path const& path: _paths) { @@ -34,23 +33,23 @@ void solidity::test::createFilesWithParentDirs(set cons boost::filesystem::create_directories(path.parent_path()); // Use binary mode to avoid line ending conversion on Windows. - ofstream newFile(path.string(), std::ofstream::binary); + std::ofstream newFile(path.string(), std::ofstream::binary); newFile << _content; if (newFile.fail() || !boost::filesystem::exists(path)) - BOOST_THROW_EXCEPTION(runtime_error("Failed to create an empty file: \"" + path.string() + "\".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create an empty file: \"" + path.string() + "\".")); } } -void solidity::test::createFileWithContent(boost::filesystem::path const& _path, string const& _content) +void solidity::test::createFileWithContent(boost::filesystem::path const& _path, std::string const& _content) { if (boost::filesystem::is_regular_file(_path)) - BOOST_THROW_EXCEPTION(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. - ofstream newFile(_path.string(), std::ofstream::binary); + std::ofstream newFile(_path.string(), std::ofstream::binary); if (newFile.fail() || !boost::filesystem::is_regular_file(_path)) - BOOST_THROW_EXCEPTION(runtime_error("Failed to create a file: \"" + _path.string() + "\".")); \ + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create a file: \"" + _path.string() + "\".")); \ newFile << _content; } @@ -80,7 +79,7 @@ bool solidity::test::createSymlinkIfSupportedByFilesystem( ) return false; else - BOOST_THROW_EXCEPTION(runtime_error( + BOOST_THROW_EXCEPTION(std::runtime_error( "Failed to create a symbolic link: \"" + _linkName.string() + "\"" " -> " + _targetPath.string() + "\"." " " + symlinkCreationError.message() + "." diff --git a/test/Metadata.cpp b/test/Metadata.cpp index 88a1f7b42f08..2fea65c65be0 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -26,8 +26,6 @@ #include #include -using namespace std; - namespace solidity::test { @@ -54,7 +52,7 @@ bytes bytecodeSansMetadata(bytes const& _bytecode) return bytes(_bytecode.begin(), _bytecode.end() - static_cast(metadataSize) - 2); } -string bytecodeSansMetadata(string const& _bytecode) +std::string bytecodeSansMetadata(std::string const& _bytecode) { return util::toHex(bytecodeSansMetadata(fromHex(_bytecode, util::WhenError::Throw))); } @@ -73,11 +71,11 @@ class TinyCBORParser assertThrow(nextType() == MajorType::Map, CBORException, "Fixed-length map expected."); return readLength(); } - string readKey() + std::string readKey() { return readString(); } - string readValue() + std::string readValue() { switch(nextType()) { @@ -132,7 +130,7 @@ class TinyCBORParser if (length == 24) return m_metadata.at(m_pos++); // Unsupported length kind. (Only by this parser.) - assertThrow(false, CBORException, string("Unsupported length ") + to_string(length)); + assertThrow(false, CBORException, std::string("Unsupported length ") + std::to_string(length)); } bytes readBytes(unsigned length) { @@ -140,28 +138,28 @@ class TinyCBORParser m_pos += length; return ret; } - string readString() + std::string readString() { // Expect a text string. assertThrow(nextType() == MajorType::TextString, CBORException, "String expected."); bytes tmp{readBytes(readLength())}; - return string{tmp.begin(), tmp.end()}; + return std::string{tmp.begin(), tmp.end()}; } unsigned m_pos; bytes const& m_metadata; }; -std::optional> parseCBORMetadata(bytes const& _metadata) +std::optional> parseCBORMetadata(bytes const& _metadata) { try { TinyCBORParser parser(_metadata); - map ret; + std::map ret; unsigned count = parser.mapItemCount(); for (unsigned i = 0; i < count; i++) { - string key = parser.readKey(); - string value = parser.readValue(); + std::string key = parser.readKey(); + std::string value = parser.readValue(); ret[std::move(key)] = std::move(value); } return ret; @@ -172,7 +170,7 @@ std::optional> parseCBORMetadata(bytes const& _metadata) } } -bool isValidMetadata(string const& _serialisedMetadata) +bool isValidMetadata(std::string const& _serialisedMetadata) { Json::Value metadata; if (!util::jsonParseStrict(_serialisedMetadata, metadata)) diff --git a/test/TestCase.cpp b/test/TestCase.cpp index 51608bd4a374..ae89bb56f31a 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -27,21 +27,20 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::frontend; using namespace solidity::frontend::test; using namespace solidity::util; -void TestCase::printSettings(ostream& _stream, const string& _linePrefix, const bool) +void TestCase::printSettings(std::ostream& _stream, const std::string& _linePrefix, const bool) { auto& settings = m_reader.settings(); if (settings.empty()) return; - _stream << _linePrefix << "// ====" << endl; + _stream << _linePrefix << "// ====" << std::endl; for (auto const& setting: settings) - _stream << _linePrefix << "// " << setting.first << ": " << setting.second << endl; + _stream << _linePrefix << "// " << setting.first << ": " << setting.second << std::endl; } void TestCase::printUpdatedSettings(std::ostream& _stream, std::string const& _linePrefix) @@ -51,7 +50,7 @@ void TestCase::printUpdatedSettings(std::ostream& _stream, std::string const& _l bool TestCase::isTestFilename(boost::filesystem::path const& _filename) { - string extension = _filename.extension().string(); + std::string extension = _filename.extension().string(); return (extension == ".sol" || extension == ".yul" || extension == ".stack") && !boost::starts_with(_filename.string(), "~") && !boost::starts_with(_filename.string(), "."); @@ -63,19 +62,19 @@ bool TestCase::shouldRun() return m_shouldRun; } -void TestCase::expect(string::iterator& _it, string::iterator _end, string::value_type _c) +void TestCase::expect(std::string::iterator& _it, std::string::iterator _end, std::string::value_type _c) { if (_it == _end || *_it != _c) - BOOST_THROW_EXCEPTION(runtime_error(string("Invalid test expectation. Expected: \"") + _c + "\".")); + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Invalid test expectation. Expected: \"") + _c + "\".")); ++_it; } -void TestCase::printSource(ostream& _stream, string const& _linePrefix, bool const) const +void TestCase::printSource(std::ostream& _stream, std::string const& _linePrefix, bool const) const { printPrefixed(_stream, m_source, _linePrefix); } -void TestCase::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const +void TestCase::printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const { printPrefixed(_stream, m_obtainedResult, _linePrefix); } @@ -84,30 +83,30 @@ TestCase::TestResult TestCase::checkResult(std::ostream& _stream, const std::str { if (m_expectation != m_obtainedResult) { - string nextIndentLevel = _linePrefix + " "; + std::string nextIndentLevel = _linePrefix + " "; util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) - << _linePrefix << "Expected result:" << endl; + << _linePrefix << "Expected result:" << std::endl; // TODO could compute a simple diff with highlighted lines printPrefixed(_stream, m_expectation, nextIndentLevel); util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) - << _linePrefix << "Obtained result:" << endl; + << _linePrefix << "Obtained result:" << std::endl; printPrefixed(_stream, m_obtainedResult, nextIndentLevel); return TestResult::Failure; } return TestResult::Success; } -EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(string const& _filename): +EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _filename): TestCase(_filename) { - string versionString = m_reader.stringSetting("EVMVersion", "any"); + std::string versionString = m_reader.stringSetting("EVMVersion", "any"); if (versionString == "any") return; - string comparator; + std::string comparator; size_t versionBegin = 0; for (auto character: versionString) - if (!isalpha(character, locale::classic())) + if (!isalpha(character, std::locale::classic())) { comparator += character; versionBegin++; @@ -118,7 +117,7 @@ EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(string const& _filena versionString = versionString.substr(versionBegin); std::optional version = langutil::EVMVersion::fromString(versionString); if (!version) - BOOST_THROW_EXCEPTION(runtime_error{"Invalid EVM version: \"" + versionString + "\""}); + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid EVM version: \"" + versionString + "\""}); langutil::EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); bool comparisonResult; @@ -135,7 +134,7 @@ EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(string const& _filena else if (comparator == "!") comparisonResult = !(evmVersion == version); else - BOOST_THROW_EXCEPTION(runtime_error{"Invalid EVM comparator: \"" + comparator + "\""}); + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid EVM comparator: \"" + comparator + "\""}); if (!comparisonResult) m_shouldRun = false; diff --git a/test/TestCaseReader.cpp b/test/TestCaseReader.cpp index 7ad752ef816e..da6174cbe9bd 100644 --- a/test/TestCaseReader.cpp +++ b/test/TestCaseReader.cpp @@ -23,36 +23,35 @@ #include #include -using namespace std; using namespace solidity::frontend::test; namespace fs = boost::filesystem; -TestCaseReader::TestCaseReader(string const& _filename): m_fileStream(_filename), m_fileName(_filename) +TestCaseReader::TestCaseReader(std::string const& _filename): m_fileStream(_filename), m_fileName(_filename) { if (!m_fileStream) - BOOST_THROW_EXCEPTION(runtime_error("Cannot open file: \"" + _filename + "\".")); - m_fileStream.exceptions(ios::badbit); + BOOST_THROW_EXCEPTION(std::runtime_error("Cannot open file: \"" + _filename + "\".")); + m_fileStream.exceptions(std::ios::badbit); - tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber(m_fileStream); + std::tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber(m_fileStream); m_unreadSettings = m_settings; } -TestCaseReader::TestCaseReader(istringstream const& _str) +TestCaseReader::TestCaseReader(std::istringstream const& _str) { - tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber( - static_cast(const_cast(_str)) + std::tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber( + static_cast(const_cast(_str)) ); } -string const& TestCaseReader::source() const +std::string const& TestCaseReader::source() const { if (m_sources.sources.size() != 1) - BOOST_THROW_EXCEPTION(runtime_error("Expected single source definition, but got multiple sources.")); + BOOST_THROW_EXCEPTION(std::runtime_error("Expected single source definition, but got multiple sources.")); return m_sources.sources.at(m_sources.mainSourceFile); } -string TestCaseReader::simpleExpectations() +std::string TestCaseReader::simpleExpectations() { return parseSimpleExpectations(m_fileStream); } @@ -63,13 +62,13 @@ bool TestCaseReader::boolSetting(std::string const& _name, bool _defaultValue) return _defaultValue; m_unreadSettings.erase(_name); - string value = m_settings.at(_name); + std::string value = m_settings.at(_name); if (value == "false") return false; if (value == "true") return true; - BOOST_THROW_EXCEPTION(runtime_error("Invalid Boolean value: " + value + ".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid Boolean value: " + value + ".")); } size_t TestCaseReader::sizetSetting(std::string const& _name, size_t _defaultValue) @@ -83,7 +82,7 @@ size_t TestCaseReader::sizetSetting(std::string const& _name, size_t _defaultVal return stoul(m_settings.at(_name)); } -string TestCaseReader::stringSetting(string const& _name, string const& _defaultValue) +std::string TestCaseReader::stringSetting(std::string const& _name, std::string const& _defaultValue) { if (m_settings.count(_name) == 0) return _defaultValue; @@ -95,26 +94,26 @@ string TestCaseReader::stringSetting(string const& _name, string const& _default void TestCaseReader::ensureAllSettingsRead() const { if (!m_unreadSettings.empty()) - BOOST_THROW_EXCEPTION(runtime_error( + BOOST_THROW_EXCEPTION(std::runtime_error( "Unknown setting(s): " + util::joinHumanReadable(m_unreadSettings | ranges::views::keys) )); } -pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(istream& _stream) +std::pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(std::istream& _stream) { - map sources; - map externalSources; - string currentSourceName; - string currentSource; - string line; + std::map sources; + std::map externalSources; + std::string currentSourceName; + std::string currentSource; + std::string line; size_t lineNumber = 1; - static string const externalSourceDelimiterStart("==== ExternalSource:"); - static string const sourceDelimiterStart("==== Source:"); - static string const sourceDelimiterEnd("===="); - static string const comment("// "); - static string const settingsDelimiter("// ===="); - static string const expectationsDelimiter("// ----"); + static std::string const externalSourceDelimiterStart("==== ExternalSource:"); + static std::string const sourceDelimiterStart("==== Source:"); + static std::string const sourceDelimiterEnd("===="); + static std::string const comment("// "); + static std::string const settingsDelimiter("// ===="); + static std::string const expectationsDelimiter("// ----"); bool sourcePart = true; while (getline(_stream, line)) { @@ -138,19 +137,19 @@ pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(is line.size() - sourceDelimiterEnd.size() - sourceDelimiterStart.size() )); if (sources.count(currentSourceName)) - BOOST_THROW_EXCEPTION(runtime_error("Multiple definitions of test source \"" + currentSourceName + "\".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Multiple definitions of test source \"" + currentSourceName + "\".")); } else if (boost::algorithm::starts_with(line, externalSourceDelimiterStart) && boost::algorithm::ends_with(line, sourceDelimiterEnd)) { - string externalSourceString = boost::trim_copy(line.substr( + std::string externalSourceString = boost::trim_copy(line.substr( externalSourceDelimiterStart.size(), line.size() - sourceDelimiterEnd.size() - externalSourceDelimiterStart.size() )); - string externalSourceName; + std::string externalSourceName; size_t remappingPos = externalSourceString.find('='); // Does the external source define a remapping? - if (remappingPos != string::npos) + if (remappingPos != std::string::npos) { externalSourceName = boost::trim_copy(externalSourceString.substr(0, remappingPos)); externalSourceString = boost::trim_copy(externalSourceString.substr(remappingPos + 1)); @@ -164,16 +163,16 @@ pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(is if (!externalSourceTarget.is_relative() || !externalSourceTarget.root_path().empty()) // NOTE: UNC paths (ones starting with // or \\) are considered relative by Boost // since they have an empty root directory (but non-empty root name). - BOOST_THROW_EXCEPTION(runtime_error("External Source paths need to be relative to the location of the test case.")); + BOOST_THROW_EXCEPTION(std::runtime_error("External Source paths need to be relative to the location of the test case.")); fs::path externalSourceFullPath = testCaseParentDir / externalSourceTarget; - string externalSourceContent; + std::string externalSourceContent; if (!fs::exists(externalSourceFullPath)) - BOOST_THROW_EXCEPTION(runtime_error("External Source '" + externalSourceTarget.string() + "' not found.")); + BOOST_THROW_EXCEPTION(std::runtime_error("External Source '" + externalSourceTarget.string() + "' not found.")); else externalSourceContent = util::readFileAsString(externalSourceFullPath); if (sources.count(externalSourceName)) - BOOST_THROW_EXCEPTION(runtime_error("Multiple definitions of test source \"" + externalSourceName + "\".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Multiple definitions of test source \"" + externalSourceName + "\".")); sources[externalSourceName] = externalSourceContent; externalSources[externalSourceName] = externalSourceTarget; } @@ -183,32 +182,32 @@ pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(is else if (boost::algorithm::starts_with(line, comment)) { size_t colon = line.find(':'); - if (colon == string::npos) - BOOST_THROW_EXCEPTION(runtime_error(string("Expected \":\" inside setting."))); - string key = line.substr(comment.size(), colon - comment.size()); - string value = line.substr(colon + 1); + if (colon == std::string::npos) + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Expected \":\" inside setting."))); + std::string key = line.substr(comment.size(), colon - comment.size()); + std::string value = line.substr(colon + 1); boost::algorithm::trim(key); boost::algorithm::trim(value); m_settings[key] = value; } else - BOOST_THROW_EXCEPTION(runtime_error(string("Expected \"//\" or \"// ---\" to terminate settings and source."))); + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Expected \"//\" or \"// ---\" to terminate settings and source."))); } // Register the last source as the main one sources[currentSourceName] = currentSource; return {{std::move(sources), std::move(externalSources), std::move(currentSourceName)}, lineNumber}; } -string TestCaseReader::parseSimpleExpectations(istream& _file) +std::string TestCaseReader::parseSimpleExpectations(std::istream& _file) { - string result; - string line; - while (getline(_file, line)) + std::string result; + std::string line; + while (std::getline(_file, line)) if (boost::algorithm::starts_with(line, "// ")) result += line.substr(3) + "\n"; else if (line == "//") result += "\n"; else - BOOST_THROW_EXCEPTION(runtime_error("Test expectations must start with \"// \".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Test expectations must start with \"// \".")); return result; } diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 3166cd6b5dd0..4f7b88fe974f 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -216,7 +216,7 @@ import re, sys json = open("$stdout_path", "r").read() json = re.sub(r"{[^{}]*Warning: This is a pre-release compiler version[^{}]*},?", "", json) json = re.sub(r"\"errors\":\s*\[\s*\],?","\n" if json[1] == " " else "",json) # Remove "errors" array if it's not empty -json = re.sub("\n\\s*\n", "\n", json) # Remove trailing whitespace +json = re.sub(r"\n\s*\n", "\n", json) # Remove trailing whitespace json = re.sub(r"},(\n{0,1})\n*(\s*(]|}))", r"}\1\2", json) # Remove trailing comma open("$stdout_path", "w").write(json) EOF diff --git a/test/cmdlineTests/abi_via_ir/args b/test/cmdlineTests/abi_via_ir/args new file mode 100644 index 000000000000..5dc346ecb4bb --- /dev/null +++ b/test/cmdlineTests/abi_via_ir/args @@ -0,0 +1 @@ +--abi --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/abi_via_ir/input.sol b/test/cmdlineTests/abi_via_ir/input.sol new file mode 100644 index 000000000000..1f5c758f719d --- /dev/null +++ b/test/cmdlineTests/abi_via_ir/input.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +error fileLevelError(uint z); + +library L { + event libraryEvent(uint r); + error libraryError(uint r); + error libraryErrorUnused(uint u); + event libraryEventUnused(uint u); +} + +contract C { + struct S { uint x; } + + event ev(uint y); + event anon_ev(uint y) anonymous; + + error err(uint z, uint w); + + function f(S memory s) public { + emit L.libraryEvent(3); + if (s.x > 1) + revert fileLevelError(3); + else + revert L.libraryError(4); + } +} diff --git a/test/cmdlineTests/abi_via_ir/output b/test/cmdlineTests/abi_via_ir/output new file mode 100644 index 000000000000..daf18f3497a7 --- /dev/null +++ b/test/cmdlineTests/abi_via_ir/output @@ -0,0 +1,167 @@ + +======= abi_via_ir/input.sol:C ======= +Contract JSON ABI +[ + { + "inputs": + [ + { + "internalType": "uint256", + "name": "z", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "w", + "type": "uint256" + } + ], + "name": "err", + "type": "error" + }, + { + "inputs": + [ + { + "internalType": "uint256", + "name": "z", + "type": "uint256" + } + ], + "name": "fileLevelError", + "type": "error" + }, + { + "inputs": + [ + { + "internalType": "uint256", + "name": "r", + "type": "uint256" + } + ], + "name": "libraryError", + "type": "error" + }, + { + "anonymous": true, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "y", + "type": "uint256" + } + ], + "name": "anon_ev", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "y", + "type": "uint256" + } + ], + "name": "ev", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "r", + "type": "uint256" + } + ], + "name": "libraryEvent", + "type": "event" + }, + { + "inputs": + [ + { + "components": + [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + } + ], + "internalType": "struct C.S", + "name": "s", + "type": "tuple" + } + ], + "name": "f", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] + +======= abi_via_ir/input.sol:L ======= +Contract JSON ABI +[ + { + "inputs": + [ + { + "internalType": "uint256", + "name": "r", + "type": "uint256" + } + ], + "name": "libraryError", + "type": "error" + }, + { + "inputs": + [ + { + "internalType": "uint256", + "name": "u", + "type": "uint256" + } + ], + "name": "libraryErrorUnused", + "type": "error" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "r", + "type": "uint256" + } + ], + "name": "libraryEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "u", + "type": "uint256" + } + ], + "name": "libraryEventUnused", + "type": "event" + } +] diff --git a/test/cmdlineTests/asm_json_import_all_valid_flags/output b/test/cmdlineTests/asm_json_import_all_valid_flags/output index 7b8aa0297982..837187d195ae 100644 --- a/test/cmdlineTests/asm_json_import_all_valid_flags/output +++ b/test/cmdlineTests/asm_json_import_all_valid_flags/output @@ -8,8 +8,8 @@ ".code": [ { - "begin": 0, - "end": 0, + "begin": -1, + "end": -1, "name": "PUSH", "source": -1, "value": "0" @@ -22,8 +22,8 @@ ".code": [ { - "begin": 0, - "end": 0, + "begin": -1, + "end": -1, "name": "PUSH", "source": -1, "value": "1" @@ -40,8 +40,8 @@ "bin": "5ffe", "bin-runtime": "6001", "opcodes": "PUSH0 INVALID ", - "srcmap": "0:0::-:0", - "srcmap-runtime": "0:0::-:0" + "srcmap": ":::-:0", + "srcmap-runtime": ":::-:0" } }, "sourceList": @@ -60,8 +60,8 @@ EVM assembly: ".code": [ { - "begin": 0, - "end": 0, + "begin": -1, + "end": -1, "name": "PUSH", "source": -1, "value": "0" @@ -74,8 +74,8 @@ EVM assembly: ".code": [ { - "begin": 0, - "end": 0, + "begin": -1, + "end": -1, "name": "PUSH", "source": -1, "value": "1" diff --git a/test/cmdlineTests/asm_json_import_difficulty_prevrandao/output b/test/cmdlineTests/asm_json_import_difficulty_prevrandao/output index 3d19f83d668f..1713fb49b6cc 100644 --- a/test/cmdlineTests/asm_json_import_difficulty_prevrandao/output +++ b/test/cmdlineTests/asm_json_import_difficulty_prevrandao/output @@ -1,6 +1,5 @@ Opcodes: PREVRANDAO PREVRANDAO EVM assembly: - /* */ prevrandao prevrandao diff --git a/test/cmdlineTests/asm_json_import_hex_subassembly_indices/output b/test/cmdlineTests/asm_json_import_hex_subassembly_indices/output index 873465aa1f3f..60f114ba68e0 100644 --- a/test/cmdlineTests/asm_json_import_hex_subassembly_indices/output +++ b/test/cmdlineTests/asm_json_import_hex_subassembly_indices/output @@ -1,7 +1,6 @@ Opcodes: PUSH0 INVALID EVM assembly: - /* */ 0x00 stop diff --git a/test/cmdlineTests/asm_json_import_random_order_data_index/output b/test/cmdlineTests/asm_json_import_random_order_data_index/output index b23848e5ddcb..ab2f02dc7c84 100644 --- a/test/cmdlineTests/asm_json_import_random_order_data_index/output +++ b/test/cmdlineTests/asm_json_import_random_order_data_index/output @@ -1,7 +1,6 @@ Opcodes: PUSH0 INVALID EVM assembly: - /* */ 0x00 stop diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index 94dfb864262a..0bd6285b785e 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -180,12 +180,10 @@ object "D_27" { } function copy_memory_to_memory_with_cleanup(src, dst, length) { - let i := 0 - for { } lt(i, length) { i := add(i, 32) } - { - mstore(add(dst, i), mload(add(src, i))) - } + + mcopy(dst, src, length) mstore(add(dst, length), 0) + } function round_up_to_mul_of_32(value) -> result { @@ -468,8 +466,7 @@ object "D_27" { } mstore(_2, newFreePtr) mstore(memPtr, 2) - let _6 := 32 - mstore(add(memPtr, _6), "/*") + mstore(add(memPtr, 32), "/*") let memPtr_1 := mload(_2) let newFreePtr_1 := add(memPtr_1, 96) if or(gt(newFreePtr_1, /** @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." */ _5), /** @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." */ lt(newFreePtr_1, memPtr_1)) @@ -480,17 +477,14 @@ object "D_27" { } mstore(_2, newFreePtr_1) mstore(memPtr_1, 39) - mstore(add(memPtr_1, _6), 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b) + let _6 := add(memPtr_1, 32) + mstore(_6, 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b) mstore(add(memPtr_1, _2), shl(200, 0x2e2e2e22202a2f)) let memPos := mload(_2) - mstore(memPos, _6) + mstore(memPos, 32) let length := mload(memPtr_1) - mstore(add(memPos, _6), length) - let i := 0 - for { } lt(i, length) { i := add(i, _6) } - { - mstore(add(add(memPos, i), _2), mload(add(add(memPtr_1, i), _6))) - } + mstore(add(memPos, 32), length) + mcopy(add(memPos, _2), _6, length) mstore(add(add(memPos, length), _2), 0) return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) } diff --git a/test/cmdlineTests/function_debug_info/output b/test/cmdlineTests/function_debug_info/output index b9ca3f3c40ec..c359d4e1c155 100644 --- a/test/cmdlineTests/function_debug_info/output +++ b/test/cmdlineTests/function_debug_info/output @@ -13,7 +13,7 @@ }, "abi_decode_tuple_t_uint256_fromMemory": { - "entryPoint": 92, + "entryPoint": 88, "parameterSlots": 2, "returnSlots": 1 } diff --git a/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json b/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json index 169e99961e93..3a69e3e2d782 100644 --- a/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json +++ b/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json @@ -17,11 +17,11 @@ [ { "length": 20, - "start": 174 + "start": 173 }, { "length": 20, - "start": 350 + "start": 349 } ] } diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/args b/test/cmdlineTests/mcopy_bytes_array_abi_decode/args new file mode 100644 index 000000000000..4a03d8d932b9 --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/args @@ -0,0 +1 @@ +--evm-version cancun --no-cbor-metadata --via-ir --ir --debug-info none diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/err b/test/cmdlineTests/mcopy_bytes_array_abi_decode/err new file mode 100644 index 000000000000..de32e66295be --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/err @@ -0,0 +1,5 @@ +Warning: Statement has no effect. + --> mcopy_bytes_array_abi_decode/input.sol:7:9: + | +7 | abi.decode("abcd", (bytes)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/input.sol b/test/cmdlineTests/mcopy_bytes_array_abi_decode/input.sol new file mode 100644 index 000000000000..07d66f800ec9 --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + function foo() external pure + { + abi.decode("abcd", (bytes)); + } +} diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/output b/test/cmdlineTests/mcopy_bytes_array_abi_decode/output new file mode 100644 index 000000000000..2a24ec834fa1 --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/output @@ -0,0 +1,230 @@ +IR: + +/// @use-src 0:"mcopy_bytes_array_abi_decode/input.sol" +object "C_15" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_15() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_15_deployed"), datasize("C_15_deployed")) + + return(_1, datasize("C_15_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_15() { + + } + + } + /// @use-src 0:"mcopy_bytes_array_abi_decode/input.sol" + object "C_15_deployed" { + code { + + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xc2985578 + { + // foo() + + external_fun_foo_14() + } + + 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_foo_14() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_foo_14() + 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 round_up_to_mul_of_32(value) -> result { + result := and(add(value, 31), not(31)) + } + + function panic_error_0x41() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x41) + revert(0, 0x24) + } + + function finalize_allocation(memPtr, size) { + let newFreePtr := add(memPtr, round_up_to_mul_of_32(size)) + // protect against overflow + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() } + mstore(64, newFreePtr) + } + + function allocate_memory(size) -> memPtr { + memPtr := allocate_unbounded() + finalize_allocation(memPtr, size) + } + + function array_allocation_size_t_string_memory_ptr(length) -> size { + // Make sure we can allocate memory without overflow + if gt(length, 0xffffffffffffffff) { panic_error_0x41() } + + size := round_up_to_mul_of_32(length) + + // add length slot + size := add(size, 0x20) + + } + + function allocate_memory_array_t_string_memory_ptr(length) -> memPtr { + let allocSize := array_allocation_size_t_string_memory_ptr(length) + memPtr := allocate_memory(allocSize) + + mstore(memPtr, length) + + } + + function store_literal_in_memory_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77(memPtr) { + + mstore(add(memPtr, 0), "abcd") + + } + + function copy_literal_to_memory_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77() -> memPtr { + memPtr := allocate_memory_array_t_string_memory_ptr(4) + store_literal_in_memory_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77(add(memPtr, 32)) + } + + function convert_t_stringliteral_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77_to_t_bytes_memory_ptr() -> converted { + converted := copy_literal_to_memory_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77() + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d() { + revert(0, 0) + } + + function revert_error_987264b3b1d58a9c7f8255e93e81c77d86d6299019c33110a076957a3e06e2ae() { + revert(0, 0) + } + + function array_allocation_size_t_bytes_memory_ptr(length) -> size { + // Make sure we can allocate memory without overflow + if gt(length, 0xffffffffffffffff) { panic_error_0x41() } + + size := round_up_to_mul_of_32(length) + + // add length slot + size := add(size, 0x20) + + } + + function copy_memory_to_memory_with_cleanup(src, dst, length) { + + mcopy(dst, src, length) + mstore(add(dst, length), 0) + + } + + function abi_decode_available_length_t_bytes_memory_ptr_fromMemory(src, length, end) -> array { + array := allocate_memory(array_allocation_size_t_bytes_memory_ptr(length)) + mstore(array, length) + let dst := add(array, 0x20) + if gt(add(src, length), end) { revert_error_987264b3b1d58a9c7f8255e93e81c77d86d6299019c33110a076957a3e06e2ae() } + copy_memory_to_memory_with_cleanup(src, dst, length) + } + + // bytes + function abi_decode_t_bytes_memory_ptr_fromMemory(offset, end) -> array { + if iszero(slt(add(offset, 0x1f), end)) { revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d() } + let length := mload(offset) + array := abi_decode_available_length_t_bytes_memory_ptr_fromMemory(add(offset, 0x20), length, end) + } + + function abi_decode_tuple_t_bytes_memory_ptr_fromMemory(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := mload(add(headStart, 0)) + if gt(offset, 0xffffffffffffffff) { revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() } + + value0 := abi_decode_t_bytes_memory_ptr_fromMemory(add(headStart, offset), dataEnd) + } + + } + + function array_length_t_bytes_memory_ptr(value) -> length { + + length := mload(value) + + } + + function fun_foo_14() { + + let _1_mpos := convert_t_stringliteral_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77_to_t_bytes_memory_ptr() + + let expr_11_mpos := abi_decode_tuple_t_bytes_memory_ptr_fromMemory(add(_1_mpos, 32), add(add(_1_mpos, 32), array_length_t_bytes_memory_ptr(_1_mpos))) + + } + + } + + data ".metadata" hex"" + } + +} diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args new file mode 100644 index 000000000000..c74711ba8aec --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args @@ -0,0 +1 @@ +--evm-version cancun --no-cbor-metadata --via-ir --optimize --ir-optimized --debug-info none diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/input.sol b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/input.sol new file mode 100644 index 000000000000..05f24d64e792 --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/input.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + function foo() external pure returns (bytes memory) + { + bytes memory ret = "aaaaa"; + return ret; + } +} diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output new file mode 100644 index 000000000000..2441357d97fb --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output @@ -0,0 +1,51 @@ +Optimized IR: +/// @use-src 0:"mcopy_bytes_array_returned_from_function/input.sol" +object "C_14" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_14_deployed") + codecopy(_1, dataoffset("C_14_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"mcopy_bytes_array_returned_from_function/input.sol" + object "C_14_deployed" { + code { + { + let _1 := memoryguard(0x80) + if iszero(lt(calldatasize(), 4)) + { + if eq(0xc2985578, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let _2 := 64 + let newFreePtr := add(_1, _2) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 36) + } + mstore(_2, newFreePtr) + mstore(_1, 5) + let _3 := add(_1, 0x20) + mstore(_3, "aaaaa") + let memPos := mload(_2) + mstore(memPos, 0x20) + let length := mload(_1) + mstore(add(memPos, 0x20), length) + mcopy(add(memPos, _2), _3, length) + mstore(add(add(memPos, length), _2), 0) + return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/args b/test/cmdlineTests/mcopy_string_literal_returned_from_function/args new file mode 100644 index 000000000000..c74711ba8aec --- /dev/null +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/args @@ -0,0 +1 @@ +--evm-version cancun --no-cbor-metadata --via-ir --optimize --ir-optimized --debug-info none diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/input.sol b/test/cmdlineTests/mcopy_string_literal_returned_from_function/input.sol new file mode 100644 index 000000000000..0251c7cec976 --- /dev/null +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + function foo() external pure returns (string memory) + { + return "MCOPY on Cancun vacation."; + } +} diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/output b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output new file mode 100644 index 000000000000..02740ec0d6cb --- /dev/null +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output @@ -0,0 +1,51 @@ +Optimized IR: +/// @use-src 0:"mcopy_string_literal_returned_from_function/input.sol" +object "C_10" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_10_deployed") + codecopy(_1, dataoffset("C_10_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"mcopy_string_literal_returned_from_function/input.sol" + object "C_10_deployed" { + code { + { + let _1 := memoryguard(0x80) + if iszero(lt(calldatasize(), 4)) + { + if eq(0xc2985578, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let _2 := 64 + let newFreePtr := add(_1, _2) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 0x24) + } + mstore(_2, newFreePtr) + mstore(_1, 25) + let _3 := add(_1, 0x20) + mstore(_3, "MCOPY on Cancun vacation.") + let memPos := mload(_2) + mstore(memPos, 0x20) + let length := mload(_1) + mstore(add(memPos, 0x20), length) + mcopy(add(memPos, _2), _3, length) + mstore(add(add(memPos, length), _2), 0) + return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/metadata/output b/test/cmdlineTests/metadata/output index bf1e750c95f0..b6a684b844f3 100644 --- a/test/cmdlineTests/metadata/output +++ b/test/cmdlineTests/metadata/output @@ -1,4 +1,4 @@ ======= metadata/input.sol:C ======= Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"metadata/input.sol":"C"},"evmVersion":"shanghai","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"metadata/input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"metadata/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"metadata/input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index ed4c6e5c02e9..0a461e3e4af4 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -98,9 +98,9 @@ object "C_59" { } mstore(_9, newFreePtr_2) mstore(memPtr_1, 100) - mstore(add(memPtr_1, _3), "longstringlongstringlongstringlo") + let _11 := add(memPtr_1, _3) + mstore(_11, "longstringlongstringlongstringlo") mstore(add(memPtr_1, _9), "ngstringlongstringlongstringlong") - let _11 := 96 mstore(add(memPtr_1, 96), "stringlongstringlongstringlongst") mstore(add(memPtr_1, 128), "ring") let memPos := mload(_9) @@ -108,11 +108,7 @@ object "C_59" { mstore(add(memPos, _3), _9) let length := mload(memPtr_1) mstore(add(memPos, _9), length) - let i := 0 - for { } lt(i, length) { i := add(i, _3) } - { - mstore(add(add(memPos, i), _11), mload(add(add(memPtr_1, i), _3))) - } + mcopy(add(memPos, 96), _11, length) mstore(add(add(memPos, length), 96), 0) return(memPos, add(sub(add(memPos, and(add(length, 31), _8)), memPos), 96)) } diff --git a/test/cmdlineTests/standard_metadata/output.json b/test/cmdlineTests/standard_metadata/output.json index 4429466676d1..955d30c34475 100644 --- a/test/cmdlineTests/standard_metadata/output.json +++ b/test/cmdlineTests/standard_metadata/output.json @@ -5,7 +5,7 @@ { "C": { - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" + "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\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" } } }, diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json index ac01fb1eba9c..aae6d02f6b41 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json @@ -40,7 +40,7 @@ "x()": "0c55699c" } }, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", "storageLayout": { "storage": [], diff --git a/test/cmdlineTests/viair_subobject_optimization/output b/test/cmdlineTests/viair_subobject_optimization/output index 4804d138434c..5090c282bb24 100644 --- a/test/cmdlineTests/viair_subobject_optimization/output +++ b/test/cmdlineTests/viair_subobject_optimization/output @@ -117,77 +117,70 @@ sub_0: assembly { tag_3: jumpi(tag_7, callvalue) jumpi(tag_7, slt(add(not(0x03), calldatasize), 0x00)) - not(0x1f) /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ dataSize(sub_0) /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - 0x3f + swap1 + not(0x1f) + swap1 dup2 + 0x3f + dup5 add - dup3 and - dup4 + dup2 add - swap1 + swap2 + dup2 dup4 - dup3 lt 0xffffffffffffffff - dup4 + dup5 gt or tag_9 jumpi - swap3 - swap1 - 0x40 - swap1 0x40 + swap3 + dup4 mstore /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ dup4 dup3 mstore 0x20 + dup3 + add swap4 dataOffset(sub_0) - 0x20 - dup5 - add + dup6 codecopy /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - mload(0x40) + 0x1f + dup4 + mload + swap5 + dup6 swap4 - dup5 - swap3 /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ 0x20 /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - dup5 + dup6 mstore - dup1 mload - swap3 - dup4 + dup1 + swap2 + dup2 /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ 0x20 /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - dup7 + dup8 add mstore - 0x00 - tag_11: - dup5 - dup2 - lt - tag_12 - jumpi - dup6 - 0x40 - dup2 - dup10 - 0x1f - dup10 + dup7 + dup7 + add + mcopy 0x00 dup6 dup3 @@ -203,25 +196,6 @@ sub_0: assembly { add swap1 return - tag_12: - dup3 - dup2 - add - dup5 - add - mload - dup9 - dup3 - add - dup4 - add - mstore - dup8 - swap6 - pop - dup4 - add - jump(tag_11) tag_9: mstore(0x00, shl(0xe0, 0x4e487b71)) mstore(0x04, 0x41) diff --git a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output index 9ee68107929a..6873abe60e47 100644 --- a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output @@ -130,4 +130,4 @@ object "C_28" { } Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":"C"},"evmVersion":"shanghai","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} diff --git a/test/cmdlineTests/yul_string_format_ascii/output.json b/test/cmdlineTests/yul_string_format_ascii/output.json index aa830d1abe9d..edb76c0cd405 100644 --- a/test/cmdlineTests/yul_string_format_ascii/output.json +++ b/test/cmdlineTests/yul_string_format_ascii/output.json @@ -96,12 +96,10 @@ object \"C_11\" { } function copy_memory_to_memory_with_cleanup(src, dst, length) { - let i := 0 - for { } lt(i, length) { i := add(i, 32) } - { - mstore(add(dst, i), mload(add(src, i))) - } + + mcopy(dst, src, length) mstore(add(dst, length), 0) + } function round_up_to_mul_of_32(value) -> result { diff --git a/test/cmdlineTests/yul_string_format_ascii_long/output.json b/test/cmdlineTests/yul_string_format_ascii_long/output.json index 348e5a0b578c..36d6cfd954e9 100644 --- a/test/cmdlineTests/yul_string_format_ascii_long/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_long/output.json @@ -96,12 +96,10 @@ object \"C_11\" { } function copy_memory_to_memory_with_cleanup(src, dst, length) { - let i := 0 - for { } lt(i, length) { i := add(i, 32) } - { - mstore(add(dst, i), mload(add(src, i))) - } + + mcopy(dst, src, length) mstore(add(dst, length), 0) + } function round_up_to_mul_of_32(value) -> result { diff --git a/test/compilationTests/corion/ico.sol b/test/compilationTests/corion/ico.sol index b9fc0679fed7..fc90b4d5a7eb 100644 --- a/test/compilationTests/corion/ico.sol +++ b/test/compilationTests/corion/ico.sol @@ -284,7 +284,7 @@ contract ico is safeMath { require( buy(payable(msg.sender), address(0x00)) ); } - function buy(address payable beneficiaryAddress, address affilateAddress) public payable returns (bool success) { + function buy(address payable beneficiaryAddress, address affiliateAddress) public payable returns (bool success) { /* Buying a token @@ -297,12 +297,12 @@ contract ico is safeMath { More than 1e10 token: 3% More than 1e9 token: 2% below 1% @beneficiaryAddress The address of the accredited where the token will be sent. - @affilateAddress The address of the person who offered who will get the referral reward. It can not be equal with the beneficiaryAddress. + @affiliateAddress The address of the person who offered who will get the referral reward. It can not be equal with the beneficiaryAddress. */ require( isICO() ); if ( beneficiaryAddress == address(0x00)) { beneficiaryAddress = payable(msg.sender); } - if ( beneficiaryAddress == affilateAddress ) { - affilateAddress = address(0x00); + if ( beneficiaryAddress == affiliateAddress ) { + affiliateAddress = address(0x00); } uint256 _value = msg.value; if ( beneficiaryAddress.balance < 0.2 trx ) { @@ -317,9 +317,9 @@ contract ico is safeMath { totalMint = safeAdd(totalMint, _reward); require( foundationAddress.send(_value * 10 / 100) ); uint256 extra; - if ( affilateAddress != address(0x00) && ( brought[affilateAddress].eth > 0 || interestDB[affilateAddress][0].amount > 0 ) ) { - affiliate[affilateAddress].weight = safeAdd(affiliate[affilateAddress].weight, _reward); - extra = affiliate[affilateAddress].weight; + if ( affiliateAddress != address(0x00) && ( brought[affiliateAddress].eth > 0 || interestDB[affiliateAddress][0].amount > 0 ) ) { + affiliate[affiliateAddress].weight = safeAdd(affiliate[affiliateAddress].weight, _reward); + extra = affiliate[affiliateAddress].weight; uint256 rate; if (extra >= 1e12) { rate = 5; @@ -332,12 +332,12 @@ contract ico is safeMath { } else { rate = 1; } - extra = safeSub(extra * rate / 100, affiliate[affilateAddress].paid); - affiliate[affilateAddress].paid = safeAdd(affiliate[affilateAddress].paid, extra); - token(tokenAddr).mint(affilateAddress, extra); + extra = safeSub(extra * rate / 100, affiliate[affiliateAddress].paid); + affiliate[affiliateAddress].paid = safeAdd(affiliate[affiliateAddress].paid, extra); + token(tokenAddr).mint(affiliateAddress, extra); } checkPremium(beneficiaryAddress); - emit EICO(beneficiaryAddress, _reward, affilateAddress, extra); + emit EICO(beneficiaryAddress, _reward, affiliateAddress, extra); return true; } @@ -372,5 +372,5 @@ contract ico is safeMath { return startBlock <= block.number && block.number <= icoDelay && ( ! aborted ) && ( ! closed ); } - event EICO(address indexed Address, uint256 indexed value, address Affiliate, uint256 AffilateValue); + event EICO(address indexed Address, uint256 indexed value, address Affiliate, uint256 AffiliateValue); } diff --git a/test/evmc/evmc.h b/test/evmc/evmc.h index 48b03e554556..571c97f474e0 100644 --- a/test/evmc/evmc.h +++ b/test/evmc/evmc.h @@ -1181,7 +1181,7 @@ struct evmc_vm * * @par Binaries naming convention * For VMs distributed as shared libraries, the name of the library SHOULD match the VM name. - * The convetional library filename prefixes and extensions SHOULD be ignored by the Client. + * The conventional library filename prefixes and extensions SHOULD be ignored by the Client. * For example, the shared library with the "beta-interpreter" implementation may be named * `libbeta-interpreter.so`. * diff --git a/test/externalTests/bleeps.sh b/test/externalTests/bleeps.sh index 30f0ec9240b9..5a987e45933e 100755 --- a/test/externalTests/bleeps.sh +++ b/test/externalTests/bleeps.sh @@ -38,7 +38,6 @@ function test_fn { HARDHAT_DEPLOY_FIXTURE=true npx --no hardhat --no-compile tes function bleeps_test { local repo="https://github.com/wighawag/bleeps" - local ref_type=branch local ref=main local config_file="hardhat.config.ts" local config_var=config @@ -48,7 +47,7 @@ function bleeps_test "${compile_only_presets[@]}" #ir-no-optimize # Compilation fails with: "YulException: Variable expr_15509_mpos is 4 too deep in the stack". No memoryguard was present. #ir-optimize-evm-only # Compilation fails with: "YulException: Variable expr_15260_mpos is 4 too deep in the stack". No memoryguard was present. - ir-optimize-evm+yul + #ir-optimize-evm+yul # Compilation fails with: "YulException: Variable expr_15208_mpos is 1 too deep in the stack". No memoryguard was present. #legacy-no-optimize # Compilation fails with: "CompilerError: Stack too deep, try removing local variables." #legacy-optimize-evm-only # Compilation fails with: "CompilerError: Stack too deep, try removing local variables." legacy-optimize-evm+yul @@ -58,7 +57,7 @@ function bleeps_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" pushd "common-lib/" neutralize_package_json_hooks diff --git a/test/externalTests/brink.sh b/test/externalTests/brink.sh index 1c3ad2e19a13..d8ad001ac014 100755 --- a/test/externalTests/brink.sh +++ b/test/externalTests/brink.sh @@ -37,8 +37,7 @@ function test_fn { SNAPSHOT_UPDATE=1 npx --no hardhat test; } function brink_test { local repo="https://github.com/brinktrade/brink-core" - local ref_type=branch - local ref=master + local ref="" local config_file="hardhat.config.js" local config_var="" local extra_settings="metadata: {bytecodeHash: 'none'}" @@ -60,7 +59,7 @@ function brink_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # TODO: Remove this when Brink merges https://github.com/brinktrade/brink-core/pull/52 sed -i "s|\(function isValidSignature(bytes \)calldata\( _data, bytes \)calldata\( _signature)\)|\1memory\2memory\3|g" src/Test/MockEIP1271Validator.sol @@ -72,13 +71,7 @@ function brink_test yarn install yarn add hardhat-gas-reporter - # TODO: Remove when https://github.com/brinktrade/brink-core/issues/48 is fixed. - # TODO: Chai is ESM-only since version 5.x (see: https://github.com/chaijs/chai/issues/1561#issuecomment-1871134261), - # thus, we should stick to version 4.x until Brink and other dependencies also migrate to ESM. - yarn add chai@4.4.0 - replace_version_pragmas - for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" "$extra_settings" "$extra_optimizer_settings" store_benchmark_report hardhat brink "$repo" "$preset" diff --git a/test/externalTests/chainlink.sh b/test/externalTests/chainlink.sh index 4d5080730f80..f11156713c76 100755 --- a/test/externalTests/chainlink.sh +++ b/test/externalTests/chainlink.sh @@ -37,7 +37,6 @@ function test_fn { yarn test; } function chainlink_test { local repo="https://github.com/solidity-external-tests/chainlink" - local ref_type=branch local ref=develop_080 local config_file="hardhat.config.ts" local config_var=config @@ -58,7 +57,7 @@ function chainlink_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" cd "contracts/" diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index 402865107a8d..1dcd7deaa399 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -37,7 +37,6 @@ function test_fn { yarn run test:contracts; } function colony_test { local repo="https://github.com/solidity-external-tests/colonyNetwork.git" - local ref_type=branch local ref="develop_080" local config_file="truffle.js" @@ -57,7 +56,7 @@ function colony_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" neutralize_package_json_hooks diff --git a/test/externalTests/elementfi.sh b/test/externalTests/elementfi.sh index 94e622d10c5a..f34a169e9512 100755 --- a/test/externalTests/elementfi.sh +++ b/test/externalTests/elementfi.sh @@ -37,8 +37,7 @@ function test_fn { npm run test; } function elementfi_test { local repo="https://github.com/element-fi/elf-contracts" - local ref_type=branch - local ref=main + local ref="" local config_file="hardhat.config.ts" local config_var=config @@ -60,7 +59,7 @@ function elementfi_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" chmod +x scripts/load-balancer-contracts.sh scripts/load-balancer-contracts.sh @@ -100,9 +99,7 @@ function elementfi_test # "ProviderError: Too Many Requests error received from eth-mainnet.alchemyapi.io" rm test/mockERC20YearnVaultTest.ts - # Several tests fail unless we use the exact versions hard-coded in package-lock.json - #neutralize_package_lock - + neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index aee291a1a468..a011dd2a720c 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -37,7 +37,6 @@ function test_fn { yarn test; } function ens_test { local repo="https://github.com/ensdomains/ens-contracts.git" - local ref_type=commit local ref="083d29a2c50cd0a8307386abf8fadc217b256256" local config_file="hardhat.config.js" @@ -57,7 +56,7 @@ function ens_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" neutralize_package_lock neutralize_package_json_hooks @@ -81,7 +80,7 @@ function ens_test sed -i "s|it\(('Cannot be called if CANNOT_CREATE_SUBDOMAIN is burned and is a new subdomain',\)|it.skip\1|g" test/wrapper/NameWrapper.js sed -i "s|it\(('Cannot be called if PARENT_CANNOT_CONTROL is burned and is an existing subdomain',\)|it.skip\1|g" test/wrapper/NameWrapper.js - find . -name "*.sol" -exec sed -i -e 's/^\(\s*\)\(assembly\)/\1\/\/\/ @solidity memory-safe-assembly\n\1\2/' '{}' \; + find . -name "*.sol" -type f -exec sed -i -e 's/^\(\s*\)\(assembly\)/\1\/\/\/ @solidity memory-safe-assembly\n\1\2/' '{}' \; for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn diff --git a/test/externalTests/euler.sh b/test/externalTests/euler.sh index 80f18e702d92..9ede1a340673 100755 --- a/test/externalTests/euler.sh +++ b/test/externalTests/euler.sh @@ -40,7 +40,6 @@ function test_fn { function euler_test { local repo="https://github.com/euler-xyz/euler-contracts" - local ref_type=branch local ref="master" local config_file="hardhat.config.js" @@ -59,7 +58,7 @@ function euler_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 5f7ea4876527..416d36153623 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -37,8 +37,7 @@ function test_fn { npm test; } function gnosis_safe_test { local repo="https://github.com/safe-global/safe-contracts.git" - local ref_type=branch - local ref=main + local ref="" local config_file="hardhat.config.ts" local config_var=userConfig @@ -58,7 +57,7 @@ function gnosis_safe_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" # NOTE: The patterns below intentionally have hard-coded versions. diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index bbb442226f62..20ea586f5f09 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -37,8 +37,7 @@ function test_fn { yarn test; } function gp2_test { local repo="https://github.com/cowprotocol/contracts.git" - local ref_type=branch - local ref=main + local ref="" local config_file="hardhat.config.ts" local config_var="config" @@ -58,24 +57,27 @@ function gp2_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" - neutralize_package_lock neutralize_package_json_hooks name_hardhat_default_export "$config_file" "$config_var" force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" force_hardhat_unlimited_contract_size "$config_file" "$config_var" yarn + # We require to install hardhat 2.20.0 due to support for evm version cancun, otherwise we get the following error: + # Invalid value {"blockGasLimit":12500000,"hardfork":"cancun","allowUnlimitedContractSize":true} for HardhatConfig.networks.hardhat - Expected a value of type HardhatNetworkConfig. + # See: https://github.com/NomicFoundation/hardhat/issues/4176 + yarn add hardhat@2.20.0 - # Workaround for error caused by the last release of hardhat-waffle@2.0.6 that bumps ethereum-waffle - # to version 4.0.10 and breaks gp2 build with the following error: - # - # Cannot find module 'ethereum-waffle/dist/cjs/src/deployContract' - # - # See: https://github.com/NomicFoundation/hardhat-waffle/commit/83ee9cb36ee59d0bedacbbd00043f030af104ad0 - yarn add '@nomiclabs/hardhat-waffle@2.0.5' + # Ignore bench directory which fails to compile with current hardhat and ethers versions. + # bench/trace/gas.ts:123:19 - error TS2339: Property 'equals' does not exist on type 'Uint8Array'. + jq '. + {"exclude": ["bench"]}' tsconfig.json > temp.json + mv temp.json tsconfig.json + + # Remove the config section that requires an Etherscan key. We don't need it just to run tests. + sed -i '/^ etherscan: {$/,/^ },$/d' hardhat.config.ts # Some dependencies come with pre-built artifacts. We want to build from scratch. rm -r node_modules/@gnosis.pm/safe-contracts/build/ @@ -104,7 +106,6 @@ function gp2_test sed -i 's|it\(("should revert when encoding invalid flags"\)|it.skip\1|g' test/GPv2Trade.test.ts replace_version_pragmas - for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" store_benchmark_report hardhat gp2 "$repo" "$preset" diff --git a/test/externalTests/perpetual-pools.sh b/test/externalTests/perpetual-pools.sh index 8d8dc34e212d..1d7bb8f33b3e 100755 --- a/test/externalTests/perpetual-pools.sh +++ b/test/externalTests/perpetual-pools.sh @@ -37,7 +37,6 @@ function test_fn { yarn test; } function perpetual_pools_test { local repo="https://github.com/solidity-external-tests/perpetual-pools-contracts" - local ref_type=branch local ref=pools-v2 local config_file="hardhat.config.ts" local config_var="config" @@ -57,7 +56,7 @@ function perpetual_pools_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. @@ -70,7 +69,12 @@ function perpetual_pools_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" force_hardhat_unlimited_contract_size "$config_file" "$config_var" + yarn install + # We set hardhat version to 2.20.0 since version 2.21.0 has issues with solidity-coverage plugin + # that often causes out-of-memory errors. + # See hardhat note about the issue here: https://github.com/NomicFoundation/hardhat/releases/tag/hardhat@2.21.0 + yarn add hardhat@2.20.0 replace_version_pragmas diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index 3f7141d9bade..0fc8aafbd69d 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -36,9 +36,8 @@ function test_fn { yarn test; } function pool_together_test { - local repo="https://github.com/pooltogether/v4-core" - local ref_type=branch - local ref=master + local repo="https://github.com/pooltogether/v4-core.git" + local ref="" local config_file="hardhat.config.ts" local config_var="config" @@ -57,17 +56,19 @@ function pool_together_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('should fail to return value if value passed does not fit in [0-9]\+ bits'\)|it.skip\1|g" test/libraries/ExtendedSafeCast.test.ts sed -i "s|it\(('should require an rng to be requested'\)|it.skip\1|g" test/DrawBeacon.test.ts - neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" yarn install + # Hardhat 2.20.0 is the last version that works. Newer versions throw this error: + # Unexpected config HardhatConfig.networks.hardhat.initialBaseFeePerGas found - This field is only valid for networks with EIP-1559. Try a newer hardfork or remove it. + yarn add hardhat@2.20.0 # These come with already compiled artifacts. We want them recompiled with latest compiler. rm -r node_modules/@pooltogether/yield-source-interface/artifacts/ diff --git a/test/externalTests/prb-math.py b/test/externalTests/prb-math.py index e57688ec2e38..2d1469fc9015 100755 --- a/test/externalTests/prb-math.py +++ b/test/externalTests/prb-math.py @@ -51,8 +51,7 @@ def configure(self): test_config = TestConfig( name="PRBMath", repo_url="https://github.com/PaulRBerg/prb-math.git", - ref_type="branch", - ref="main", + ref="", compile_only_presets=[ # pylint: disable=line-too-long # SettingsPreset.IR_NO_OPTIMIZE, # Error: Yul exception:Variable expr_15699_address is 2 slot(s) too deep inside the stack. Stack too deep. diff --git a/test/externalTests/trident.sh b/test/externalTests/trident.sh index d8d94eb3c101..e5fa914e9cb8 100755 --- a/test/externalTests/trident.sh +++ b/test/externalTests/trident.sh @@ -45,7 +45,6 @@ function test_fn { function trident_test { local repo="https://github.com/sushiswap/trident" - local ref_type=commit # FIXME: Switch back to master branch when https://github.com/sushiswap/trident/issues/303 gets fixed. local ref="0cab5ae884cc9a41223d52791be775c3a053cb26" # master as of 2021-12-16 local config_file="hardhat.config.ts" @@ -66,7 +65,7 @@ function trident_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # TODO: Currently tests work only with the exact versions from yarn.lock. # Re-enable this when https://github.com/sushiswap/trident/issues/284 is fixed. diff --git a/test/externalTests/uniswap.sh b/test/externalTests/uniswap.sh index 8d2551b61920..04f27ab3f77f 100755 --- a/test/externalTests/uniswap.sh +++ b/test/externalTests/uniswap.sh @@ -37,7 +37,6 @@ function test_fn { UPDATE_SNAPSHOT=1 npx hardhat test; } function uniswap_test { local repo="https://github.com/solidity-external-tests/uniswap-v3-core.git" - local ref_type=branch local ref=main_080 local config_file="hardhat.config.ts" local config_var=config @@ -57,7 +56,7 @@ function uniswap_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. @@ -91,6 +90,11 @@ function uniswap_test # TODO: Remove when https://github.com/ethers-io/ethers.js/discussions/2849 is resolved. yarn add ethers@5.6.1 + # We set hardhat version to 2.20.0 since version 2.21.0 has issues with solidity-coverage plugin + # that often causes out-of-memory errors. + # See hardhat note about the issue here: https://github.com/NomicFoundation/hardhat/releases/tag/hardhat@2.21.0 + yarn add hardhat@2.20.0 + replace_version_pragmas for preset in $SELECTED_PRESETS; do diff --git a/test/externalTests/yield-liquidator.sh b/test/externalTests/yield-liquidator.sh index 7a4353af578e..16a6287e53dd 100755 --- a/test/externalTests/yield-liquidator.sh +++ b/test/externalTests/yield-liquidator.sh @@ -37,7 +37,6 @@ function test_fn { npm run test; } function yield_liquidator_test { local repo="https://github.com/yieldprotocol/yield-liquidator-v2" - local ref_type=branch local ref="master" local config_file="hardhat.config.ts" local config_var="module.exports" @@ -57,7 +56,7 @@ function yield_liquidator_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" neutralize_package_lock neutralize_package_json_hooks diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 54d753347573..64c901f61428 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -42,8 +42,7 @@ function test_fn { npm test; } function zeppelin_test { local repo="https://github.com/OpenZeppelin/openzeppelin-contracts.git" - local ref_type=branch - local ref="master" + local ref="" local config_file="hardhat.config.js" local compile_only_presets=( @@ -62,7 +61,7 @@ function zeppelin_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. @@ -96,18 +95,22 @@ function zeppelin_test sed -i "s|it(\('calling upgradeToAndCall on the implementation reverts'\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js sed -i "s|it(\('calling upgradeTo from a contract that is not an ERC1967 proxy\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js sed -i "s|it(\('calling upgradeToAndCall from a contract that is not an ERC1967 proxy\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js + sed -i "s|it(\('rejects overflow'\)|it.skip(\1|g" test/token/ERC20/ERC20.test.js + sed -i "s|it(\('decimals overflow'\)|it.skip(\1|g" test/token/ERC20/extensions/ERC4626.test.js # Here only the testToInt(248) and testToInt(256) cases fail so change the loop range to skip them sed -i "s|range(8, 256, 8)\(.forEach(bits => testToInt(bits));\)|range(8, 240, 8)\1|" test/utils/math/SafeCast.test.js - neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" npm install + # We require to install hardhat 2.20.0 due to support for evm version cancun, otherwise we get the following error: + # Invalid value {"blockGasLimit":10000000,"allowUnlimitedContractSize":true,"hardfork":"cancun"} for HardhatConfig.networks.hardhat - Expected a value of type HardhatNetworkConfig. + # See: https://github.com/NomicFoundation/hardhat/issues/4176 + npm install hardhat@2.20.0 replace_version_pragmas - for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn store_benchmark_report hardhat zeppelin "$repo" "$preset" diff --git a/test/libsolidity/GasCosts.cpp b/test/libsolidity/GasCosts.cpp index 520732810195..d8dad9e02705 100644 --- a/test/libsolidity/GasCosts.cpp +++ b/test/libsolidity/GasCosts.cpp @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(string_storage) if (CommonOptions::get().useABIEncoderV1) CHECK_DEPLOY_GAS(133045, 129731, evmVersion); else - CHECK_DEPLOY_GAS(144999, 121229, evmVersion); + CHECK_DEPLOY_GAS(144995, 121229, evmVersion); } // This is only correct on >=Constantinople. else if (!CommonOptions::get().useABIEncoderV1) @@ -110,22 +110,22 @@ BOOST_AUTO_TEST_CASE(string_storage) { // Costs with 0 are cases which cannot be triggered in tests. if (evmVersion < EVMVersion::istanbul()) - CHECK_DEPLOY_GAS(0, 109241, evmVersion); + CHECK_DEPLOY_GAS(0, 109237, evmVersion); else if (evmVersion < EVMVersion::shanghai()) - CHECK_DEPLOY_GAS(0, 97697, evmVersion); + CHECK_DEPLOY_GAS(0, 97693, evmVersion); // Shanghai is cheaper due to `push0` else - CHECK_DEPLOY_GAS(0, 97071, evmVersion); + CHECK_DEPLOY_GAS(0, 97067, evmVersion); } else { if (evmVersion < EVMVersion::istanbul()) - CHECK_DEPLOY_GAS(139013, 123969, evmVersion); + CHECK_DEPLOY_GAS(139009, 123969, evmVersion); else if (evmVersion < EVMVersion::shanghai()) - CHECK_DEPLOY_GAS(123361, 110969, evmVersion); + CHECK_DEPLOY_GAS(123357, 110969, evmVersion); // Shanghai is cheaper due to `push0` else - CHECK_DEPLOY_GAS(121493, 110969, evmVersion); + CHECK_DEPLOY_GAS(121489, 110969, evmVersion); } } else if (evmVersion < EVMVersion::istanbul()) @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(string_storage) else if (evmVersion < EVMVersion::shanghai()) CHECK_DEPLOY_GAS(114077, 96461, evmVersion); else - CHECK_DEPLOY_GAS(114077, 95835, evmVersion); + CHECK_DEPLOY_GAS(114077, 95831, evmVersion); if (evmVersion >= EVMVersion::byzantium()) { diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 25113b689d17..381ec5bda54e 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -569,6 +569,11 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp (_compileViaYul ? "ir"s : "legacy"s) + (m_optimiserSettings == OptimiserSettings::full() ? "Optimized" : ""); + soltestAssert( + io_test.call().expectations.gasUsedExcludingCode.count(setting) == + io_test.call().expectations.gasUsedForCodeDeposit.count(setting) + ); + // We don't check gas if enforce gas cost is not active // or test is run with abi encoder v1 only // or gas used less than threshold for enforcing feature @@ -579,17 +584,23 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp !m_enforceGasCost || m_gasUsed < m_enforceGasCostMinValue || m_gasUsed >= InitialGas || - (setting == "ir" && io_test.call().expectations.gasUsed.count(setting) == 0) || + (setting == "ir" && io_test.call().expectations.gasUsedExcludingCode.count(setting) == 0) || io_test.call().kind == FunctionCall::Kind::Builtin ) return true; solAssert(!m_runWithABIEncoderV1Only, ""); - io_test.setGasCost(setting, m_gasUsed); + // NOTE: Cost excluding code is unlikely to be negative but it may still be possible due to refunds. + // We'll deal with it when we actually have a test case like that. + solUnimplementedAssert(m_gasUsed >= m_gasUsedForCodeDeposit); + io_test.setGasCostExcludingCode(setting, m_gasUsed - m_gasUsedForCodeDeposit); + io_test.setCodeDepositGasCost(setting, m_gasUsedForCodeDeposit); + return - io_test.call().expectations.gasUsed.count(setting) > 0 && - m_gasUsed == io_test.call().expectations.gasUsed.at(setting); + io_test.call().expectations.gasUsedExcludingCode.count(setting) > 0 && + m_gasUsed - m_gasUsedForCodeDeposit == io_test.call().expectations.gasUsedExcludingCode.at(setting) && + m_gasUsedForCodeDeposit == io_test.call().expectations.gasUsedForCodeDeposit.at(setting); } void SemanticTest::printSource(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index ab013692d5ea..7fafa2a62e08 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1050,9 +1050,11 @@ BOOST_AUTO_TEST_CASE(evm_version) BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"paris\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"shanghai\",")); BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"shanghai\"") != std::string::npos); + result = compile(inputForVersion("\"evmVersion\": \"cancun\",")); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"cancun\"") != std::string::npos); // test default result = compile(inputForVersion("")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"shanghai\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"cancun\"") != std::string::npos); // test invalid result = compile(inputForVersion("\"evmVersion\": \"invalid\",")); BOOST_CHECK(result["errors"][0]["message"].asString() == "Invalid EVM version requested."); diff --git a/test/libsolidity/gasTests/abiv2.sol b/test/libsolidity/gasTests/abiv2.sol index aacb333bfeca..6fa822fade47 100644 --- a/test/libsolidity/gasTests/abiv2.sol +++ b/test/libsolidity/gasTests/abiv2.sol @@ -14,9 +14,9 @@ contract C { } // ---- // creation: -// codeDepositCost: 1213200 -// executionCost: 1259 -// totalCost: 1214459 +// codeDepositCost: 1208000 +// executionCost: 1252 +// totalCost: 1209252 // external: // a(): 2425 // b(uint256): infinite diff --git a/test/libsolidity/gasTests/abiv2_optimised.sol b/test/libsolidity/gasTests/abiv2_optimised.sol index 1ab8803d28b2..8f407e6ede24 100644 --- a/test/libsolidity/gasTests/abiv2_optimised.sol +++ b/test/libsolidity/gasTests/abiv2_optimised.sol @@ -17,9 +17,9 @@ contract C { // optimize-yul: true // ---- // creation: -// codeDepositCost: 639000 +// codeDepositCost: 634600 // executionCost: 668 -// totalCost: 639668 +// totalCost: 635268 // external: // a(): 2283 // b(uint256): 4649 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol index f548c50bcf52..3dd5dd269340 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol @@ -59,10 +59,10 @@ contract C { // EVMVersion: >homestead // ---- // test_bytes() -> -// gas irOptimized: 321332 -// gas legacy: 319111 -// gas legacyOptimized: 269317 +// gas irOptimized: 306908 +// gas legacy: 305827 +// gas legacyOptimized: 255013 // test_uint256() -> -// gas irOptimized: 447646 -// gas legacy: 433627 -// gas legacyOptimized: 365410 +// gas irOptimized: 435054 +// gas legacy: 421315 +// gas legacyOptimized: 352838 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol index 686164de856a..5457e7f6743e 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol @@ -60,10 +60,10 @@ contract C { // EVMVersion: >homestead // ---- // test_bytes() -> -// gas irOptimized: 321332 -// gas legacy: 319111 -// gas legacyOptimized: 269317 +// gas irOptimized: 306908 +// gas legacy: 305827 +// gas legacyOptimized: 255013 // test_uint256() -> -// gas irOptimized: 447646 -// gas legacy: 433627 -// gas legacyOptimized: 365410 +// gas irOptimized: 435054 +// gas legacy: 421315 +// gas legacyOptimized: 352838 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol index 5e50d5e9a807..c0d5f5d3fb9c 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol @@ -50,6 +50,6 @@ contract C { // f2() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3 -// gas irOptimized: 112630 -// gas legacy: 114794 -// gas legacyOptimized: 112572 +// gas irOptimized: 111708 +// gas legacy: 113892 +// gas legacyOptimized: 111646 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol index 55f7991def80..c41905e2a491 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol @@ -30,6 +30,9 @@ contract C is B { } // ---- // test() -> 77 -// gas irOptimized: 110348 -// gas legacy: 151866 -// gas legacyOptimized: 110373 +// gas irOptimized: 55148 +// gas irOptimized code: 55200 +// gas legacy: 57266 +// gas legacy code: 94600 +// gas legacyOptimized: 55173 +// gas legacyOptimized code: 55200 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol index 7de26301205c..7a2395549b5f 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol @@ -39,4 +39,5 @@ contract C is B { // ---- // test() -> 5, 10 // gas irOptimized: 87337 -// gas legacy: 102651 +// gas legacy: 66251 +// gas legacy code: 36400 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol index 22aad67492e8..f749e403b567 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol @@ -20,6 +20,6 @@ contract C { // f(uint256[][1]): 32, 32, 0 -> true // f(uint256[][1]): 32, 32, 1, 42 -> true // f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true -// gas irOptimized: 120043 +// gas irOptimized: 117157 // gas legacy: 101568 // gas legacyOptimized: 119092 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol index a92336097172..46df313331e4 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol @@ -33,8 +33,8 @@ contract C { // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1, 5, 6 -> 0x20, 0x40, 5, 2 // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1 -> FAILURE // f_storage(uint256[],uint256[2]): 0x20, 1, 2 -> 0x20, 0x60, 0x20, 1, 2 -// gas irOptimized: 111642 -// gas legacy: 112944 -// gas legacyOptimized: 112092 +// gas irOptimized: 111395 +// gas legacy: 112709 +// gas legacyOptimized: 111852 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5, 6 -> 0x20, 0x80, 0x20, 2, 5, 6 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5 -> FAILURE diff --git a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol index 33075675358e..14699df57219 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol @@ -18,10 +18,10 @@ contract C { // EVMVersion: >homestead // ---- // h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324 -// gas irOptimized: 180720 -// gas legacy: 184830 -// gas legacyOptimized: 181493 +// gas irOptimized: 180103 +// gas legacy: 184235 +// gas legacyOptimized: 180873 // i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224 -// gas irOptimized: 112425 -// gas legacy: 115398 -// gas legacyOptimized: 112982 +// gas irOptimized: 112104 +// gas legacy: 115091 +// gas legacyOptimized: 112666 diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol index c06d2b24c457..9f59c43155ee 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol @@ -8,6 +8,6 @@ contract C { } // ---- // f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg" -// gas irOptimized: 135661 -// gas legacy: 137278 -// gas legacyOptimized: 136048 +// gas irOptimized: 135452 +// gas legacy: 137096 +// gas legacyOptimized: 135834 diff --git a/test/libsolidity/semanticTests/arithmetics/check_var_init.sol b/test/libsolidity/semanticTests/arithmetics/check_var_init.sol index 6cc02bd97580..9061cd284de9 100644 --- a/test/libsolidity/semanticTests/arithmetics/check_var_init.sol +++ b/test/libsolidity/semanticTests/arithmetics/check_var_init.sol @@ -16,4 +16,5 @@ contract D { // ---- // f() -> FAILURE, hex"4e487b71", 0x11 // g(), 100 wei -> 1 -// gas legacy: 100388 +// gas legacy: 76780 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol index ca65f070657c..19acb7cba14b 100644 --- a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol +++ b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol @@ -8,9 +8,12 @@ contract C { } // ---- // constructor(): 1, 2, 3 -> -// gas irOptimized: 139656 -// gas legacy: 180517 -// gas legacyOptimized: 150462 +// gas irOptimized: 124816 +// gas irOptimized code: 14800 +// gas legacy: 134317 +// gas legacy code: 46200 +// gas legacyOptimized: 127062 +// gas legacyOptimized code: 23400 // a(uint256): 0 -> 1 // a(uint256): 1 -> 2 // a(uint256): 2 -> 3 diff --git a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol index 38dbe52bccde..24565b4c62a6 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol @@ -17,25 +17,25 @@ contract c { // ---- // f(uint256): 0 -> 0x20, 0x00 // f(uint256): 31 -> 0x20, 0x1f, 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e00 -// gas irOptimized: 104476 -// gas legacy: 112974 -// gas legacyOptimized: 112717 +// gas irOptimized: 103283 +// gas legacy: 112883 +// gas legacyOptimized: 112629 // f(uint256): 32 -> 0x20, 0x20, 1780731860627700044960722568376592200742329637303199754547598369979440671 -// gas irOptimized: 118962 -// gas legacy: 129034 -// gas legacyOptimized: 128952 +// gas irOptimized: 117740 +// gas legacy: 128943 +// gas legacyOptimized: 128864 // f(uint256): 33 -> 0x20, 33, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x2000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 125419 -// gas legacy: 136234 -// gas legacyOptimized: 135643 +// gas irOptimized: 124080 +// gas legacy: 136071 +// gas legacyOptimized: 135479 // f(uint256): 63 -> 0x20, 0x3f, 1780731860627700044960722568376592200742329637303199754547598369979440671, 14532552714582660066924456880521368950258152170031413196862950297402215316992 -// gas irOptimized: 129529 -// gas legacy: 148834 -// gas legacyOptimized: 148873 +// gas irOptimized: 127140 +// gas legacy: 148671 +// gas legacyOptimized: 148709 // f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000 // gas legacy: 59345 // gas legacyOptimized: 57279 // f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968 -// gas irOptimized: 421911 -// gas legacy: 459355 -// gas legacyOptimized: 461066 +// gas irOptimized: 416966 +// gas legacy: 458976 +// gas legacyOptimized: 460674 diff --git a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol index d2361dac5462..36b94d7c3974 100644 --- a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol +++ b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol @@ -16,7 +16,10 @@ contract C { } // ---- // constructor() -// gas irOptimized: 226349 -// gas legacy: 215757 -// gas legacyOptimized: 181760 +// gas irOptimized: 89121 +// gas irOptimized code: 137200 +// gas legacy: 89553 +// gas legacy code: 126200 +// gas legacyOptimized: 83556 +// gas legacyOptimized code: 98200 // f() -> 0 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol index 5482f615f241..33a4c7045af5 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol @@ -35,12 +35,12 @@ contract C { } // ---- // f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000 -// gas irOptimized: 179750 -// gas legacy: 181001 -// gas legacyOptimized: 180018 +// gas irOptimized: 179420 +// gas legacy: 180675 +// gas legacyOptimized: 179700 // g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000 -// gas irOptimized: 106679 -// gas legacy: 109720 -// gas legacyOptimized: 106932 +// gas irOptimized: 106349 +// gas legacy: 109394 +// gas legacyOptimized: 106614 // h() -> 0x40, 0x60, 0x00, 0x00 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol index 275a0fca1b75..56a415079084 100644 --- a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol @@ -46,11 +46,11 @@ contract C { } // ---- // test() -> 0x20, 0x14, "[a called][b called]" -// gas irOptimized: 116645 -// gas legacy: 118936 -// gas legacyOptimized: 116975 +// gas irOptimized: 116546 +// gas legacy: 118845 +// gas legacyOptimized: 116887 // test2() -> 0x20, 0x14, "[b called][a called]" // test3() -> 0x20, 0x14, "[b called][a called]" -// gas irOptimized: 103246 -// gas legacy: 102745 -// gas legacyOptimized: 101669 +// gas irOptimized: 103147 +// gas legacy: 102654 +// gas legacyOptimized: 101581 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol index 211477c553c2..0e8cff97fd57 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol @@ -11,6 +11,6 @@ contract C { } // ---- // f() -> 0x20, 0x02, 0x40, 0x80, 3, 0x6162630000000000000000000000000000000000000000000000000000000000, 0x99, 44048183304486788312148433451363384677562265908331949128489393215789685032262, 32241931068525137014058842823026578386641954854143559838526554899205067598957, 49951309422467613961193228765530489307475214998374779756599339590522149884499, 0x54555658595a6162636465666768696a6b6c6d6e6f707172737475767778797a, 0x4142434445464748494a4b4c4d4e4f5051525354555658595a00000000000000 -// gas irOptimized: 202731 -// gas legacy: 204798 -// gas legacyOptimized: 203357 +// gas irOptimized: 202162 +// gas legacy: 204328 +// gas legacyOptimized: 202887 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol index dd90985735b3..0fb513543bea 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol @@ -18,6 +18,9 @@ contract B { } // ---- // f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004 -// gas irOptimized: 114404 -// gas legacy: 230001 -// gas legacyOptimized: 130637 +// gas irOptimized: 59204 +// gas irOptimized code: 55200 +// gas legacy: 68001 +// gas legacy code: 162000 +// gas legacyOptimized: 60037 +// gas legacyOptimized code: 70600 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol index ac11d779a563..0eb0f1e90e7d 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol @@ -9,8 +9,11 @@ contract Creator { } // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 126363 -// gas legacy: 174186 -// gas legacyOptimized: 128709 +// gas irOptimized: 103927 +// gas irOptimized code: 22400 +// gas legacy: 115186 +// gas legacy code: 59000 +// gas legacyOptimized: 104909 +// gas legacyOptimized code: 23800 // r() -> 4 // ch() -> 3 diff --git a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol index 773e904cc095..e35e24bbf12a 100644 --- a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol +++ b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol @@ -42,6 +42,9 @@ contract C { } // ---- // test() -> 5, 6, 7 -// gas irOptimized: 255728 -// gas legacy: 440376 -// gas legacyOptimized: 278651 +// gas irOptimized: 86128 +// gas irOptimized code: 169600 +// gas legacy: 97576 +// gas legacy code: 342800 +// gas legacyOptimized: 87851 +// gas legacyOptimized code: 190800 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol index 5b1a61839183..674b0841e6b4 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol @@ -9,6 +9,6 @@ contract c { } // ---- // test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 107343 -// gas legacy: 121408 -// gas legacyOptimized: 120534 +// gas irOptimized: 107183 +// gas legacy: 121245 +// gas legacyOptimized: 120370 diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index 92b0c06bfb26..a7608f6e0c81 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -24,6 +24,9 @@ contract Main { } // ---- // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 -// gas irOptimized: 111924 -// gas legacy: 125162 -// gas legacyOptimized: 113012 +// gas irOptimized: 99524 +// gas irOptimized code: 12400 +// gas legacy: 101554 +// gas legacy code: 23600 +// gas legacyOptimized: 99612 +// gas legacyOptimized code: 13400 diff --git a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol index dc77f0dff83a..8d0cb0a01294 100644 --- a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol +++ b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol @@ -28,9 +28,12 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 443406 -// gas legacy: 711299 -// gas legacyOptimized: 482382 +// gas irOptimized: 81932 +// gas irOptimized code: 355200 +// gas legacy: 101472 +// gas legacy code: 604200 +// gas legacyOptimized: 85004 +// gas legacyOptimized code: 392400 // h() -> 0x20, 0x40, 0x00, 0 // ~ emit ev(uint256[],uint256): 0x40, 0x21, 0x02, 0x00, 0x00 // g() -> 0x20, 0x40, 0, 0x00 diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 3d9c1ffecefe..3e60ba451c8c 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -24,6 +24,9 @@ contract Creator { } // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 -// gas irOptimized: 424526 -// gas legacy: 581443 -// gas legacyOptimized: 444599 +// gas irOptimized: 328126 +// gas irOptimized code: 96400 +// gas legacy: 336626 +// gas legacy code: 244800 +// gas legacyOptimized: 329599 +// gas legacyOptimized code: 115000 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 067a64e0e5f6..c0b9df16c34d 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -24,6 +24,9 @@ contract Creator { } // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 275102 -// gas legacy: 418462 -// gas legacyOptimized: 291960 +// gas irOptimized: 169361 +// gas irOptimized code: 99200 +// gas legacy: 172944 +// gas legacy code: 239800 +// gas legacyOptimized: 169858 +// gas legacyOptimized code: 117000 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 0665cb807a7d..0918a970e272 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -8,8 +8,11 @@ contract Test { } // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> -// gas irOptimized: 269225 -// gas legacy: 311324 -// gas legacyOptimized: 258604 +// gas irOptimized: 180756 +// gas irOptimized code: 79200 +// gas legacy: 195165 +// gas legacy code: 109400 +// gas legacyOptimized: 181600 +// gas legacyOptimized code: 71400 // m_x() -> 7 // m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol index 3037aaa31753..8fa725dad569 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol @@ -17,8 +17,11 @@ contract Main { } // ---- // constructor(): "abc", true -// gas irOptimized: 104394 -// gas legacy: 143300 -// gas legacyOptimized: 102961 +// gas irOptimized: 80174 +// gas irOptimized code: 24200 +// gas legacy: 85100 +// gas legacy code: 58200 +// gas legacyOptimized: 80133 +// gas legacyOptimized code: 22800 // getFlag() -> true // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol index 4117b84b64f9..33650aff6fb6 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol @@ -17,4 +17,5 @@ contract C { } // ---- // f() -> 16 -// gas legacy: 102082 +// gas legacy: 78482 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index 22acd1cc3fab..e6ce445ada39 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -9,9 +9,12 @@ contract C { } // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 171015 -// gas legacy: 218378 -// gas legacyOptimized: 176211 +// gas irOptimized: 147975 +// gas irOptimized code: 23000 +// gas legacy: 157978 +// gas legacy code: 60400 +// gas legacyOptimized: 150011 +// gas legacyOptimized code: 26200 // a() -> 1 // b(uint256): 0 -> 2 // b(uint256): 1 -> 3 diff --git a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol index eec01005ebd2..b1dc80a408d8 100644 --- a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol +++ b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol @@ -17,6 +17,9 @@ contract C { } // ---- // f(), 2000 ether -> true -// gas irOptimized: 119441 -// gas legacy: 122621 -// gas legacyOptimized: 122490 +// gas irOptimized: 117641 +// gas irOptimized code: 1800 +// gas legacy: 117821 +// gas legacy code: 4800 +// gas legacyOptimized: 117690 +// gas legacyOptimized code: 4800 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol index 20cd8760b9b9..ef53142d458a 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol @@ -14,5 +14,6 @@ contract B is A { // compileViaYul: true // ---- // constructor() -> -// gas irOptimized: 119640 +// gas irOptimized: 99436 +// gas irOptimized code: 20200 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol index 820c56a4eea2..e19ad39cfad7 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol @@ -9,7 +9,10 @@ contract B is A { } // ---- // constructor() -> -// gas irOptimized: 119640 -// gas legacy: 133594 -// gas legacyOptimized: 115341 +// gas irOptimized: 99436 +// gas irOptimized code: 20200 +// gas legacy: 100974 +// gas legacy code: 32600 +// gas legacyOptimized: 99137 +// gas legacyOptimized code: 16200 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_with_params.sol b/test/libsolidity/semanticTests/constructor_with_params.sol index 1916f692fd1a..1c5a170202f3 100644 --- a/test/libsolidity/semanticTests/constructor_with_params.sol +++ b/test/libsolidity/semanticTests/constructor_with_params.sol @@ -9,7 +9,9 @@ contract C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 101390 -// gas legacy: 115678 +// gas irOptimized: 81170 +// gas irOptimized code: 20200 +// gas legacy: 83614 +// gas legacy code: 32000 // i() -> 2 // k() -> 0 diff --git a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol index b2f66e4500d8..29f401a77322 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol @@ -21,9 +21,12 @@ contract D is B, C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 151966 -// gas legacy: 168623 -// gas legacyOptimized: 144577 +// gas irOptimized: 124350 +// gas irOptimized code: 27600 +// gas legacy: 128223 +// gas legacy code: 40400 +// gas legacyOptimized: 123921 +// gas legacyOptimized code: 20600 // i() -> 2 // j() -> 2 // k() -> 1 diff --git a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol index f5b20d9816a0..b0373b74f193 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol @@ -12,8 +12,11 @@ contract D is C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 121805 -// gas legacy: 137193 -// gas legacyOptimized: 118548 +// gas irOptimized: 101581 +// gas irOptimized code: 20200 +// gas legacy: 105193 +// gas legacy code: 32000 +// gas legacyOptimized: 101504 +// gas legacyOptimized code: 17000 // i() -> 2 // k() -> 1 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 f8b5141b97fc..6a01d0019295 100644 --- a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol +++ b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol @@ -15,8 +15,11 @@ contract C { } // ---- // constructor() -> -// gas irOptimized: 165386 -// gas legacy: 244800 -// gas legacyOptimized: 171615 +// gas irOptimized: 113970 +// gas irOptimized code: 51400 +// gas legacy: 119776 +// gas legacy code: 125000 +// gas legacyOptimized: 114187 +// gas legacyOptimized code: 57400 // deposit(bytes32), 18 wei: 0x1234 -> // ~ emit Deposit(address,bytes32,uint256) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: #0xc06afe3a8444fc0004668591e8306bfb9968e79e, #0x1234, 0x00 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index f9f53275bba9..925ed54e6dc3 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -74,9 +74,12 @@ contract FixedFeeRegistrar is Registrar { } // ---- // constructor() -// gas irOptimized: 384610 -// gas legacy: 913421 -// gas legacyOptimized: 476928 +// gas irOptimized: 77654 +// gas irOptimized code: 302200 +// gas legacy: 115395 +// gas legacy code: 792400 +// gas legacyOptimized: 84566 +// gas legacyOptimized code: 387600 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 // gas irOptimized: 45967 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index 646601e6fb8b..aed2a11df22c 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -33,9 +33,12 @@ contract test { // EVMVersion: >=constantinople // ---- // constructor() -// gas irOptimized: 405832 -// gas legacy: 735054 -// gas legacyOptimized: 522722 +// gas irOptimized: 78952 +// gas irOptimized code: 320600 +// gas legacy: 102034 +// gas legacy code: 627400 +// gas legacyOptimized: 87950 +// gas legacyOptimized code: 429800 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 4f3342dea72f..ce77683aab73 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -176,35 +176,38 @@ contract DepositContract is IDepositContract, ERC165 { } // ---- // constructor() -// gas irOptimized: 1386886 -// gas legacy: 2369061 -// gas legacyOptimized: 1740144 +// gas irOptimized: 809248 +// gas irOptimized code: 558000 +// gas legacy: 919945 +// gas legacy code: 1437600 +// gas legacyOptimized: 848464 +// gas legacyOptimized code: 875200 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # // supportsInterface(bytes4): 0x8564090700000000000000000000000000000000000000000000000000000000 -> true # the deposit interface id # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 115231 -// gas legacy: 148205 -// gas legacyOptimized: 122303 +// gas irOptimized: 109009 +// gas legacy: 142735 +// gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 115231 -// gas legacy: 148205 -// gas legacyOptimized: 122303 +// gas irOptimized: 109009 +// gas legacy: 142735 +// gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 // get_deposit_root() -> 0x2089653123d9c721215120b6db6738ba273bbc5228ac093b1f983badcdc8a438 -// gas irOptimized: 115216 -// gas legacy: 148214 -// gas legacyOptimized: 122315 +// gas irOptimized: 108994 +// gas legacy: 142744 +// gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 // get_deposit_root() -> 0x40255975859377d912c53aa853245ebd939bdd2b33a28e084babdcc1ed8238ee -// gas irOptimized: 115216 -// gas legacy: 148214 -// gas legacyOptimized: 122315 +// gas irOptimized: 108994 +// gas legacy: 142744 +// gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index 3311a8dcf444..ddd63971836c 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -48,9 +48,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 1841740 -// gas legacy: 2414091 -// gas legacyOptimized: 1847616 +// gas irOptimized: 177336 +// gas irOptimized code: 1664400 +// gas legacy: 209687 +// gas legacy code: 2204400 +// gas legacyOptimized: 178012 +// gas legacyOptimized code: 1669600 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22137 // gas legacy: 22767 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index fb1d1a43524a..deacfd05641b 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -48,9 +48,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 1716327 -// gas legacy: 2193550 -// gas legacyOptimized: 1725061 +// gas irOptimized: 168523 +// gas irOptimized code: 1547800 +// gas legacy: 195146 +// gas legacy code: 1998400 +// gas legacyOptimized: 168857 +// gas legacyOptimized code: 1556200 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22004 // gas legacy: 22497 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 3f555405ddbb..cdaec8797eb7 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -33,9 +33,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 407507 -// gas legacy: 615090 -// gas legacyOptimized: 451871 +// gas irOptimized: 79503 +// gas irOptimized code: 328000 +// gas legacy: 92086 +// gas legacy code: 523000 +// gas legacyOptimized: 82667 +// gas legacyOptimized code: 369200 // prb_pi() -> 3141592656369545286 // gas irOptimized: 57478 // gas legacy: 100947 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 18d6db37df1e..102c85ae0fa8 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -49,9 +49,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 630224 -// gas legacy: 1061957 -// gas legacyOptimized: 718937 +// gas irOptimized: 95949 +// gas irOptimized code: 528000 +// gas legacy: 126106 +// gas legacy code: 930200 +// gas legacyOptimized: 102559 +// gas legacyOptimized code: 611400 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22660 // gas legacy: 23190 diff --git a/test/libsolidity/semanticTests/freeFunctions/new_operator.sol b/test/libsolidity/semanticTests/freeFunctions/new_operator.sol index dd44a1b5950c..d621629c3b49 100644 --- a/test/libsolidity/semanticTests/freeFunctions/new_operator.sol +++ b/test/libsolidity/semanticTests/freeFunctions/new_operator.sol @@ -13,4 +13,5 @@ contract D { } // ---- // f() -> 2 -// gas legacy: 100211 +// gas legacy: 76611 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_no_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_no_args.sol index b6a33fb7e835..6044065958a4 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_no_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_no_args.sol @@ -11,4 +11,5 @@ contract D { } // ---- // f() -> 2 -// gas legacy: 100185 +// gas legacy: 76585 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol index 39592f4a4882..1133dc2be300 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -15,7 +15,10 @@ contract D { } // ---- // constructor(): 2 -> -// gas irOptimized: 192703 -// gas legacy: 241234 -// gas legacyOptimized: 192961 +// gas irOptimized: 138863 +// gas irOptimized code: 53800 +// gas legacy: 145570 +// gas legacy code: 95600 +// gas legacyOptimized: 138297 +// gas legacyOptimized code: 54600 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol index 3850a0be7fd6..ba90a8ecd5a6 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -17,7 +17,10 @@ contract D { // EVMVersion: >=constantinople // ---- // constructor(): 2 -> -// gas irOptimized: 192866 -// gas legacy: 241606 -// gas legacyOptimized: 193193 +// gas irOptimized: 139026 +// gas irOptimized code: 53800 +// gas legacy: 145936 +// gas legacy code: 95600 +// gas legacyOptimized: 138529 +// gas legacyOptimized code: 54600 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index a1c74cf89838..5b254a9f6c2d 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -22,9 +22,12 @@ contract C { } // ---- // constructor(), 1 ether -> -// gas irOptimized: 262355 -// gas legacy: 441442 -// gas legacyOptimized: 292862 +// gas irOptimized: 89155 +// gas irOptimized code: 167800 +// gas legacy: 102626 +// gas legacy code: 333200 +// gas legacyOptimized: 91471 +// gas legacyOptimized code: 196200 // f(uint256): 0 -> FAILURE // f(uint256): 1 -> FAILURE // f(uint256): 2 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol index 96f097ce7f4a..8bf182a89ee8 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -25,9 +25,12 @@ contract C { // revertStrings: debug // ---- // constructor(), 1 ether -> -// gas irOptimized: 390464 -// gas legacy: 809985 -// gas legacyOptimized: 498331 +// gas irOptimized: 98842 +// gas irOptimized code: 286000 +// gas legacy: 123163 +// gas legacy code: 681200 +// gas legacyOptimized: 106957 +// gas legacyOptimized code: 386400 // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 1 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 2 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/functionCall/failed_create.sol b/test/libsolidity/semanticTests/functionCall/failed_create.sol index 091e5a77a62a..b6c077753a51 100644 --- a/test/libsolidity/semanticTests/functionCall/failed_create.sol +++ b/test/libsolidity/semanticTests/functionCall/failed_create.sol @@ -17,9 +17,12 @@ contract C { // EVMVersion: >=byzantium // ---- // constructor(), 20 wei -// gas irOptimized: 166148 -// gas legacy: 285547 -// gas legacyOptimized: 168515 +// 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 // x() -> 1 // f(uint256): 20 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index 79a829aa77ba..806c8eb41b9d 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -38,9 +38,12 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 252642 -// gas legacy: 391588 -// gas legacyOptimized: 268089 +// gas irOptimized: 120226 +// gas irOptimized code: 132400 +// gas legacy: 130568 +// gas legacy code: 261000 +// 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/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol index 71b6ebb2c7a3..c186fc40b22c 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -37,9 +37,12 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 252642 -// gas legacy: 391588 -// gas legacyOptimized: 268089 +// gas irOptimized: 120226 +// gas irOptimized code: 132400 +// gas legacy: 130568 +// gas legacy code: 261000 +// 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/functionCall/send_zero_ether.sol b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol index 18a19979295b..94a721323244 100644 --- a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol +++ b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol @@ -16,6 +16,7 @@ contract Main { // ---- // constructor(), 20 wei -> // gas irOptimized: 100264 -// gas legacy: 113411 +// gas legacy: 57555 +// gas legacy code: 53000 // gas legacyOptimized: 100361 // s() -> true diff --git a/test/libsolidity/semanticTests/functionTypes/store_function.sol b/test/libsolidity/semanticTests/functionTypes/store_function.sol index 132a6c95659a..5397d0b70187 100644 --- a/test/libsolidity/semanticTests/functionTypes/store_function.sol +++ b/test/libsolidity/semanticTests/functionTypes/store_function.sol @@ -26,5 +26,7 @@ contract C { // ---- // t() -> 9 // gas irOptimized: 99064 -// gas legacy: 149095 -// gas legacyOptimized: 106188 +// gas legacy: 79495 +// gas legacy code: 69600 +// gas legacyOptimized: 77588 +// gas legacyOptimized code: 28600 diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index 145c32add6e9..c8806c50d060 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -27,8 +27,11 @@ contract C { } // ---- // f() -> 3, 7, 5 -// gas irOptimized: 124021 -// gas legacy: 148528 -// gas legacyOptimized: 123971 +// gas irOptimized: 86821 +// gas irOptimized code: 37200 +// gas legacy: 87728 +// gas legacy code: 60800 +// gas legacyOptimized: 86771 +// gas legacyOptimized code: 37200 // x() -> 7 // y() -> 5 diff --git a/test/libsolidity/semanticTests/immutable/use_scratch.sol b/test/libsolidity/semanticTests/immutable/use_scratch.sol index 0a5ccf729f59..dc07086c29c3 100644 --- a/test/libsolidity/semanticTests/immutable/use_scratch.sol +++ b/test/libsolidity/semanticTests/immutable/use_scratch.sol @@ -15,8 +15,11 @@ contract C { } // ---- // constructor(): 3 -> -// gas irOptimized: 123542 -// gas legacy: 197645 -// gas legacyOptimized: 137678 +// gas irOptimized: 81126 +// gas irOptimized code: 42400 +// gas legacy: 88245 +// gas legacy code: 109400 +// gas legacyOptimized: 81858 +// gas legacyOptimized code: 55800 // f() -> 84, 23 // m(uint256): 3 -> 7 diff --git a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol index c65d1abec558..0865ed2876ad 100644 --- a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol +++ b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol @@ -21,7 +21,9 @@ contract D { // ---- // f() -> 1 // gas irOptimized: 77051 -// gas legacy: 112280 +// gas legacy: 54480 +// gas legacy code: 57800 // g() -> 5 // gas irOptimized: 77106 -// gas legacy: 112816 +// gas legacy: 55016 +// gas legacy code: 57800 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol index 3114c80f1912..0567c2ab1412 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol @@ -23,4 +23,5 @@ contract B { // ---- // g() -> 42 // gas irOptimized: 80813 -// gas legacy: 122471 +// gas legacy: 55871 +// gas legacy code: 66600 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol index 74bf42ec7e61..d5ff54b68a16 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol @@ -23,5 +23,7 @@ contract B { // ---- // g() -> 42 // gas irOptimized: 100282 -// gas legacy: 180440 -// gas legacyOptimized: 112596 +// gas legacy: 56840 +// gas legacy code: 123600 +// gas legacyOptimized: 54996 +// gas legacyOptimized code: 57600 diff --git a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol index 33392e8d48c6..e704a297bbac 100644 --- a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol +++ b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol @@ -19,6 +19,8 @@ contract A { } // ---- // g(int256): -1 -> -1 -// gas legacy: 102086 +// gas legacy: 77878 +// gas legacy code: 24200 // g(int256): 10 -> 10 -// gas legacy: 101714 +// gas legacy: 77506 +// gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index d8fd8766fec6..fdd0bafaadfe 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -39,9 +39,12 @@ contract Main { } // ---- // constructor(), 22 wei -> -// gas irOptimized: 261888 -// gas legacy: 392786 -// gas legacyOptimized: 261633 +// gas irOptimized: 143864 +// gas irOptimized code: 118000 +// gas legacy: 156586 +// gas legacy code: 236200 +// gas legacyOptimized: 143593 +// gas legacyOptimized code: 118000 // getFlag() -> true // getName() -> "abc" // getBalances() -> 12, 10 diff --git a/test/libsolidity/semanticTests/inlineAssembly/blobhash_pre_cancun.sol b/test/libsolidity/semanticTests/inlineAssembly/blobhash_pre_cancun.sol index 8972958e1f80..d3a41fc07bf3 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/blobhash_pre_cancun.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/blobhash_pre_cancun.sol @@ -15,7 +15,7 @@ contract C { } } // ==== -// EVMVersion: <=shanghai +// EVMVersion: 1 // g() -> 1000 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 f3fe0384472d..e43fc475740a 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol @@ -68,3 +68,9 @@ contract C { // testCall() -> true // tloadAllowedStaticCall() -> true // tstoreNotAllowedStaticCall() -> true +// gas irOptimized: 98419720 +// gas irOptimized code: 19000 +// gas legacy: 98409086 +// 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 935435420e44..f4975cd4c790 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol @@ -40,5 +40,15 @@ contract D { // EVMVersion: >=cancun // ---- // constructor() -> +// gas irOptimized: 127944 +// gas irOptimized code: 225200 +// gas legacy: 149357 +// gas legacy code: 499800 +// gas legacyOptimized: 125830 +// gas legacyOptimized code: 203200 // destroy() -> // createAndDestroy() -> +// gas legacy: 67044 +// gas legacy code: 92600 +// gas legacyOptimized: 65675 +// gas legacyOptimized code: 39400 diff --git a/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol b/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol index bdd9401ee5a6..d64c7dfb5fce 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol @@ -18,3 +18,6 @@ contract C { // EVMVersion: >=cancun // ---- // test() -> FAILURE +// gas irOptimized: 98437877 +// gas legacy: 98437872 +// gas legacyOptimized: 98437873 diff --git a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol index 306bc35670fe..0ad55b5ddff1 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -16,9 +16,12 @@ contract ClientReceipt { } // ---- // constructor(), 2000 wei -> -// gas irOptimized: 169915 -// gas legacy: 230038 -// gas legacyOptimized: 173883 +// gas irOptimized: 114107 +// gas irOptimized code: 55800 +// gas legacy: 118618 +// gas legacy code: 111400 +// gas legacyOptimized: 114067 +// gas legacyOptimized code: 59800 // balance -> 1500 // gas irOptimized: 191881 // gas legacy: 235167 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 ce6a0f48db09..a621b4c12ad5 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 @@ -53,9 +53,13 @@ contract C { // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 183981 -// gas legacyOptimized: 123563 +// gas legacy: 56981 +// gas legacy code: 127000 +// gas legacyOptimized: 55163 +// gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 183239 -// gas legacyOptimized: 123251 +// gas legacy: 56239 +// gas legacy code: 127000 +// gas legacyOptimized: 54851 +// 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 f3f8ebdc63db..84f6bf08e7a6 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 @@ -59,9 +59,13 @@ contract C { // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 183981 -// gas legacyOptimized: 123563 +// gas legacy: 56981 +// gas legacy code: 127000 +// gas legacyOptimized: 55163 +// gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 183239 -// gas legacyOptimized: 123251 +// gas legacy: 56239 +// gas legacy code: 127000 +// gas legacyOptimized: 54851 +// gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/salted_create/prediction_example.sol b/test/libsolidity/semanticTests/salted_create/prediction_example.sol index 1c5ce63ad456..75174729326f 100644 --- a/test/libsolidity/semanticTests/salted_create/prediction_example.sol +++ b/test/libsolidity/semanticTests/salted_create/prediction_example.sol @@ -26,4 +26,5 @@ contract C { // compileViaYul: also // ---- // createDSalted(bytes32,uint256): 42, 64 -> -// gas legacy: 102943 +// gas legacy: 78574 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create.sol b/test/libsolidity/semanticTests/salted_create/salted_create.sol index 743ff5fd2a23..535a2813c17c 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create.sol @@ -21,6 +21,9 @@ contract A { // ---- // different_salt() -> true // same_salt() -> true -// gas irOptimized: 98438895 -// gas legacy: 98439109 -// gas legacyOptimized: 98438967 +// gas irOptimized: 98438295 +// gas irOptimized code: 600 +// gas legacy: 98437509 +// gas legacy code: 1600 +// gas legacyOptimized: 98437367 +// gas legacyOptimized code: 1600 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index c4db17474223..735731c8abf7 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -21,6 +21,9 @@ contract A { // EVMVersion: >=constantinople // ---- // f(), 10 ether -> 3007, 3008, 3009 -// gas irOptimized: 253005 -// gas legacy: 381063 -// gas legacyOptimized: 279694 +// gas irOptimized: 187005 +// gas irOptimized code: 66000 +// gas legacy: 190863 +// gas legacy code: 190200 +// gas legacyOptimized: 187258 +// gas legacyOptimized code: 92400 diff --git a/test/libsolidity/semanticTests/smoke/alignment.sol b/test/libsolidity/semanticTests/smoke/alignment.sol index 3e8016f988f8..296ae0161711 100644 --- a/test/libsolidity/semanticTests/smoke/alignment.sol +++ b/test/libsolidity/semanticTests/smoke/alignment.sol @@ -25,5 +25,6 @@ contract D { // stateDecimal() -> right(42) // stateBytes() -> left(0x4200ef) // internalStateDecimal() -> 0x20 -// gas legacy: 100265 +// gas legacy: 76665 +// gas legacy code: 23600 // update(bool,uint256,bytes32): false, -23, left(0x2300ef) -> false, -23, left(0x2300ef) diff --git a/test/libsolidity/semanticTests/smoke/constructor.sol b/test/libsolidity/semanticTests/smoke/constructor.sol index 79b92867bc0d..2783fe4a8c9c 100644 --- a/test/libsolidity/semanticTests/smoke/constructor.sol +++ b/test/libsolidity/semanticTests/smoke/constructor.sol @@ -12,9 +12,12 @@ contract C { } // ---- // constructor(), 2 wei: 3 -> -// gas irOptimized: 104412 -// gas legacy: 148308 -// gas legacyOptimized: 106727 +// gas irOptimized: 78996 +// gas irOptimized code: 25400 +// gas legacy: 83056 +// gas legacy code: 65200 +// gas legacyOptimized: 78899 +// gas legacyOptimized code: 27800 // state() -> 3 // balance() -> 2 // balance -> 2 diff --git a/test/libsolidity/semanticTests/state/blockhash_basic.sol b/test/libsolidity/semanticTests/state/blockhash_basic.sol index 01069aa0c6dc..64b8d55a26b6 100644 --- a/test/libsolidity/semanticTests/state/blockhash_basic.sol +++ b/test/libsolidity/semanticTests/state/blockhash_basic.sol @@ -12,9 +12,12 @@ contract C { } // ---- // constructor() -// gas irOptimized: 108150 -// gas legacy: 152179 -// gas legacyOptimized: 106750 +// gas irOptimized: 80338 +// gas irOptimized code: 27800 +// gas legacy: 83571 +// gas legacy code: 68600 +// gas legacyOptimized: 80338 +// gas legacyOptimized code: 26400 // genesisHash() -> 0x3737373737373737373737373737373737373737373737373737373737373737 // currentHash() -> 0 // f(uint256): 0 -> 0x3737373737373737373737373737373737373737373737373737373737373737 diff --git a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol index 1d1783a16291..8ee19a278a23 100644 --- a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol @@ -36,8 +36,8 @@ contract C { } // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121481 -// gas legacy: 123069 -// gas legacyOptimized: 121756 +// gas irOptimized: 121394 +// gas legacy: 122978 +// gas legacyOptimized: 121648 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol index a1b0999ff5b1..9b0fa9207a8c 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol @@ -44,8 +44,8 @@ contract C { } // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121598 -// gas legacy: 123208 -// gas legacyOptimized: 121763 +// gas irOptimized: 121511 +// gas legacy: 123117 +// gas legacyOptimized: 121655 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol index b88466113408..a0834ca5bf5b 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol @@ -52,14 +52,14 @@ contract C { } // ---- // from_memory() -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 123039 -// gas legacy: 130227 -// gas legacyOptimized: 128758 +// gas irOptimized: 122952 +// gas legacy: 130136 +// gas legacyOptimized: 128650 // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121709 -// gas legacy: 123282 -// gas legacyOptimized: 121868 +// gas irOptimized: 121622 +// gas legacy: 123191 +// gas legacyOptimized: 121760 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 115130 -// gas legacy: 122516 -// gas legacyOptimized: 120804 +// gas irOptimized: 115043 +// gas legacy: 122425 +// gas legacyOptimized: 120696 diff --git a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol index e6b569922c5f..033f0f518c12 100644 --- a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol @@ -45,18 +45,18 @@ contract C { } // ---- // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121686 -// gas legacy: 123144 -// gas legacyOptimized: 121808 +// gas irOptimized: 121599 +// gas legacy: 123053 +// gas legacyOptimized: 121700 // from_storage() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121731 -// gas legacy: 123193 -// gas legacyOptimized: 121860 +// gas irOptimized: 121644 +// gas legacy: 123102 +// gas legacyOptimized: 121752 // from_memory() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 122947 -// gas legacy: 130088 -// gas legacyOptimized: 128754 +// gas irOptimized: 122860 +// gas legacy: 129997 +// gas legacyOptimized: 128646 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 21, 3, 0x666f6f0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 115045 -// gas legacy: 118301 -// gas legacyOptimized: 115432 +// gas irOptimized: 114958 +// gas legacy: 118210 +// gas legacyOptimized: 115324 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index 27ab530cd76d..8976cf3c52cc 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -113,9 +113,12 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 352698 -// gas legacy: 834932 -// gas legacyOptimized: 412648 +// gas irOptimized: 121082 +// gas irOptimized code: 231600 +// gas legacy: 163352 +// gas legacy code: 671400 +// gas legacyOptimized: 127448 +// gas legacyOptimized code: 285200 // totalSupply() -> 20 // gas irOptimized: 23415 // gas legacy: 23653 diff --git a/test/libsolidity/semanticTests/using/using_global_invisible.sol b/test/libsolidity/semanticTests/using/using_global_invisible.sol index 3e767a185d90..818707f6fe35 100644 --- a/test/libsolidity/semanticTests/using/using_global_invisible.sol +++ b/test/libsolidity/semanticTests/using/using_global_invisible.sol @@ -40,4 +40,5 @@ contract D { // ---- // library: "A":L // test() -> 3 -// gas legacy: 120881 +// gas legacy: 59681 +// gas legacy code: 61200 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 80daf116cdbd..f283aaeaa3de 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -8,15 +8,18 @@ contract C { } // To avoid dependency on exact length. - function f() public view returns (bool) { return address(this).code.length > 400; } + function f() public view returns (bool) { return address(this).code.length > 380; } function g() public view returns (uint) { return address(0).code.length; } function h() public view returns (uint) { return address(1).code.length; } } // ---- // constructor() -> -// gas irOptimized: 173273 -// gas legacy: 241796 -// gas legacyOptimized: 153670 +// gas irOptimized: 70351 +// gas irOptimized code: 95800 +// gas legacy: 82380 +// gas legacy code: 153800 +// gas legacyOptimized: 69496 +// gas legacyOptimized code: 79200 // initCode() -> 0x20, 0 // f() -> true // g() -> 0 diff --git a/test/libsolidity/semanticTests/various/code_access_content.sol b/test/libsolidity/semanticTests/various/code_access_content.sol index 92d31d621433..dc4e49b2dae0 100644 --- a/test/libsolidity/semanticTests/various/code_access_content.sol +++ b/test/libsolidity/semanticTests/various/code_access_content.sol @@ -38,6 +38,8 @@ contract C { } // ---- // testRuntime() -> true -// gas legacy: 100177 +// gas legacy: 76577 +// gas legacy code: 23600 // testCreation() -> true -// gas legacy: 100600 +// gas legacy: 77000 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/various/code_access_create.sol b/test/libsolidity/semanticTests/various/code_access_create.sol index 075682129cda..d2b7f92f4e66 100644 --- a/test/libsolidity/semanticTests/various/code_access_create.sol +++ b/test/libsolidity/semanticTests/various/code_access_create.sol @@ -23,4 +23,5 @@ contract C { } // ---- // test() -> 7 -// gas legacy: 100849 +// gas legacy: 76649 +// gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/various/code_access_runtime.sol b/test/libsolidity/semanticTests/various/code_access_runtime.sol index 9a9e7a80bf90..b62eb0b8535c 100644 --- a/test/libsolidity/semanticTests/various/code_access_runtime.sol +++ b/test/libsolidity/semanticTests/various/code_access_runtime.sol @@ -23,4 +23,5 @@ contract C { // EVMVersion: >=constantinople // ---- // test() -> 42 -// gas legacy: 100235 +// gas legacy: 76035 +// gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/various/code_length.sol b/test/libsolidity/semanticTests/various/code_length.sol index 97a7637976eb..c30ac838fe4c 100644 --- a/test/libsolidity/semanticTests/various/code_length.sol +++ b/test/libsolidity/semanticTests/various/code_length.sol @@ -59,5 +59,6 @@ contract C { } // ---- // constructor() -// gas legacy: 124168 +// gas legacy: 66936 +// gas legacy code: 57200 // f(): true, true -> true, true diff --git a/test/libsolidity/semanticTests/various/create_calldata.sol b/test/libsolidity/semanticTests/various/create_calldata.sol index c3d038136f6e..b8ec252095c8 100644 --- a/test/libsolidity/semanticTests/various/create_calldata.sol +++ b/test/libsolidity/semanticTests/various/create_calldata.sol @@ -8,7 +8,10 @@ contract C { } // ---- // constructor(): 42 -> -// gas irOptimized: 145578 -// gas legacy: 173845 -// gas legacyOptimized: 137877 +// gas irOptimized: 67834 +// gas irOptimized code: 70400 +// gas legacy: 78029 +// gas legacy code: 90200 +// gas legacyOptimized: 68321 +// gas legacyOptimized code: 64600 // s() -> 0x20, 0 diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index b752a5210152..f7956c4c50eb 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -96,9 +96,12 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 353276 -// gas legacy: 807683 -// gas legacyOptimized: 408718 +// gas irOptimized: 121248 +// gas irOptimized code: 232000 +// gas legacy: 159959 +// gas legacy code: 647600 +// gas legacyOptimized: 126918 +// gas legacyOptimized code: 281800 // totalSupply() -> 20 // gas irOptimized: 23415 // gas legacy: 23524 diff --git a/test/libsolidity/semanticTests/various/external_types_in_calls.sol b/test/libsolidity/semanticTests/various/external_types_in_calls.sol index e8742c2346b0..aff302d26e8f 100644 --- a/test/libsolidity/semanticTests/various/external_types_in_calls.sol +++ b/test/libsolidity/semanticTests/various/external_types_in_calls.sol @@ -24,5 +24,6 @@ contract C { } // ---- // test() -> 9, 7 -// gas legacy: 127514 +// gas legacy: 80314 +// gas legacy code: 47200 // t2() -> 9 diff --git a/test/libsolidity/semanticTests/various/many_subassemblies.sol b/test/libsolidity/semanticTests/various/many_subassemblies.sol index 26c3a1bbff7b..67a576da7889 100644 --- a/test/libsolidity/semanticTests/various/many_subassemblies.sol +++ b/test/libsolidity/semanticTests/various/many_subassemblies.sol @@ -30,6 +30,9 @@ contract D { } // ---- // run() -> -// gas irOptimized: 381615 -// gas legacy: 392719 -// gas legacyOptimized: 392719 +// gas irOptimized: 375015 +// gas irOptimized code: 6600 +// gas legacy: 375119 +// gas legacy code: 17600 +// gas legacyOptimized: 375119 +// gas legacyOptimized code: 17600 diff --git a/test/libsolidity/semanticTests/various/negative_stack_height.sol b/test/libsolidity/semanticTests/various/negative_stack_height.sol index 3c9130e9fdf0..44fd0089cf70 100644 --- a/test/libsolidity/semanticTests/various/negative_stack_height.sol +++ b/test/libsolidity/semanticTests/various/negative_stack_height.sol @@ -65,5 +65,7 @@ contract C { // compileViaYul: false // ---- // constructor() -> -// gas legacy: 575272 -// gas legacyOptimized: 345026 +// gas legacy: 92268 +// gas legacy code: 483000 +// gas legacyOptimized: 75022 +// gas legacyOptimized code: 270000 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol index 85c95be44795..263da7133fa9 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol @@ -64,9 +64,12 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 1 ether -> -// gas irOptimized: 455954 -// gas legacy: 375495 -// gas legacyOptimized: 507630 +// gas irOptimized: 67028 +// gas irOptimized code: 175400 +// gas legacy: 76163 +// gas legacy code: 297400 +// gas legacyOptimized: 66516 +// gas legacyOptimized code: 168000 // exists() -> false // test_create_and_terminate() -> // exists() -> false 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 4bc65b760811..16797ee4c0fd 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol @@ -35,16 +35,30 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 2 ether -> +// gas irOptimized: 107718 +// gas irOptimized code: 116200 +// gas legacy: 120424 +// gas legacy code: 253600 +// gas legacyOptimized: 109015 +// gas legacyOptimized code: 130800 // balance: 0x1111111111111111111111111111111111111111 -> 0 // balance: 0x2222222222222222222222222222222222222222 -> 0 // balance -> 2000000000000000000 // exists() -> false // test_deploy_and_terminate_twice() -> +// gas irOptimized: 121350 +// gas irOptimized code: 14000 +// gas legacy: 122384 +// gas legacy code: 43200 +// gas legacyOptimized: 121596 +// gas legacyOptimized code: 22800 // exists() -> false // balance: 0x1111111111111111111111111111111111111111 -> 1000000000000000000 // balance: 0x2222222222222222222222222222222222222222 -> 0 // balance -> 1000000000000000000 // deploy() -> +// gas legacy: 58491 +// gas legacy code: 43200 // exists() -> true // balance: 0x1111111111111111111111111111111111111111 -> 1000000000000000000 // balance: 0x2222222222222222222222222222222222222222 -> 0 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol index 473571bf1391..1b3022efedf0 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol @@ -82,14 +82,21 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 1 ether -> -// gas irOptimized: 562058 -// gas legacy: 633310 -// gas legacyOptimized: 590051 +// gas irOptimized: 132874 +// gas irOptimized code: 292400 +// gas legacy: 151217 +// gas legacy code: 533400 +// gas legacyOptimized: 131436 +// gas legacyOptimized code: 276600 // exists() -> false // test_deploy_and_terminate() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 118541 -// gas legacyOptimized: 118305 +// gas irOptimized: 96394 +// gas irOptimized code: 20800 +// gas legacy: 97788 +// gas legacy code: 20800 +// gas legacyOptimized: 96044 +// gas legacyOptimized code: 20800 // exists() -> false // deploy_create2() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 @@ -99,3 +106,6 @@ contract D { // test_balance_after_selfdestruct() -> // exists() -> true // deploy_create2() -> FAILURE +// gas irOptimized: 96903654 +// gas legacy: 96903660 +// gas legacyOptimized: 96903641 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun.sol index 4142eb25cf2d..a39b6c42355c 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun.sol @@ -62,9 +62,12 @@ contract D { // EVMVersion: =shanghai // ---- // constructor(), 1 ether -> -// gas irOptimized: 242428 -// gas legacy: 373563 -// gas legacyOptimized: 234516 +// gas irOptimized: 67028 +// gas irOptimized code: 175400 +// gas legacy: 76163 +// gas legacy code: 297400 +// gas legacyOptimized: 66516 +// gas legacyOptimized code: 168000 // exists() -> false // test_create_and_terminate() -> // exists() -> false diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol index 57b2d5c66ac4..a09a7cac68b1 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol @@ -35,23 +35,30 @@ contract D { // EVMVersion: <=shanghai // ---- // constructor(), 2 ether -> -// gas irOptimized: 223918 -// gas legacy: 374228 -// gas legacyOptimized: 239815 +// gas irOptimized: 107718 +// gas irOptimized code: 116200 +// gas legacy: 120424 +// gas legacy code: 253600 +// gas legacyOptimized: 109015 +// gas legacyOptimized code: 130800 // balance: 0x1111111111111111111111111111111111111111 -> 0 // balance: 0x2222222222222222222222222222222222222222 -> 0 // balance -> 2000000000000000000 // exists() -> false // test_deploy_and_terminate_twice() -> -// gas irOptimized: 135350 -// gas legacy: 165584 -// gas legacyOptimized: 144396 +// gas irOptimized: 121350 +// gas irOptimized code: 14000 +// gas legacy: 122384 +// gas legacy code: 43200 +// gas legacyOptimized: 121596 +// gas legacyOptimized code: 22800 // exists() -> false // balance: 0x1111111111111111111111111111111111111111 -> 1000000000000000000 // balance: 0x2222222222222222222222222222222222222222 -> 0 // balance -> 1000000000000000000 // deploy() -> -// gas legacy: 101691 +// gas legacy: 58491 +// gas legacy code: 43200 // exists() -> true // balance: 0x1111111111111111111111111111111111111111 -> 1000000000000000000 // balance: 0x2222222222222222222222222222222222222222 -> 0 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol index 9c9949854a0a..fc650ebba741 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol @@ -79,15 +79,21 @@ contract D { // EVMVersion: =shanghai // ---- // constructor(), 1 ether -> -// gas irOptimized: 430265 -// gas legacy: 690264 -// gas legacyOptimized: 412819 +// gas irOptimized: 133253 +// gas irOptimized code: 297000 +// gas legacy: 151644 +// gas legacy code: 538600 +// gas legacyOptimized: 131799 +// gas legacyOptimized code: 281000 // exists() -> false // test_deploy_and_terminate() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 117489 -// gas legacy: 118895 -// gas legacyOptimized: 117137 +// gas irOptimized: 96689 +// gas irOptimized code: 20800 +// gas legacy: 98095 +// gas legacy code: 20800 +// gas legacyOptimized: 96337 +// gas legacyOptimized code: 20800 // exists() -> false // deploy_create2() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/various/senders_balance.sol b/test/libsolidity/semanticTests/various/senders_balance.sol index 6628454db9db..5b4371149f42 100644 --- a/test/libsolidity/semanticTests/various/senders_balance.sol +++ b/test/libsolidity/semanticTests/various/senders_balance.sol @@ -16,7 +16,10 @@ contract D { } // ---- // constructor(), 27 wei -> -// gas irOptimized: 167865 -// gas legacy: 218459 -// gas legacyOptimized: 167292 +// gas irOptimized: 114057 +// gas irOptimized code: 53800 +// gas legacy: 117835 +// gas legacy code: 100600 +// gas legacyOptimized: 113676 +// gas legacyOptimized code: 53600 // f() -> 27 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index ce8946c55c4e..ef53a4e47848 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -19,6 +19,6 @@ contract C { } // ---- // g() -> 2, 6 -// gas irOptimized: 178475 -// gas legacy: 180839 -// gas legacyOptimized: 179374 +// gas irOptimized: 178263 +// gas legacy: 180657 +// gas legacyOptimized: 179156 diff --git a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol index 1306529d4183..77a330f3cd54 100644 --- a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol +++ b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol @@ -35,12 +35,19 @@ contract D { // EVMVersion: >=byzantium // ---- // f() -> 0x1 # This should work, next should throw # -// gas legacy: 102095 +// gas legacy: 76495 +// gas legacy code: 25600 // fview() -> FAILURE -// gas irOptimized: 98438588 -// gas legacy: 98438774 -// gas legacyOptimized: 98438580 +// gas irOptimized: 98425388 +// gas irOptimized code: 13200 +// gas legacy: 98413174 +// gas legacy code: 25600 +// gas legacyOptimized: 98425380 +// gas legacyOptimized code: 13200 // fpure() -> FAILURE -// gas irOptimized: 98438589 -// gas legacy: 98438774 -// gas legacyOptimized: 98438580 +// gas irOptimized: 98425389 +// gas irOptimized code: 13200 +// gas legacy: 98413174 +// gas legacy code: 25600 +// gas legacyOptimized: 98425380 +// gas legacyOptimized code: 13200 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol index 9f262fbdeb51..427a006dc102 100644 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ b/test/libsolidity/semanticTests/various/value_complex.sol @@ -19,7 +19,10 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 172407 -// gas legacy: 252296 -// gas legacyOptimized: 180352 +// gas irOptimized: 114399 +// gas irOptimized code: 58000 +// gas legacy: 120076 +// gas legacy code: 132200 +// 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 index 1e591050c3b3..97fbbab1e634 100644 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ b/test/libsolidity/semanticTests/various/value_insane.sol @@ -18,7 +18,10 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 173271 -// gas legacy: 253820 -// gas legacyOptimized: 180784 +// gas irOptimized: 114463 +// gas irOptimized code: 58800 +// gas legacy: 120200 +// gas legacy code: 133600 +// gas legacyOptimized: 114568 +// gas legacyOptimized code: 66200 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/smtCheckerTests/imports/import_base.sol b/test/libsolidity/smtCheckerTests/imports/import_base.sol index 3e8aeefe4845..fb6ed2ee4800 100644 --- a/test/libsolidity/smtCheckerTests/imports/import_base.sol +++ b/test/libsolidity/smtCheckerTests/imports/import_base.sol @@ -12,7 +12,7 @@ contract Base { import "base"; contract Der is Base { function g(uint y) public { - require(x < 10); // added to restrict the search space and avoid non-determinsm in Spacer + require(x < 10); // added to restrict the search space and avoid non-determinism in Spacer x += f(); assert(y > x); } @@ -20,5 +20,5 @@ contract Der is Base { // ==== // SMTEngine: all // ---- -// Warning 6328: (der:173-186): CHC: Assertion violation happens here. +// Warning 6328: (der:174-187): 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/types/mapping_6.sol b/test/libsolidity/smtCheckerTests/types/mapping_6.sol new file mode 100644 index 000000000000..f2b6d74d7a43 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_6.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0 + + +// Regression for handling signedness, see issues #14791 and #14792 +contract C { + mapping(bool => int240) internal v1; + mapping(bytes14 => bytes15) internal v; + + function f() public payable { + delete v["A"]; + } +} diff --git a/test/libsolidity/smtCheckerTests/types/string_1.sol b/test/libsolidity/smtCheckerTests/types/string_1.sol index 8209f992805d..3a74a8e1ce31 100644 --- a/test/libsolidity/smtCheckerTests/types/string_1.sol +++ b/test/libsolidity/smtCheckerTests/types/string_1.sol @@ -6,5 +6,6 @@ contract C } // ==== // SMTEngine: all +// SMTIgnoreCex: no // ---- -// Warning 6328: (77-121): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.f(s1, s2) +// Warning 6328: (77-121): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.f(s1, s2) -- counterexample incomplete; parameter name used instead of value diff --git a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol index fc4783ceba19..373d76c339ff 100644 --- a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol +++ b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol @@ -40,14 +40,14 @@ contract C { // Info 4164: (94-124): Inferred type: word // Info 4164: (125-161): Inferred type: integer // Info 4164: (162-192): Inferred type: () -// Info 4164: (194-228): Inferred type: tfun(('u:type, 'v:type), 'u:type -> 'v:type) +// Info 4164: (194-228): Inferred type: tfun(('s:type, 't:type), 's:type -> 't:type) // Info 4164: (202-208): Inferred type: ('s:type, 't:type) // Info 4164: (203-204): Inferred type: 's:type // Info 4164: (206-207): Inferred type: 't:type -// Info 4164: (229-265): Inferred type: tfun(('y:type, 'z:type), ('y:type, 'z:type)) -// Info 4164: (238-244): Inferred type: ('w:type, 'x:type) -// Info 4164: (239-240): Inferred type: 'w:type -// Info 4164: (242-243): Inferred type: 'x:type +// Info 4164: (229-265): Inferred type: tfun(('u:type, 'v:type), ('u:type, 'v:type)) +// Info 4164: (238-244): Inferred type: ('u:type, 'v:type) +// Info 4164: (239-240): Inferred type: 'u:type +// Info 4164: (242-243): Inferred type: 'v:type // Info 4164: (284-584): Inferred type: () -> () // Info 4164: (292-294): Inferred type: () // Info 4164: (318-325): Inferred type: void @@ -84,9 +84,9 @@ contract C { // Info 4164: (525-529): Inferred type: word // Info 4164: (540-553): Inferred type: bool // Info 4164: (540-550): Inferred type: (bool, word) -> bool -// Info 4164: (540-544): Inferred type: ('bl:type, 'bm:type) +// Info 4164: (540-544): Inferred type: (?bh:type, ?bi:type) // Info 4164: (551-552): Inferred type: (bool, word) // Info 4164: (563-577): Inferred type: word // Info 4164: (563-574): Inferred type: (bool, word) -> word -// Info 4164: (563-567): Inferred type: ('bq:type, 'br:type) +// Info 4164: (563-567): Inferred type: (?bm:type, ?bn:type) // Info 4164: (575-576): Inferred type: (bool, word) diff --git a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_function.sol b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_function.sol new file mode 100644 index 000000000000..da1169969143 --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_function.sol @@ -0,0 +1,17 @@ +pragma experimental solidity; + +type T(X); + +function f(p: P, q: T(Q)) { + let r: (R, S); + let s: S; +} +// ==== +// EVMVersion: >=constantinople +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError 5934: (57-58): Undeclared type variable. +// TypeError 5934: (65-66): Undeclared type variable. +// TypeError 5934: (83-84): Undeclared type variable. +// TypeError 5934: (86-87): Undeclared type variable. +// TypeError 5934: (101-102): Undeclared type variable. diff --git a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_quantified_function.sol b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_quantified_function.sol new file mode 100644 index 000000000000..91b734569372 --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_quantified_function.sol @@ -0,0 +1,12 @@ +pragma experimental solidity; + +forall A +function f(b: B) { + let c: C; +} +// ==== +// EVMVersion: >=constantinople +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError 5934: (54-55): Undeclared type variable. +// TypeError 5934: (70-71): Undeclared type variable. diff --git a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_type_class.sol b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_type_class.sol new file mode 100644 index 000000000000..8af0cce82699 --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_type_class.sol @@ -0,0 +1,17 @@ +pragma experimental solidity; + +type T(X); + +class Self: C { + function f(self: Self); +} + +instantiation T(Y): C { + function f(self: T(Z)) {} +} +// ==== +// EVMVersion: >=constantinople +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError 5934: (137-138): Undeclared type variable. +// TypeError 7428: (90-145): Instantiation function 'f' does not match the declaration in the type class (T('bc:type) -> () != T('y:type) -> ()). diff --git a/test/libsolidity/syntaxTests/experimental/inference/instantiation_invalid_type_constructor.sol b/test/libsolidity/syntaxTests/experimental/inference/instantiation_invalid_type_constructor.sol new file mode 100644 index 000000000000..0245deb1f401 --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/inference/instantiation_invalid_type_constructor.sol @@ -0,0 +1,13 @@ +pragma experimental solidity; + +class Self: C {} + +function f() {} + +instantiation f: C {} +// ==== +// EVMVersion: >=constantinople +// compileViaYul: true +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError 9831: (80-81): Expected type declaration. diff --git a/test/libsolidity/syntaxTests/experimental/inference/instantiation_member_type_does_not_match_declaration.sol b/test/libsolidity/syntaxTests/experimental/inference/instantiation_member_type_does_not_match_declaration.sol new file mode 100644 index 000000000000..1c845b8eeece --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/inference/instantiation_member_type_does_not_match_declaration.sol @@ -0,0 +1,18 @@ +pragma experimental solidity; + +type T; +type U; + +class Self: C { + function f(self: Self); +} + +instantiation T: C { + function f(self: U) {} +} +// ==== +// EVMVersion: >=constantinople +// compileViaYul: true +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError 7428: (95-144): Instantiation function 'f' does not match the declaration in the type class (U -> () != T -> ()). diff --git a/test/libsolidity/syntaxTests/experimental/inference/instantiation_not_for_class.sol b/test/libsolidity/syntaxTests/experimental/inference/instantiation_not_for_class.sol new file mode 100644 index 000000000000..c48fff74f94e --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/inference/instantiation_not_for_class.sol @@ -0,0 +1,12 @@ +pragma experimental solidity; + +type T; +type U; + +instantiation T: U {} +// ==== +// EVMVersion: >=constantinople +// compileViaYul: true +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError 3570: (65-66): Expected a type class. diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol index eacc895202f3..c9c7e01109e7 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol @@ -3,6 +3,7 @@ pragma experimental solidity; type T; type U(A); +forall (X, Y) function f(x, y: X, z: U(Y)) {} function run(a: T, b: U(T), c: U(U(T))) { @@ -15,39 +16,42 @@ function run(a: T, b: U(T), c: U(U(T))) { // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. // Info 4164: (31-38): Inferred type: T -// Info 4164: (39-49): Inferred type: tfun('u:type, U('u:type)) +// Info 4164: (39-49): Inferred type: tfun('t:type, U('t:type)) // Info 4164: (45-48): Inferred type: 't:type // Info 4164: (46-47): Inferred type: 't:type -// Info 4164: (51-82): Inferred type: ('x:type, 'y:type, U('ba:type)) -> () -// Info 4164: (61-79): Inferred type: ('x:type, 'y:type, U('ba:type)) -// Info 4164: (62-63): Inferred type: 'x:type -// Info 4164: (65-69): Inferred type: 'y:type -// Info 4164: (68-69): Inferred type: 'y:type -// Info 4164: (71-78): Inferred type: U('ba:type) -// Info 4164: (74-78): Inferred type: U('ba:type) -// Info 4164: (74-75): Inferred type: tfun('ba:type, U('ba:type)) -// Info 4164: (76-77): Inferred type: 'ba:type -// Info 4164: (84-159): Inferred type: (T, U(T), U(U(T))) -> () -// Info 4164: (96-123): Inferred type: (T, U(T), U(U(T))) -// Info 4164: (97-101): Inferred type: T -// Info 4164: (100-101): Inferred type: T -// Info 4164: (103-110): Inferred type: U(T) -// Info 4164: (106-110): Inferred type: U(T) -// Info 4164: (106-107): Inferred type: tfun(T, U(T)) -// Info 4164: (108-109): Inferred type: T -// Info 4164: (112-122): Inferred type: U(U(T)) -// Info 4164: (115-122): Inferred type: U(U(T)) -// Info 4164: (115-116): Inferred type: tfun(U(T), U(U(T))) -// Info 4164: (117-121): Inferred type: U(T) -// Info 4164: (117-118): Inferred type: tfun(T, U(T)) -// Info 4164: (119-120): Inferred type: T -// Info 4164: (130-140): Inferred type: () -// Info 4164: (130-131): Inferred type: (T, T, U(T)) -> () -// Info 4164: (132-133): Inferred type: T -// Info 4164: (135-136): Inferred type: T -// Info 4164: (138-139): Inferred type: U(T) -// Info 4164: (146-156): Inferred type: () -// Info 4164: (146-147): Inferred type: (U(T), U(T), U(U(T))) -> () -// Info 4164: (148-149): Inferred type: U(T) -// Info 4164: (151-152): Inferred type: U(T) -// Info 4164: (154-155): Inferred type: U(U(T)) +// Info 4164: (58-64): Inferred type: ('u:type, 'v:type) +// Info 4164: (59-60): Inferred type: 'u:type +// Info 4164: (62-63): Inferred type: 'v:type +// Info 4164: (65-96): Inferred type: ('y:type, 'u:type, U('v:type)) -> () +// Info 4164: (75-93): Inferred type: ('y:type, 'u:type, U('v:type)) +// Info 4164: (76-77): Inferred type: 'y:type +// Info 4164: (79-83): Inferred type: 'u:type +// Info 4164: (82-83): Inferred type: 'u:type +// Info 4164: (85-92): Inferred type: U('v:type) +// Info 4164: (88-92): Inferred type: U('v:type) +// Info 4164: (88-89): Inferred type: tfun('v:type, U('v:type)) +// Info 4164: (90-91): Inferred type: 'v:type +// Info 4164: (98-173): Inferred type: (T, U(T), U(U(T))) -> () +// Info 4164: (110-137): Inferred type: (T, U(T), U(U(T))) +// Info 4164: (111-115): Inferred type: T +// Info 4164: (114-115): Inferred type: T +// Info 4164: (117-124): Inferred type: U(T) +// Info 4164: (120-124): Inferred type: U(T) +// Info 4164: (120-121): Inferred type: tfun(T, U(T)) +// Info 4164: (122-123): Inferred type: T +// Info 4164: (126-136): Inferred type: U(U(T)) +// Info 4164: (129-136): Inferred type: U(U(T)) +// Info 4164: (129-130): Inferred type: tfun(U(T), U(U(T))) +// Info 4164: (131-135): Inferred type: U(T) +// Info 4164: (131-132): Inferred type: tfun(T, U(T)) +// Info 4164: (133-134): Inferred type: T +// Info 4164: (144-154): Inferred type: () +// Info 4164: (144-145): Inferred type: (T, T, U(T)) -> () +// Info 4164: (146-147): Inferred type: T +// Info 4164: (149-150): Inferred type: T +// Info 4164: (152-153): Inferred type: U(T) +// Info 4164: (160-170): Inferred type: () +// Info 4164: (160-161): Inferred type: (U(T), U(T), U(U(T))) -> () +// Info 4164: (162-163): Inferred type: U(T) +// Info 4164: (165-166): Inferred type: U(T) +// Info 4164: (168-169): Inferred type: U(U(T)) diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol index b597a5b25295..85f810a9dc0d 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol @@ -7,6 +7,7 @@ type V; class Self: C {} class Self: D {} +forall (X, Y, Z) function run() { let x: T(U, X, Z: C); let y: T(V, Y, Z: D); @@ -16,7 +17,7 @@ function run() { // compileViaYul: true // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. -// Info 4164: (31-47): Inferred type: tfun(('ba:type, 'bb:type, 'bc:type), T('ba:type, 'bb:type, 'bc:type)) +// Info 4164: (31-47): Inferred type: tfun(('x:type, 'y:type, 'z:type), T('x:type, 'y:type, 'z:type)) // Info 4164: (37-46): Inferred type: ('x:type, 'y:type, 'z:type) // Info 4164: (38-39): Inferred type: 'x:type // Info 4164: (41-42): Inferred type: 'y:type @@ -24,24 +25,28 @@ function run() { // Info 4164: (48-55): Inferred type: U // Info 4164: (56-63): Inferred type: V // Info 4164: (65-81): Inferred type: C -// Info 4164: (71-75): Inferred type: 'be:(type, C) +// Info 4164: (71-75): Inferred type: 'k:(type, C) // Info 4164: (82-98): Inferred type: D -// Info 4164: (88-92): Inferred type: 'bg:(type, D) -// Info 4164: (100-170): Inferred type: () -> () -// Info 4164: (112-114): Inferred type: () -// Info 4164: (125-141): Inferred type: T(U, 'bm:type, 'bo:(type, C)) -// Info 4164: (128-141): Inferred type: T(U, 'bm:type, 'bo:(type, C)) -// Info 4164: (128-129): Inferred type: tfun((U, 'bm:type, 'bo:(type, C)), T(U, 'bm:type, 'bo:(type, C))) -// Info 4164: (130-131): Inferred type: U -// Info 4164: (133-134): Inferred type: 'bm:type -// Info 4164: (136-140): Inferred type: 'bo:(type, C) -// Info 4164: (136-137): Inferred type: 'bo:(type, C) -// Info 4164: (139-140): Inferred type: 'bo:(type, C) -// Info 4164: (151-167): Inferred type: T(V, 'bt:type, 'bv:(type, D)) -// Info 4164: (154-167): Inferred type: T(V, 'bt:type, 'bv:(type, D)) -// Info 4164: (154-155): Inferred type: tfun((V, 'bt:type, 'bv:(type, D)), T(V, 'bt:type, 'bv:(type, D))) -// Info 4164: (156-157): Inferred type: V -// Info 4164: (159-160): Inferred type: 'bt:type -// Info 4164: (162-166): Inferred type: 'bv:(type, D) -// Info 4164: (162-163): Inferred type: 'bv:(type, D) -// Info 4164: (165-166): Inferred type: 'bv:(type, D) +// Info 4164: (88-92): Inferred type: 'l:(type, D) +// Info 4164: (107-116): Inferred type: (?bc:type, ?bd:type, ?bq:(type, C, D)) +// Info 4164: (108-109): Inferred type: ?bc:type +// Info 4164: (111-112): Inferred type: ?bd:type +// Info 4164: (114-115): Inferred type: ?bq:(type, C, D) +// Info 4164: (117-187): Inferred type: () -> () +// Info 4164: (129-131): Inferred type: () +// Info 4164: (142-158): Inferred type: T(U, ?bc:type, ?bq:(type, C, D)) +// Info 4164: (145-158): Inferred type: T(U, ?bc:type, ?bq:(type, C, D)) +// Info 4164: (145-146): Inferred type: tfun((U, ?bc:type, ?bq:(type, C, D)), T(U, ?bc:type, ?bq:(type, C, D))) +// Info 4164: (147-148): Inferred type: U +// Info 4164: (150-151): Inferred type: ?bc:type +// Info 4164: (153-157): Inferred type: ?bq:(type, C, D) +// Info 4164: (153-154): Inferred type: ?bq:(type, C, D) +// Info 4164: (156-157): Inferred type: ?bq:(type, C, D) +// Info 4164: (168-184): Inferred type: T(V, ?bd:type, ?bq:(type, C, D)) +// Info 4164: (171-184): Inferred type: T(V, ?bd:type, ?bq:(type, C, D)) +// Info 4164: (171-172): Inferred type: tfun((V, ?bd:type, ?bq:(type, C, D)), T(V, ?bd:type, ?bq:(type, C, D))) +// Info 4164: (173-174): Inferred type: V +// Info 4164: (176-177): Inferred type: ?bd:type +// Info 4164: (179-183): Inferred type: ?bq:(type, C, D) +// Info 4164: (179-180): Inferred type: ?bq:(type, C, D) +// Info 4164: (182-183): Inferred type: ?bq:(type, C, D) diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_abs_and_rep.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_abs_and_rep.sol index 89f3f5f1a8b9..ebebf6dafc3c 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_abs_and_rep.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_abs_and_rep.sol @@ -24,15 +24,15 @@ function fun() { // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. // Info 4164: (31-41): Inferred type: uint // Info 4164: (42-54): Inferred type: string -// Info 4164: (56-66): Inferred type: tfun('v:type, T('v:type)) +// Info 4164: (56-66): Inferred type: tfun('u:type, T('u:type)) // Info 4164: (62-65): Inferred type: 'u:type // Info 4164: (63-64): Inferred type: 'u:type -// Info 4164: (67-84): Inferred type: tfun('x:type, U('x:type)) -// Info 4164: (73-76): Inferred type: 'w:type -// Info 4164: (74-75): Inferred type: 'w:type -// Info 4164: (79-83): Inferred type: T('w:type) -// Info 4164: (79-80): Inferred type: tfun('w:type, T('w:type)) -// Info 4164: (81-82): Inferred type: 'w:type +// Info 4164: (67-84): Inferred type: tfun('v:type, U('v:type)) +// Info 4164: (73-76): Inferred type: 'v:type +// Info 4164: (74-75): Inferred type: 'v:type +// Info 4164: (79-83): Inferred type: T('v:type) +// Info 4164: (79-80): Inferred type: tfun('v:type, T('v:type)) +// Info 4164: (81-82): Inferred type: 'v:type // Info 4164: (86-245): Inferred type: () -> () // Info 4164: (98-100): Inferred type: () // Info 4164: (111-121): Inferred type: U(uint) @@ -43,13 +43,13 @@ function fun() { // Info 4164: (134-141): Inferred type: T(uint) // Info 4164: (134-135): Inferred type: tfun(uint, T(uint)) // Info 4164: (136-140): Inferred type: uint -// Info 4164: (147-155): Inferred type: T('bi:type) -// Info 4164: (147-152): Inferred type: U(uint) -> T('bi:type) -// Info 4164: (147-148): Inferred type: U('bg:type) +// Info 4164: (147-155): Inferred type: T(uint) +// Info 4164: (147-152): Inferred type: U(uint) -> T(uint) +// Info 4164: (147-148): Inferred type: U(?be:type) // Info 4164: (153-154): Inferred type: U(uint) -// Info 4164: (161-169): Inferred type: U('bm:type) -// Info 4164: (161-166): Inferred type: T(uint) -> U('bm:type) -// Info 4164: (161-162): Inferred type: U('bk:type) +// Info 4164: (161-169): Inferred type: U(uint) +// Info 4164: (161-166): Inferred type: T(uint) -> U(uint) +// Info 4164: (161-162): Inferred type: U(?bh:type) // Info 4164: (167-168): Inferred type: T(uint) // Info 4164: (180-192): Inferred type: U(string) // Info 4164: (183-192): Inferred type: U(string) @@ -59,11 +59,11 @@ function fun() { // Info 4164: (205-214): Inferred type: T(string) // Info 4164: (205-206): Inferred type: tfun(string, T(string)) // Info 4164: (207-213): Inferred type: string -// Info 4164: (220-228): Inferred type: T('bu:type) -// Info 4164: (220-225): Inferred type: U(string) -> T('bu:type) -// Info 4164: (220-221): Inferred type: U('bs:type) +// Info 4164: (220-228): Inferred type: T(string) +// Info 4164: (220-225): Inferred type: U(string) -> T(string) +// Info 4164: (220-221): Inferred type: U(?bo:type) // Info 4164: (226-227): Inferred type: U(string) -// Info 4164: (234-242): Inferred type: U('by:type) -// Info 4164: (234-239): Inferred type: T(string) -> U('by:type) -// Info 4164: (234-235): Inferred type: U('bw:type) +// Info 4164: (234-242): Inferred type: U(string) +// Info 4164: (234-239): Inferred type: T(string) -> U(string) +// Info 4164: (234-235): Inferred type: U(?br:type) // Info 4164: (240-241): Inferred type: T(string) diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol index 25ab330f3b32..c26436e06cca 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol @@ -51,28 +51,28 @@ function fun(a: T(int: P3), b: T(str: P4)) { // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. // Info 4164: (31-61): Inferred type: bool -// Info 4164: (63-73): Inferred type: tfun('z:type, T('z:type)) +// Info 4164: (63-73): Inferred type: tfun('y:type, T('y:type)) // Info 4164: (69-72): Inferred type: 'y:type // Info 4164: (70-71): Inferred type: 'y:type // Info 4164: (74-83): Inferred type: int // Info 4164: (84-93): Inferred type: str // Info 4164: (95-156): Inferred type: C -// Info 4164: (101-105): Inferred type: 'bd:(type, C) -// Info 4164: (115-154): Inferred type: ('bd:(type, C), 'bd:(type, C)) -> 'bd:(type, C) -// Info 4164: (127-145): Inferred type: ('bd:(type, C), 'bd:(type, C)) -// Info 4164: (128-135): Inferred type: 'bd:(type, C) -// Info 4164: (131-135): Inferred type: 'bd:(type, C) -// Info 4164: (137-144): Inferred type: 'bd:(type, C) -// Info 4164: (140-144): Inferred type: 'bd:(type, C) -// Info 4164: (149-153): Inferred type: 'bd:(type, C) +// Info 4164: (101-105): Inferred type: 'k:(type, C) +// Info 4164: (115-154): Inferred type: ('k:(type, C), 'k:(type, C)) -> 'k:(type, C) +// Info 4164: (127-145): Inferred type: ('k:(type, C), 'k:(type, C)) +// Info 4164: (128-135): Inferred type: 'k:(type, C) +// Info 4164: (131-135): Inferred type: 'k:(type, C) +// Info 4164: (137-144): Inferred type: 'k:(type, C) +// Info 4164: (140-144): Inferred type: 'k:(type, C) +// Info 4164: (149-153): Inferred type: 'k:(type, C) // Info 4164: (158-175): Inferred type: P1 -// Info 4164: (164-168): Inferred type: 'bg:(type, P1) +// Info 4164: (164-168): Inferred type: 'l:(type, P1) // Info 4164: (176-193): Inferred type: P2 -// Info 4164: (182-186): Inferred type: 'bj:(type, P2) +// Info 4164: (182-186): Inferred type: 'm:(type, P2) // Info 4164: (194-211): Inferred type: P3 -// Info 4164: (200-204): Inferred type: 'bw:(type, P3) +// Info 4164: (200-204): Inferred type: 'n:(type, P3) // Info 4164: (212-229): Inferred type: P4 -// Info 4164: (218-222): Inferred type: 'by:(type, P4) +// Info 4164: (218-222): Inferred type: 'o:(type, P4) // Info 4164: (231-255): Inferred type: void // Info 4164: (256-280): Inferred type: void // Info 4164: (281-305): Inferred type: void @@ -80,56 +80,56 @@ function fun(a: T(int: P3), b: T(str: P4)) { // Info 4164: (332-356): Inferred type: void // Info 4164: (357-381): Inferred type: void // Info 4164: (383-458): Inferred type: void -// Info 4164: (398-405): Inferred type: 'ca:(type, P1) -// Info 4164: (399-404): Inferred type: 'ca:(type, P1) -// Info 4164: (402-404): Inferred type: 'ca:(type, P1) -// Info 4164: (415-456): Inferred type: (T('ca:(type, P1)), T('ca:(type, P1))) -> T('ca:(type, P1)) -// Info 4164: (427-445): Inferred type: (T('ca:(type, P1)), T('ca:(type, P1))) -// Info 4164: (428-435): Inferred type: T('ca:(type, P1)) -// Info 4164: (431-435): Inferred type: T('ca:(type, P1)) -// Info 4164: (431-432): Inferred type: tfun('ca:(type, P1), T('ca:(type, P1))) -// Info 4164: (433-434): Inferred type: 'ca:(type, P1) -// Info 4164: (437-444): Inferred type: T('ca:(type, P1)) -// Info 4164: (440-444): Inferred type: T('ca:(type, P1)) -// Info 4164: (440-441): Inferred type: tfun('ca:(type, P1), T('ca:(type, P1))) -// Info 4164: (442-443): Inferred type: 'ca:(type, P1) -// Info 4164: (449-453): Inferred type: T('ca:(type, P1)) -// Info 4164: (449-450): Inferred type: tfun('ca:(type, P1), T('ca:(type, P1))) -// Info 4164: (451-452): Inferred type: 'ca:(type, P1) +// Info 4164: (398-405): Inferred type: 'bu:(type, P1) +// Info 4164: (399-404): Inferred type: 'bu:(type, P1) +// Info 4164: (402-404): Inferred type: 'bu:(type, P1) +// Info 4164: (415-456): Inferred type: (T('bu:(type, P1)), T('bu:(type, P1))) -> T('bu:(type, P1)) +// Info 4164: (427-445): Inferred type: (T('bu:(type, P1)), T('bu:(type, P1))) +// Info 4164: (428-435): Inferred type: T('bu:(type, P1)) +// Info 4164: (431-435): Inferred type: T('bu:(type, P1)) +// Info 4164: (431-432): Inferred type: tfun('bu:(type, P1), T('bu:(type, P1))) +// Info 4164: (433-434): Inferred type: 'bu:(type, P1) +// Info 4164: (437-444): Inferred type: T('bu:(type, P1)) +// Info 4164: (440-444): Inferred type: T('bu:(type, P1)) +// Info 4164: (440-441): Inferred type: tfun('bu:(type, P1), T('bu:(type, P1))) +// Info 4164: (442-443): Inferred type: 'bu:(type, P1) +// Info 4164: (449-453): Inferred type: T('bu:(type, P1)) +// Info 4164: (449-450): Inferred type: tfun('bu:(type, P1), T('bu:(type, P1))) +// Info 4164: (451-452): Inferred type: 'bu:(type, P1) // Info 4164: (460-535): Inferred type: void -// Info 4164: (475-482): Inferred type: 'ck:(type, P2) -// Info 4164: (476-481): Inferred type: 'ck:(type, P2) -// Info 4164: (479-481): Inferred type: 'ck:(type, P2) -// Info 4164: (493-533): Inferred type: (T('ck:(type, P2)), T('ck:(type, P2))) -> bool -// Info 4164: (504-522): Inferred type: (T('ck:(type, P2)), T('ck:(type, P2))) -// Info 4164: (505-512): Inferred type: T('ck:(type, P2)) -// Info 4164: (508-512): Inferred type: T('ck:(type, P2)) -// Info 4164: (508-509): Inferred type: tfun('ck:(type, P2), T('ck:(type, P2))) -// Info 4164: (510-511): Inferred type: 'ck:(type, P2) -// Info 4164: (514-521): Inferred type: T('ck:(type, P2)) -// Info 4164: (517-521): Inferred type: T('ck:(type, P2)) -// Info 4164: (517-518): Inferred type: tfun('ck:(type, P2), T('ck:(type, P2))) -// Info 4164: (519-520): Inferred type: 'ck:(type, P2) +// Info 4164: (475-482): Inferred type: 'ce:(type, P2) +// Info 4164: (476-481): Inferred type: 'ce:(type, P2) +// Info 4164: (479-481): Inferred type: 'ce:(type, P2) +// Info 4164: (493-533): Inferred type: (T('ce:(type, P2)), T('ce:(type, P2))) -> bool +// Info 4164: (504-522): Inferred type: (T('ce:(type, P2)), T('ce:(type, P2))) +// Info 4164: (505-512): Inferred type: T('ce:(type, P2)) +// Info 4164: (508-512): Inferred type: T('ce:(type, P2)) +// Info 4164: (508-509): Inferred type: tfun('ce:(type, P2), T('ce:(type, P2))) +// Info 4164: (510-511): Inferred type: 'ce:(type, P2) +// Info 4164: (514-521): Inferred type: T('ce:(type, P2)) +// Info 4164: (517-521): Inferred type: T('ce:(type, P2)) +// Info 4164: (517-518): Inferred type: tfun('ce:(type, P2), T('ce:(type, P2))) +// Info 4164: (519-520): Inferred type: 'ce:(type, P2) // Info 4164: (526-530): Inferred type: bool // Info 4164: (537-618): Inferred type: void -// Info 4164: (552-565): Inferred type: 'bm:(type, P1, P2) -// Info 4164: (553-564): Inferred type: 'bm:(type, P1, P2) -// Info 4164: (556-564): Inferred type: 'bm:(type, P1, P2) -// Info 4164: (557-559): Inferred type: 'bm:(type, P1, P2) -// Info 4164: (561-563): Inferred type: 'bm:(type, P1, P2) -// Info 4164: (575-616): Inferred type: (T('bm:(type, P1, P2)), T('bm:(type, P1, P2))) -> T('bm:(type, P1, P2)) -// Info 4164: (587-605): Inferred type: (T('bm:(type, P1, P2)), T('bm:(type, P1, P2))) -// Info 4164: (588-595): Inferred type: T('bm:(type, P1, P2)) -// Info 4164: (591-595): Inferred type: T('bm:(type, P1, P2)) -// Info 4164: (591-592): Inferred type: tfun('bm:(type, P1, P2), T('bm:(type, P1, P2))) -// Info 4164: (593-594): Inferred type: 'bm:(type, P1, P2) -// Info 4164: (597-604): Inferred type: T('bm:(type, P1, P2)) -// Info 4164: (600-604): Inferred type: T('bm:(type, P1, P2)) -// Info 4164: (600-601): Inferred type: tfun('bm:(type, P1, P2), T('bm:(type, P1, P2))) -// Info 4164: (602-603): Inferred type: 'bm:(type, P1, P2) -// Info 4164: (609-613): Inferred type: T('bm:(type, P1, P2)) -// Info 4164: (609-610): Inferred type: tfun('bm:(type, P1, P2), T('bm:(type, P1, P2))) -// Info 4164: (611-612): Inferred type: 'bm:(type, P1, P2) +// Info 4164: (552-565): Inferred type: 'bi:(type, P1, P2) +// Info 4164: (553-564): Inferred type: 'bi:(type, P1, P2) +// Info 4164: (556-564): Inferred type: 'bi:(type, P1, P2) +// Info 4164: (557-559): Inferred type: 'bi:(type, P1, P2) +// Info 4164: (561-563): Inferred type: 'bi:(type, P1, P2) +// Info 4164: (575-616): Inferred type: (T('bi:(type, P1, P2)), T('bi:(type, P1, P2))) -> T('bi:(type, P1, P2)) +// Info 4164: (587-605): Inferred type: (T('bi:(type, P1, P2)), T('bi:(type, P1, P2))) +// Info 4164: (588-595): Inferred type: T('bi:(type, P1, P2)) +// Info 4164: (591-595): Inferred type: T('bi:(type, P1, P2)) +// Info 4164: (591-592): Inferred type: tfun('bi:(type, P1, P2), T('bi:(type, P1, P2))) +// Info 4164: (593-594): Inferred type: 'bi:(type, P1, P2) +// Info 4164: (597-604): Inferred type: T('bi:(type, P1, P2)) +// Info 4164: (600-604): Inferred type: T('bi:(type, P1, P2)) +// Info 4164: (600-601): Inferred type: tfun('bi:(type, P1, P2), T('bi:(type, P1, P2))) +// Info 4164: (602-603): Inferred type: 'bi:(type, P1, P2) +// Info 4164: (609-613): Inferred type: T('bi:(type, P1, P2)) +// Info 4164: (609-610): Inferred type: tfun('bi:(type, P1, P2), T('bi:(type, P1, P2))) +// Info 4164: (611-612): Inferred type: 'bi:(type, P1, P2) // Info 4164: (620-748): Inferred type: (T(int), T(str)) -> () // Info 4164: (632-662): Inferred type: (T(int), T(str)) // Info 4164: (633-646): Inferred type: T(int) diff --git a/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameter_and_return.sol b/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameter_and_return.sol new file mode 100644 index 000000000000..00cd7b1207df --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameter_and_return.sol @@ -0,0 +1,16 @@ +pragma experimental solidity; + +type T; +type U; + +forall X +function f(x: X) -> X {} + +function test(t: T, u: U) { + t = f(u); +} +// ==== +// EVMVersion: >=constantinople +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError 8456: (115-123): Cannot unify T and U. diff --git a/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameters.sol b/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameters.sol new file mode 100644 index 000000000000..7122cdd9efce --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameters.sol @@ -0,0 +1,16 @@ +pragma experimental solidity; + +type T; +type U; + +forall X +function f(x: X, y: X) {} + +function test(t: T, u: U) { + f(t, u); +} +// ==== +// EVMVersion: >=constantinople +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError 8456: (116-123): Cannot unify T and U. diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function.sol new file mode 100644 index 000000000000..ba22a9fae4b4 --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function.sol @@ -0,0 +1,27 @@ +pragma experimental solidity; + +forall (A) +function f(a: A) {} + +forall (A, B) +function g(a: A, b: B) {} +// ==== +// EVMVersion: >=constantinople +// compileViaYul: true +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// Info 4164: (38-41): Inferred type: 's:type +// Info 4164: (39-40): Inferred type: 's:type +// Info 4164: (42-61): Inferred type: 's:type -> () +// Info 4164: (52-58): Inferred type: 's:type +// Info 4164: (53-57): Inferred type: 's:type +// Info 4164: (56-57): Inferred type: 's:type +// Info 4164: (70-76): Inferred type: ('v:type, 'w:type) +// Info 4164: (71-72): Inferred type: 'v:type +// Info 4164: (74-75): Inferred type: 'w:type +// Info 4164: (77-102): Inferred type: ('v:type, 'w:type) -> () +// Info 4164: (87-99): Inferred type: ('v:type, 'w:type) +// Info 4164: (88-92): Inferred type: 'v:type +// Info 4164: (91-92): Inferred type: 'v:type +// Info 4164: (94-98): Inferred type: 'w:type +// Info 4164: (97-98): Inferred type: 'w:type diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_no_type_var.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_no_type_var.sol new file mode 100644 index 000000000000..66753fdd0f68 --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_no_type_var.sol @@ -0,0 +1,14 @@ +pragma experimental solidity; + +forall () +function f(x: ()) {} +// ==== +// EVMVersion: >=constantinople +// compileViaYul: true +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// Info 4164: (38-40): Inferred type: () +// Info 4164: (41-61): Inferred type: () -> () +// Info 4164: (51-58): Inferred type: () +// Info 4164: (52-57): Inferred type: () +// Info 4164: (55-57): Inferred type: () diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_with_sorts.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_with_sorts.sol new file mode 100644 index 000000000000..1ab09fd2bd24 --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_with_sorts.sol @@ -0,0 +1,43 @@ +pragma experimental solidity; + +class Self: Class1 {} +class Self: Class2 {} + +forall (A: (Class1, Class2), B: Class1) +function f(a: A: Class1, b: B: Class1) {} + +forall A: Class1 +function g(a: A) {} +// ==== +// EVMVersion: >=constantinople +// compileViaYul: true +// ---- +// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. +// Info 4164: (31-52): Inferred type: Class1 +// Info 4164: (37-41): Inferred type: 'k:(type, Class1) +// Info 4164: (53-74): Inferred type: Class2 +// Info 4164: (59-63): Inferred type: 'l:(type, Class2) +// Info 4164: (83-115): Inferred type: ('ba:(type, Class1, Class2), 'bg:(type, Class1)) +// Info 4164: (84-103): Inferred type: 'ba:(type, Class1, Class2) +// Info 4164: (87-103): Inferred type: 'ba:(type, Class1, Class2) +// Info 4164: (88-94): Inferred type: 'ba:(type, Class1, Class2) +// Info 4164: (96-102): Inferred type: 'ba:(type, Class1, Class2) +// Info 4164: (105-114): Inferred type: 'bg:(type, Class1) +// Info 4164: (108-114): Inferred type: 'bg:(type, Class1) +// Info 4164: (116-157): Inferred type: ('ba:(type, Class1, Class2), 'bg:(type, Class1)) -> () +// Info 4164: (126-154): Inferred type: ('ba:(type, Class1, Class2), 'bg:(type, Class1)) +// Info 4164: (127-139): Inferred type: 'ba:(type, Class1, Class2) +// Info 4164: (130-139): Inferred type: 'ba:(type, Class1, Class2) +// Info 4164: (130-131): Inferred type: 'ba:(type, Class1, Class2) +// Info 4164: (133-139): Inferred type: 'ba:(type, Class1, Class2) +// Info 4164: (141-153): Inferred type: 'bg:(type, Class1) +// Info 4164: (144-153): Inferred type: 'bg:(type, Class1) +// Info 4164: (144-145): Inferred type: 'bg:(type, Class1) +// Info 4164: (147-153): Inferred type: 'bg:(type, Class1) +// Info 4164: (166-175): Inferred type: 'bi:(type, Class1) +// Info 4164: (166-175): Inferred type: 'bi:(type, Class1) +// Info 4164: (169-175): Inferred type: 'bi:(type, Class1) +// Info 4164: (176-195): Inferred type: 'bi:(type, Class1) -> () +// Info 4164: (186-192): Inferred type: 'bi:(type, Class1) +// Info 4164: (187-191): Inferred type: 'bi:(type, Class1) +// Info 4164: (190-191): Inferred type: 'bi:(type, Class1) diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class.sol new file mode 100644 index 000000000000..aa0012eac16f --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class.sol @@ -0,0 +1,8 @@ +pragma experimental solidity; + +forall (A, B) +class Self: C {} +// ==== +// EVMVersion: >=constantinople +// ---- +// ParserError 5709: (45-50): Expected a function definition. diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class_instantiation.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class_instantiation.sol new file mode 100644 index 000000000000..31573447a369 --- /dev/null +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class_instantiation.sol @@ -0,0 +1,12 @@ +pragma experimental solidity; + +type T; + +class Self: C {} + +forall (A, B) +instantiation T: C {} +// ==== +// EVMVersion: >=constantinople +// ---- +// ParserError 5709: (72-85): Expected a function definition. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol index c0284b330e25..8f58c77ce6f3 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol @@ -6,7 +6,7 @@ contract C { } } // ==== -// EVMVersion: <=shanghai +// EVMVersion: =shanghai // ---- -// DeclarationError 4619: (106-114): Function "blobhash" not found. +// TypeError 8314: (106-114): The "blobhash" instruction is only available for Cancun-compatible VMs (you are currently compiling for "shanghai"). // DeclarationError 8678: (99-116): Variable count for assignment to "ret" does not match number of values (1 vs. 0) diff --git a/test/libsolidity/syntaxTests/inlineAssembly/mcopy_pre_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/mcopy_pre_cancun.sol index 090e2f62862c..96be578948c9 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/mcopy_pre_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/mcopy_pre_cancun.sol @@ -6,6 +6,6 @@ contract C { } } // ==== -// EVMVersion: =cancun +// ---- +// Warning 2394: (72-78): 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. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/tstore_warning_only_once_multiple_sources.sol b/test/libsolidity/syntaxTests/inlineAssembly/tstore_warning_only_once_multiple_sources.sol new file mode 100644 index 000000000000..51e3a19bccc0 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/tstore_warning_only_once_multiple_sources.sol @@ -0,0 +1,34 @@ +==== Source: A ==== +contract C { + function f() external { + assembly { + tstore(0, 0) + let a := tload(0) + tstore(0, 1) + tstore(1, a) + } + } +} +==== Source: B ==== +import {C as C} from "A"; +contract D { + function g() external { + assembly { + tstore(0, 0) + tstore(0, 1) + } + } +} +==== Source: C ==== +contract X { + function h() external { + assembly { + tstore(0, 0) + tstore(0, 0) + } + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 2394: (A:72-78): 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. diff --git a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol index 21c48cc43323..f22b9755d652 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol @@ -7,6 +7,6 @@ contract test { } } // ==== -// EVMVersion: >=shanghai +// EVMVersion: >=cancun // ---- -// Warning 5574: (21-27154): Contract code size is 27187 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. +// 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/combined_too_large_shanghai.sol b/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol index 3fc466db3927..32e8d9133be2 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol @@ -29,4 +29,4 @@ contract test { // Warning 5574: (0-27130): Contract code size is 27187 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. // Warning 5574: (27132-27224): Contract code size is 27213 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. // Warning 5574: (27226-27319): Contract code size is 27212 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. -// Warning 3860: (27321-27398): Contract initcode size is 54628 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 3860: (27321-27398): Contract initcode size is 54618 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). 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/initcode_too_large_shanghai.sol b/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol index f82434d5d663..d48693db05b1 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol @@ -27,4 +27,4 @@ contract test { // ==== // EVMVersion: =shanghai // ---- -// Warning 3860: (20321-20415): Contract initcode size is 60896 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 3860: (20321-20415): Contract initcode size is 60882 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). 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/types/magic_block_blobbasefee_error.sol b/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_error.sol index 11a5bd991ae4..1546ea7c9f98 100644 --- a/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_error.sol +++ b/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_error.sol @@ -12,5 +12,5 @@ contract C { // EVMVersion: =shanghai // ---- // TypeError 1006: (74-91): "blobbasefee" is not supported by the VM version. -// DeclarationError 4619: (187-198): Function "blobbasefee" not found. +// TypeError 6679: (187-198): The "blobbasefee" instruction is only available for Cancun-compatible VMs (you are currently compiling for "shanghai"). // DeclarationError 8678: (180-200): Variable count for assignment to "ret" does not match number of values (1 vs. 0) diff --git a/test/libsolidity/util/SoltestTypes.h b/test/libsolidity/util/SoltestTypes.h index b5b746e325e5..791cea011610 100644 --- a/test/libsolidity/util/SoltestTypes.h +++ b/test/libsolidity/util/SoltestTypes.h @@ -215,9 +215,16 @@ struct FunctionCallExpectations raw += param.rawBytes; return raw; } - /// Gas used by function call - /// Should have values for Yul, YulOptimized, Legacy and LegacyOptimized - std::map gasUsed; + /// Gas used by function call minus the portion spent on code deposits (which is tracked + /// separately, in @a gasUsedForCodeDeposit). + /// bytecode (and therefore the cost), except for EVM version. E.g. IR codegen without + /// optimization legacy codegen with optimization. + std::map gasUsedExcludingCode; + + /// The portion of @a gasUsed spent on code deposits of newly created contracts. + /// May exceed @a gasUsed in rare corner cases due to refunds. + /// Keys must always match @a gasUsedExcludingCode. + std::map gasUsedForCodeDeposit; }; /** diff --git a/test/libsolidity/util/TestFileParser.cpp b/test/libsolidity/util/TestFileParser.cpp index 3fba998a07bf..5a32a1591a16 100644 --- a/test/libsolidity/util/TestFileParser.cpp +++ b/test/libsolidity/util/TestFileParser.cpp @@ -84,18 +84,31 @@ std::vector TestFileParser::parseFunctio BOOST_THROW_EXCEPTION(TestParserError("Expected function call before gas usage filter.")); std::string runType = m_scanner.currentLiteral(); - if (std::set{"ir", "irOptimized", "legacy", "legacyOptimized"}.count(runType) > 0) - { - m_scanner.scanNextToken(); - expect(Token::Colon); - if (calls.back().expectations.gasUsed.count(runType) > 0) - throw TestParserError("Gas usage expectation set multiple times."); - calls.back().expectations.gasUsed[runType] = u256(parseDecimalNumber()); - } - else + if (std::set{"ir", "irOptimized", "legacy", "legacyOptimized"}.count(runType) == 0) BOOST_THROW_EXCEPTION(TestParserError( "Expected \"ir\", \"irOptimized\", \"legacy\", or \"legacyOptimized\"." )); + m_scanner.scanNextToken(); + + bool isCodeDepositCost = false; + if (accept(Token::Identifier)) + { + if (m_scanner.currentLiteral() != "code") + BOOST_THROW_EXCEPTION(TestParserError("Expected \"code\" or \":\".")); + isCodeDepositCost = true; + m_scanner.scanNextToken(); + } + + expect(Token::Colon); + + std::map& gasExpectationMap = (isCodeDepositCost ? + calls.back().expectations.gasUsedForCodeDeposit : + calls.back().expectations.gasUsedExcludingCode + ); + if (gasExpectationMap.count(runType) > 0) + throw TestParserError("Gas usage expectation set multiple times."); + + gasExpectationMap[runType] = u256(parseDecimalNumber()); } else { @@ -189,6 +202,17 @@ std::vector TestFileParser::parseFunctio } } } + + for (FunctionCall& call: calls) + { + // Ensure that each specified gas expectation has both components to simplify working with them. + for (auto const& [runType, gas]: call.expectations.gasUsedForCodeDeposit) + call.expectations.gasUsedExcludingCode.try_emplace({runType, 0}); + + for (auto const& [runType, gas]: call.expectations.gasUsedExcludingCode) + call.expectations.gasUsedForCodeDeposit.try_emplace({runType, 0}); + } + return calls; } diff --git a/test/libsolidity/util/TestFileParserTests.cpp b/test/libsolidity/util/TestFileParserTests.cpp index 59934fdb25cc..4bb4aed3aced 100644 --- a/test/libsolidity/util/TestFileParserTests.cpp +++ b/test/libsolidity/util/TestFileParserTests.cpp @@ -49,18 +49,18 @@ std::vector parse(std::string const& _source, std::map _rawArguments = std::vector{}, - bool _isConstructor = false, - bool _isLibrary = false + FunctionCall const& _call, + FunctionCall::DisplayMode _mode, + std::string _signature = "", + bool _failure = true, + bytes _arguments = bytes{}, + bytes _expectations = bytes{}, + FunctionValue _value = { 0 }, + std::string _argumentComment = "", + std::string _expectationComment = "", + std::vector _rawArguments = std::vector{}, + bool _isConstructor = false, + bool _isLibrary = false ) { BOOST_REQUIRE_EQUAL(_call.expectations.failure, _failure); @@ -1063,6 +1063,147 @@ BOOST_AUTO_TEST_CASE(call_effects) BOOST_CHECK_THROW(parse(source, builtins), std::exception); } +BOOST_AUTO_TEST_CASE(gas) +{ + char const* source = R"( + // f() -> + // gas ir: 3245 + // gas legacy: 5000 + // gas legacyOptimized: 0 + )"; + auto const calls = parse(source); + BOOST_REQUIRE_EQUAL(calls.size(), 1); + BOOST_REQUIRE_EQUAL(calls[0].expectations.failure, false); + BOOST_TEST(calls[0].expectations.gasUsedExcludingCode == (std::map{ + {"ir", 3245}, + {"legacy", 5000}, + {"legacyOptimized", 0}, + })); + BOOST_TEST(calls[0].expectations.gasUsedForCodeDeposit == (std::map{ + {"ir", 0}, + {"legacy", 0}, + {"legacyOptimized", 0}, + })); +} + +BOOST_AUTO_TEST_CASE(gas_before_call) +{ + char const* source = R"( + // gas ir: 3245 + // f() -> + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_invalid_run_type) +{ + char const* source = R"( + // f() -> + // gas ir: 3245 + // gas experimental: 5000 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_duplicate_run_type) +{ + char const* source = R"( + // f() -> + // gas ir: 3245 + // gas ir: 3245 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost) +{ + char const* source = R"( + // f() -> + // gas legacyOptimized code: 1 + // gas ir: 13000 + // gas irOptimized: 6000 + // gas irOptimized code: 666 + // gas legacy code: 0 + // gas legacyOptimized: 1 + )"; + auto const calls = parse(source); + BOOST_REQUIRE_EQUAL(calls.size(), 1); + BOOST_REQUIRE_EQUAL(calls[0].expectations.failure, false); + BOOST_TEST(calls[0].expectations.gasUsedExcludingCode == (std::map{ + {"ir", 13000}, + {"irOptimized", 6000}, + {"legacy", 0}, + {"legacyOptimized", 1}, + })); + BOOST_TEST(calls[0].expectations.gasUsedForCodeDeposit == (std::map{ + {"ir", 0}, + {"irOptimized", 666}, + {"legacy", 0}, + {"legacyOptimized", 1}, + })); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_invalid_suffix) +{ + char const* source = R"( + // f() -> + // gas ir data: 3245 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_tokens_after_suffix) +{ + char const* source = R"( + // f() -> + // gas ir code code: 3245 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_double_code_gas) +{ + char const* source = R"( + // f() -> + // gas ir: 3245 + // gas ir code: 1 + // gas ir code: 1 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_non_code_cost) +{ + // NOTE: This arrangement is unlikely but may still be possible due to refunds. + // We'll deal with it when we actually have a test case like that. + char const* source = R"( + // f() -> + // gas ir: -10 + // gas ir code: 20 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_total_cost) +{ + char const* source = R"( + // f() -> + // gas ir: -30 + // gas ir code: 20 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_code_cost) +{ + char const* source = R"( + // f() -> + // gas ir: 10 + // gas ir code: -10 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index 64dfbd98253e..dd74d4035c68 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -21,6 +21,10 @@ #include +#include +#include +#include + #include #include #include @@ -331,35 +335,77 @@ std::string TestFunctionCall::formatRawParameters( return os.str(); } +namespace +{ + +std::string formatGasDiff(std::optional const& _gasUsed, std::optional const& _reference) +{ + if (!_reference.has_value() || !_gasUsed.has_value() || _gasUsed == _reference) + return ""; + + solUnimplementedAssert(*_gasUsed < u256(1) << 255); + solUnimplementedAssert(*_reference < u256(1) << 255); + s256 difference = static_cast(*_gasUsed) - static_cast(*_reference); + + if (*_reference == 0) + return fmt::format("{}", difference.str()); + + int percent = static_cast( + 100.0 * (static_cast(difference) / static_cast(*_reference)) + ); + return fmt::format("{} ({:+}%)", difference.str(), percent); +} + +// TODO: Convert this into a generic helper for getting optional form a map +std::optional gasOrNullopt(std::map const& _map, std::string const& _key) +{ + auto it = _map.find(_key); + if (it == _map.end()) + return std::nullopt; + + return it->second; +} + +} + std::string TestFunctionCall::formatGasExpectations( std::string const& _linePrefix, bool _useActualCost, bool _showDifference ) const { + using ranges::views::keys; + using ranges::views::set_symmetric_difference; + + soltestAssert(set_symmetric_difference(m_codeDepositGasCosts | keys, m_gasCostsExcludingCode | keys).empty()); + soltestAssert(set_symmetric_difference(m_call.expectations.gasUsedForCodeDeposit | keys, m_call.expectations.gasUsedExcludingCode | keys).empty()); + std::stringstream os; - for (auto const& [runType, gasUsed]: (_useActualCost ? m_gasCosts : m_call.expectations.gasUsed)) - if (!runType.empty()) + for (auto const& [runType, gasUsedExcludingCode]: (_useActualCost ? m_gasCostsExcludingCode : m_call.expectations.gasUsedExcludingCode)) + { + soltestAssert(runType != ""); + + u256 gasUsedForCodeDeposit = (_useActualCost ? m_codeDepositGasCosts : m_call.expectations.gasUsedForCodeDeposit).at(runType); + + os << std::endl << _linePrefix << "// gas " << runType << ": " << gasUsedExcludingCode.str(); + std::string gasDiff = formatGasDiff( + gasOrNullopt(m_gasCostsExcludingCode, runType), + gasOrNullopt(m_call.expectations.gasUsedExcludingCode, runType) + ); + if (_showDifference && !gasDiff.empty() && _useActualCost) + os << " [" << gasDiff << "]"; + + if (gasUsedForCodeDeposit != 0) { - bool differentResults = - m_gasCosts.count(runType) > 0 && - m_call.expectations.gasUsed.count(runType) > 0 && - m_gasCosts.at(runType) != m_call.expectations.gasUsed.at(runType); - - s256 difference = 0; - if (differentResults) - difference = - static_cast(m_gasCosts.at(runType)) - - static_cast(m_call.expectations.gasUsed.at(runType)); - int percent = 0; - if (differentResults) - percent = static_cast( - 100.0 * (static_cast(difference) / static_cast(m_call.expectations.gasUsed.at(runType))) - ); - os << std::endl << _linePrefix << "// gas " << runType << ": " << (gasUsed.str()); - if (_showDifference && differentResults && _useActualCost) - os << " [" << std::showpos << difference << " (" << percent << "%)]"; - } + os << std::endl << _linePrefix << "// gas " << runType << " code: " << gasUsedForCodeDeposit.str(); + std::string codeGasDiff = formatGasDiff( + gasOrNullopt(m_codeDepositGasCosts, runType), + gasOrNullopt(m_call.expectations.gasUsedForCodeDeposit, runType) + ); + if (_showDifference && !codeGasDiff.empty() && _useActualCost) + os << " [" << codeGasDiff << "]"; + } + } return os.str(); } diff --git a/test/libsolidity/util/TestFunctionCall.h b/test/libsolidity/util/TestFunctionCall.h index 8b4ed5019d41..724cb8286c19 100644 --- a/test/libsolidity/util/TestFunctionCall.h +++ b/test/libsolidity/util/TestFunctionCall.h @@ -51,7 +51,11 @@ class TestFunctionCall ExpectedValuesActualGas }; - TestFunctionCall(FunctionCall _call): m_call(std::move(_call)), m_gasCosts(m_call.expectations.gasUsed) {} + TestFunctionCall(FunctionCall _call): + m_call(std::move(_call)), + m_gasCostsExcludingCode(m_call.expectations.gasUsedExcludingCode), + m_codeDepositGasCosts(m_call.expectations.gasUsedForCodeDeposit) + {} /// Formats this function call test and applies the format that was detected during parsing. /// _renderMode determines the source of values to be inserted into the updated test expectations. @@ -93,7 +97,8 @@ class TestFunctionCall void calledNonExistingFunction() { m_calledNonExistingFunction = true; } void setFailure(const bool _failure) { m_failure = _failure; } void setRawBytes(const bytes _rawBytes) { m_rawBytes = _rawBytes; } - void setGasCost(std::string const& _runType, u256 const& _gasCost) { m_gasCosts[_runType] = _gasCost; } + void setGasCostExcludingCode(std::string const& _runType, u256 const& _gasCost) { m_gasCostsExcludingCode[_runType] = _gasCost; } + void setCodeDepositGasCost(std::string const& _runType, u256 const& _gasCost) { m_codeDepositGasCosts[_runType] = _gasCost; } void setContractABI(Json::Value _contractABI) { m_contractABI = std::move(_contractABI); } void setSideEffects(std::vector _sideEffects) { m_call.actualSideEffects = _sideEffects; } @@ -142,7 +147,9 @@ class TestFunctionCall /// Result of the actual call been made. bytes m_rawBytes = bytes{}; /// Actual gas costs - std::map m_gasCosts; + std::map m_gasCostsExcludingCode; + /// Actual code deposit gas costs + std::map m_codeDepositGasCosts; /// Transaction status of the actual call. False in case of a REVERT or any other failure. bool m_failure = true; /// JSON object which holds the contract ABI and that is used to set the output formatting diff --git a/test/libsolidity/util/TestFunctionCallTests.cpp b/test/libsolidity/util/TestFunctionCallTests.cpp index fa3fe995cac5..5741ccd0debe 100644 --- a/test/libsolidity/util/TestFunctionCallTests.cpp +++ b/test/libsolidity/util/TestFunctionCallTests.cpp @@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(format_unsigned_singleline) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(format_unsigned_singleline_signed_encoding) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(format_unsigned_multiline) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter result{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{result}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{result}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{}, std::string{}}; FunctionCall call{"f(uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(format_multiple_unsigned_singleline) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param, param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param, param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param, param}, std::string{}}; FunctionCall call{"f(uint8, uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(format_signed_singleline) bytes expectedBytes = toBigEndian(u256{-1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "-1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(int8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(format_hex_singleline) bytes expectedBytes = result + bytes(32 - result.size(), 0); ABIType abiType{ABIType::Hex, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "0x31", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bytes32)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(format_hex_string_singleline) bytes expectedBytes = fromHex("4200ef"); ABIType abiType{ABIType::HexString, ABIType::AlignLeft, 3}; Parameter param{expectedBytes, "hex\"4200ef\"", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(string)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(format_bool_true_singleline) bytes expectedBytes = toBigEndian(u256{true}); ABIType abiType{ABIType::Boolean, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "true", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bool)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE(format_bool_false_singleline) bytes expectedBytes = toBigEndian(u256{false}); ABIType abiType{ABIType::Boolean, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "false", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bool)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -198,7 +198,7 @@ BOOST_AUTO_TEST_CASE(format_bool_left_singleline) bytes expectedBytes = toBigEndian(u256{false}); ABIType abiType{ABIType::Boolean, ABIType::AlignLeft, 32}; Parameter param{expectedBytes, "left(false)", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bool)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -213,7 +213,7 @@ BOOST_AUTO_TEST_CASE(format_hex_number_right_singleline) bytes expectedBytes = result + bytes(32 - result.size(), 0); ABIType abiType{ABIType::Hex, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "right(0x42)", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bool)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(format_empty_byte_range) bytes expectedBytes; ABIType abiType{ABIType::None, ABIType::AlignNone, 0}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{}, std::string{}}; FunctionCall call{"f()", {0}, arguments, expectations}; call.omitsArrow = false; @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(format_failure_singleline) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{}, true, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{}, true, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -250,6 +250,73 @@ BOOST_AUTO_TEST_CASE(format_failure_singleline) BOOST_REQUIRE_EQUAL(test.format(), "// f(uint8): 1 -> FAILURE"); } +BOOST_AUTO_TEST_CASE(format_gas) +{ + FunctionCall call{ + "f()", + FunctionValue{0}, + FunctionCallArgs{}, + FunctionCallExpectations{ + std::vector{}, + false, // failure + "some comment", + { + {"ir", 3245}, + {"legacy", 5000}, + {"legacy optimized", 0}, + }, + { + {"ir", 0}, + {"legacy", 0}, + {"legacy optimized", 0}, + }, + } + }; + call.omitsArrow = false; + + BOOST_REQUIRE_EQUAL( + TestFunctionCall(call).format(), + "// f() -> #some comment#\n" + "// gas ir: 3245\n" + "// gas legacy: 5000\n" + "// gas legacy optimized: 0" + ); +} + +BOOST_AUTO_TEST_CASE(format_gas_with_code_deposit) +{ + FunctionCall call{ + "f()", + FunctionValue{0}, + FunctionCallArgs{}, + FunctionCallExpectations{ + std::vector{}, + false, // failure + "some comment", + { + {"ir", 0}, // Zero costs are shown + {"legacy", 4875}, + {"legacy optimized", 300}, + }, + { + {"ir", 0}, // Zero code deposit costs are omitted + {"legacy", 125}, + {"legacy optimized", 0}, + }, + } + }; + call.omitsArrow = false; + + BOOST_REQUIRE_EQUAL( + TestFunctionCall(call).format(), + "// f() -> #some comment#\n" + "// gas ir: 0\n" + "// gas legacy: 4875\n" + "// gas legacy code: 125\n" + "// gas legacy optimized: 300" + ); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libyul/yulInterpreterTests/mcopy.yul b/test/libyul/yulInterpreterTests/mcopy.yul index 6483239cb151..3ec6af00213f 100644 --- a/test/libyul/yulInterpreterTests/mcopy.yul +++ b/test/libyul/yulInterpreterTests/mcopy.yul @@ -7,7 +7,7 @@ mcopy(0x60, 0, 32) // Append a duplicate of the first word past msize mcopy(0x90, 0x30, 1) // Copy the 0x44 byte from the middle of second word past msize mcopy(0, 0, 0) // No-op - mcopy(0x2f, 0x90, 2) // Copy the 0x4400 straddling msize back into the the middle of second word + mcopy(0x2f, 0x90, 2) // Copy the 0x4400 straddling msize back into the middle of second word mcopy(0xa0, 0, 160) // Duplicate the whole thing } // ==== diff --git a/test/libyul/yulSyntaxTests/tstore_warning_only_once.yul b/test/libyul/yulSyntaxTests/tstore_warning_only_once.yul new file mode 100644 index 000000000000..44a6b59b49ab --- /dev/null +++ b/test/libyul/yulSyntaxTests/tstore_warning_only_once.yul @@ -0,0 +1,10 @@ +{ + tstore(0, 0) + tstore(0, 1) + let x := tload(0) + tstore(1, 0) +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 2394: (6-12): 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. diff --git a/test/scripts/test_gas_diff_stats.py b/test/scripts/test_gas_diff_stats.py new file mode 100644 index 000000000000..e67bd0be8930 --- /dev/null +++ b/test/scripts/test_gas_diff_stats.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python + +import unittest +from textwrap import dedent + +# NOTE: This test file file only works with scripts/ added to PYTHONPATH so pylint can't find the imports +# pragma pylint: disable=import-error +from gas_diff_stats import collect_statistics +# pragma pylint: enable=import-error + +class TestGasDiffStats(unittest.TestCase): + def test_collect_statistics_should_fail_on_empty_diff(self): + with self.assertRaises(RuntimeError): + self.assertEqual(collect_statistics(""), (0, 0, 0, 0, 0, 0)) + + def test_collect_statistics_should_accept_whitespace_only_diff(self): + # TODO: Should it really work this way? + # If we're rejecting empty diff, not sure why whitespace is accepted. + self.assertEqual(collect_statistics("\n"), (0, 0, 0, 0, 0, 0)) + self.assertEqual(collect_statistics("\n \n\t\n\n"), (0, 0, 0, 0, 0, 0)) + + def test_collect_statistics_should_report_sum_of_gas_costs(self): + diff_output = dedent(""" + diff --git a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol + index 1306529d4..77a330f3c 100644 + --- a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol + +++ b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol + @@ -38 +38,2 @@ contract D { + -// gas legacy: 102095 + +// gas legacy: 76495 + @@ -40,3 +41,6 @@ contract D { + -// gas irOptimized: 98438588 + -// gas legacy: 98438774 + -// gas legacyOptimized: 98438580 + +// gas irOptimized: 25388 + +// gas legacy: 98413174 + +// gas legacyOptimized: 25380 + @@ -44,3 +48,6 @@ contract D { + -// gas irOptimized: 98438589 + -// gas legacy: 98438774 + -// gas legacyOptimized: 98438580 + +// gas irOptimized: 25389 + +// gas legacy: 98413174 + +// gas legacyOptimized: 25380 + """).splitlines() + + self.assertEqual(collect_statistics(diff_output), ( + 98438588 + 98438589, # -irOptimized + 98438580 + 98438580, # -legacyOptimized + 102095 + 98438774 + 98438774, # -legacy + 25388 + 25389, # +irOptimized + 25380 + 25380, # +legacyOptimized + 76495 + 98413174 + 98413174, # +legacy + )) + + def test_collect_statistics_should_ignore_ir_costs(self): + diff_output = dedent(""" + -// gas legacy: 1 + -// gas ir: 2 + +// gas legacy: 3 + +// gas ir: 4 + """).splitlines() + + self.assertEqual(collect_statistics(diff_output), ( + 0, # -irOptimized + 0, # -legacyOptimized + 1, # -legacy + 0, # +irOptimized + 0, # +legacyOptimized + 3, # +legacy + )) + + def test_collect_statistics_should_ignore_unchanged_costs(self): + diff_output = dedent(""" + -// gas legacy: 1 + // gas legacyOptimized: 2 + +// gas legacy: 3 + """).splitlines() + + self.assertEqual(collect_statistics(diff_output), ( + 0, # -irOptimized + 0, # -legacyOptimized + 1, # -legacy + 0, # +irOptimized + 0, # +legacyOptimized + 3, # +legacy + )) + + def test_collect_statistics_should_include_code_deposit_in_total_cost(self): + diff_output = dedent(""" + -// gas irOptimized: 1 + -// gas legacy: 20 + -// gas legacyOptimized: 300 + +// gas irOptimized: 4000 + +// gas irOptimized code: 50000 + +// gas legacy: 600000 + +// gas legacyOptimized: 7000000 + +// gas legacyOptimized code: 80000000 + -// gas legacy code: 900000000 + """).splitlines() + + self.assertEqual(collect_statistics(diff_output), ( + 1, # -irOptimized + 300, # -legacyOptimized + 900000020, # -legacy + 54000, # +irOptimized + 87000000, # +legacyOptimized + 600000, # +legacy + )) diff --git a/test/soltest.cpp b/test/soltest.cpp index 6aa100248875..5fde4bda5679 100644 --- a/test/soltest.cpp +++ b/test/soltest.cpp @@ -35,6 +35,7 @@ #pragma warning(pop) #endif +#pragma GCC diagnostic pop #pragma GCC diagnostic pop #include @@ -49,7 +50,6 @@ using namespace boost::unit_test; using namespace solidity::frontend::test; namespace fs = boost::filesystem; -using namespace std; namespace { @@ -100,7 +100,7 @@ void runTestCase(TestCase::Config const& _config, TestCase::TestCaseCreator cons { try { - stringstream errorStream; + std::stringstream errorStream; auto testCase = _testCaseCreator(_config); if (testCase->shouldRun()) switch (testCase->run(errorStream)) @@ -133,7 +133,7 @@ int registerTests( boost::unit_test::test_suite& _suite, boost::filesystem::path const& _basepath, boost::filesystem::path const& _path, - vector const& _labels, + std::vector const& _labels, TestCase::TestCaseCreator _testCaseCreator, solidity::test::Batcher& _batcher ) @@ -176,9 +176,9 @@ int registerTests( // This must be a vector of unique_ptrs because Boost.Test keeps the equivalent of a string_view to the filename // that is passed in. If the strings were stored directly in the vector, pointers/references to them would be // invalidated on reallocation. - static vector> filenames; + static std::vector> filenames; - filenames.emplace_back(make_unique(_path.string())); + filenames.emplace_back(std::make_unique(_path.string())); auto test_case = make_test_case( [config, _testCaseCreator] { @@ -236,14 +236,14 @@ test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) exit(EXIT_FAILURE); if (solidity::test::CommonOptions::get().disableSemanticTests) - cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl; + std::cout << std::endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << std::endl << std::endl; if (!solidity::test::CommonOptions::get().enforceGasTest) - cout << endl << "WARNING :: Gas Cost Expectations are not being enforced" << endl << endl; + 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) - cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << endl; + std::cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << std::endl; // Batch the boost tests BoostBatcher boostBatcher(batcher); @@ -290,12 +290,12 @@ test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) } catch (solidity::test::ConfigException const& exception) { - cerr << exception.what() << endl; + std::cerr << exception.what() << std::endl; exit(EXIT_FAILURE); } catch (std::runtime_error const& exception) { - cerr << exception.what() << endl; + std::cerr << exception.what() << std::endl; exit(EXIT_FAILURE); } diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 2d93bdbc2b9a..9d20f1059fb3 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -448,9 +448,6 @@ int main(int argc, char const *argv[]) if (options.disableSemanticTests) cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl; - if (!options.enforceGasTest) - cout << "WARNING :: Gas Cost Expectations are not being enforced" << endl << endl; - TestStats global_stats{0, 0}; cout << "Running tests..." << endl << endl; diff --git a/test/tools/ossfuzz/README.md b/test/tools/ossfuzz/README.md index 9343602d44d2..dae338648980 100644 --- a/test/tools/ossfuzz/README.md +++ b/test/tools/ossfuzz/README.md @@ -69,7 +69,7 @@ To help oss-fuzz do this, we (as project maintainers) need to provide the follow To be consistent and aid better evaluation of the utility of the fuzzing dictionary, we stick to the following rules-of-thumb: - Full tokens such as `block.number` are preceded and followed by a whitespace - - Incomplete tokens including function calls such as `msg.sender.send()` are abbreviated `.send(` to provide some leeway to the fuzzer to sythesize variants such as `address(this).send()` + - Incomplete tokens including function calls such as `msg.sender.send()` are abbreviated `.send(` to provide some leeway to the fuzzer to synthesize variants such as `address(this).send()` - Language keywords are suffixed by a whitespace with the exception of those that end a line of code such as `break;` and `continue;` [1]: https://github.com/google/oss-fuzz diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 6c8f291d29a3..1ba0d599d4b7 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -593,6 +593,18 @@ void ProtoConverter::visit(UnaryOp const& _x) return; } + if (op == UnaryOp::TLOAD && !m_evmVersion.supportsTransientStorage()) + { + m_output << dictionaryToken(); + return; + } + + if (op == UnaryOp::BLOBHASH && !m_evmVersion.hasBlobHash()) + { + m_output << dictionaryToken(); + return; + } + // The following instructions may lead to change of EVM state and are hence // excluded to avoid false positives. if ( @@ -620,6 +632,9 @@ void ProtoConverter::visit(UnaryOp const& _x) case UnaryOp::SLOAD: m_output << "sload"; break; + case UnaryOp::TLOAD: + m_output << "tload"; + break; case UnaryOp::ISZERO: m_output << "iszero"; break; @@ -638,6 +653,9 @@ void ProtoConverter::visit(UnaryOp const& _x) case UnaryOp::BLOCKHASH: m_output << "blockhash"; break; + case UnaryOp::BLOBHASH: + m_output << "blobhash"; + break; } m_output << "("; if (op == UnaryOp::MLOAD) @@ -796,6 +814,10 @@ void ProtoConverter::visit(CopyFunc const& _x) if (type == CopyFunc::RETURNDATA && !m_evmVersion.supportsReturndata()) return; + // Bail out if MCOPY is not supported for fuzzed EVM version + if (type == CopyFunc::MEMORY && !m_evmVersion.hasMcopy()) + return; + // Code copy may change state if e.g., some byte of code // is stored to storage via a sequence of mload and sstore. if (m_filterStatefulInstructions && type == CopyFunc::CODE) @@ -816,13 +838,22 @@ void ProtoConverter::visit(CopyFunc const& _x) case CopyFunc::DATA: m_output << "datacopy"; break; + case CopyFunc::MEMORY: + m_output << "mcopy"; } m_output << "("; m_output << "mod("; visit(_x.target()); m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; - visit(_x.source()); + if (type == CopyFunc::MEMORY) + { + m_output << "mod("; + visit(_x.source()); + m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + } + else + visit(_x.source()); m_output << ", "; m_output << "mod("; visit(_x.size()); @@ -1141,9 +1172,12 @@ void ProtoConverter::visit(StoreFunc const& _x) case StoreFunc::MSTORE8: m_output << "mstore8("; break; + case StoreFunc::TSTORE: + m_output << "tstore("; + break; } // Write to memory within bounds, storage is unbounded - if (storeType == StoreFunc::SSTORE) + if (storeType == StoreFunc::SSTORE || storeType == StoreFunc::TSTORE) visit(_x.loc()); else if (storeType == StoreFunc::MSTORE8) { @@ -1755,18 +1789,29 @@ void ProtoConverter::fillFunctionCallInput(unsigned _numInParams) void ProtoConverter::saveFunctionCallOutput(vector const& _varsVec) { - for (auto const& var: _varsVec) + constexpr auto numSlots = 10; + constexpr auto slotSize = 32; + + for (string const& var: _varsVec) { // Flip a dice to choose whether to save output values // in storage or memory. - bool coinFlip = counter() % 2 == 0; + unsigned diceThrow = counter() % (m_evmVersion.supportsTransientStorage() ? 3 : 2); // Pseudo-randomly choose one of the first ten 32-byte // aligned slots. - string slot = to_string((counter() % 10) * 32); - if (coinFlip) + string slot = std::to_string((counter() % numSlots) * slotSize); + if (diceThrow == 0) m_output << "sstore(" << slot << ", " << var << ")\n"; - else + else if (diceThrow == 1) m_output << "mstore(" << slot << ", " << var << ")\n"; + else + { + yulAssert( + m_evmVersion.supportsTransientStorage(), + "Proto fuzzer: Invalid evm version" + ); + m_output << "tstore(" << slot << ", " << var << ")\n"; + } } } diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index b7f7c72e5a8e..c264dd51af13 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -346,7 +346,9 @@ class ProtoConverter static auto constexpr s_dataIdentifier = "datablock"; /// Upper bound on memory writes is 64KB in order to /// preserve semantic equivalence in the presence of - /// memory guard + /// memory guard. Note that s_maxMemory must be much larger + /// than s_maxSize to create tests without significant overlap + /// of I/O memory regions. static unsigned constexpr s_maxMemory = 65536; /// Upper bound on size for range copy functions static unsigned constexpr s_maxSize = 32768; diff --git a/test/tools/ossfuzz/yulProto.proto b/test/tools/ossfuzz/yulProto.proto index 7552fb23adde..cf14b887c1b3 100644 --- a/test/tools/ossfuzz/yulProto.proto +++ b/test/tools/ossfuzz/yulProto.proto @@ -149,12 +149,14 @@ message UnaryOp { NOT = 0; MLOAD = 1; SLOAD = 2; - ISZERO = 3; - CALLDATALOAD = 4; - EXTCODESIZE = 5; - EXTCODEHASH = 6; - BALANCE = 7; - BLOCKHASH = 8; + TLOAD = 3; + ISZERO = 4; + CALLDATALOAD = 5; + EXTCODESIZE = 6; + EXTCODEHASH = 7; + BALANCE = 8; + BLOCKHASH = 9; + BLOBHASH = 10; } required UOp op = 1; required Expression operand = 2; @@ -186,6 +188,7 @@ message CopyFunc { CODE = 1; RETURNDATA = 2; DATA = 3; + MEMORY = 4; } required CopyType ct = 1; required Expression target = 2; @@ -230,6 +233,7 @@ message StoreFunc { MSTORE = 0; SSTORE = 1; MSTORE8 = 2; + TSTORE = 3; } required Expression loc = 1; required Expression val = 2; diff --git a/test/tools/yulInterpreter/Inspector.cpp b/test/tools/yulInterpreter/Inspector.cpp index 9c4701d00a12..7746483a367a 100644 --- a/test/tools/yulInterpreter/Inspector.cpp +++ b/test/tools/yulInterpreter/Inspector.cpp @@ -56,7 +56,7 @@ void InspectedInterpreter::run( InspectedInterpreter{_inspector, _state, _dialect, scope, _disableExternalCalls, _disableMemoryTrace}(_ast); } -Inspector::NodeAction Inspector::queryUser(DebugData const& _data, std::map const& _variables) +Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std::map const& _variables) { if (m_stepMode == NodeAction::RunNode) { @@ -131,7 +131,7 @@ Inspector::NodeAction Inspector::queryUser(DebugData const& _data, std::map(_data.nativeLocation.start), diff --git a/test/tools/yulInterpreter/Inspector.h b/test/tools/yulInterpreter/Inspector.h index 611279c6fe1c..f4518c7087d3 100644 --- a/test/tools/yulInterpreter/Inspector.h +++ b/test/tools/yulInterpreter/Inspector.h @@ -53,13 +53,13 @@ class Inspector * @returns NodeAction::RunNode if the current AST node (and all children nodes!) should be * processed without stopping, else NodeAction::StepThroughNode. */ - NodeAction queryUser(DebugData const& _data, std::map const& _variables); + NodeAction queryUser(langutil::DebugData const& _data, std::map const& _variables); void stepMode(NodeAction _action) { m_stepMode = _action; } std::string const& source() const { return m_source; } - void interactiveVisit(DebugData const& _debugData, std::map const& _variables, std::function _visitNode) + void interactiveVisit(langutil::DebugData const& _debugData, std::map const& _variables, std::function _visitNode) { Inspector::NodeAction action = queryUser(_debugData, _variables); @@ -78,7 +78,7 @@ class Inspector } private: - std::string currentSource(DebugData const& _data) const; + std::string currentSource(langutil::DebugData const& _data) const; /// Source of the file std::string const& m_source; diff --git a/test/yulPhaser/AlgorithmRunner.cpp b/test/yulPhaser/AlgorithmRunner.cpp index 003403929eb2..56868f1ce76e 100644 --- a/test/yulPhaser/AlgorithmRunner.cpp +++ b/test/yulPhaser/AlgorithmRunner.cpp @@ -35,7 +35,6 @@ #include #include -using namespace std; using namespace boost::unit_test::framework; using namespace boost::test_tools; using namespace solidity::langutil; @@ -74,44 +73,44 @@ class AlgorithmRunnerFixture { protected: // NOTE: Regexes here should not contain spaces because we strip them before matching - regex RoundSummaryRegex{R"(-+ROUND\d+\[round:[0-9.]+s,total:[0-9.]+s\]-+)"}; - regex InitialPopulationHeaderRegex{"-+INITIALPOPULATION-+"}; + std::regex RoundSummaryRegex{R"(-+ROUND\d+\[round:[0-9.]+s,total:[0-9.]+s\]-+)"}; + std::regex InitialPopulationHeaderRegex{"-+INITIALPOPULATION-+"}; - string individualPattern(Individual const& individual) const + std::string individualPattern(Individual const& individual) const { - ostringstream output; + std::ostringstream output; output << individual.fitness << individual.chromosome; return output.str(); } - string topChromosomePattern(size_t roundNumber, Individual const& individual) const + std::string topChromosomePattern(size_t roundNumber, Individual const& individual) const { - ostringstream output; + std::ostringstream output; output << roundNumber << R"(\|[0-9.]+\|)" << individualPattern(individual); return output.str(); } - bool nextLineMatches(stringstream& stream, regex const& pattern) const + bool nextLineMatches(std::stringstream& stream, std::regex const& pattern) const { - string line; - if (getline(stream, line).fail()) + std::string line; + if (std::getline(stream, line).fail()) return false; - return regex_match(stripWhitespace(line), pattern); + return std::regex_match(stripWhitespace(line), pattern); } - shared_ptr m_fitnessMetric = make_shared(); + std::shared_ptr m_fitnessMetric = std::make_shared(); Population const m_population = Population::makeRandom(m_fitnessMetric, 5, 0, 20); - stringstream m_output; + std::stringstream m_output; AlgorithmRunner::Options m_options; }; class AlgorithmRunnerAutosaveFixture: public AlgorithmRunnerFixture { public: - static vector chromosomeStrings(Population const& _population) + static std::vector chromosomeStrings(Population const& _population) { - vector lines; + std::vector lines; for (auto const& individual: _population.individuals()) lines.push_back(toString(individual.chromosome)); @@ -120,7 +119,7 @@ class AlgorithmRunnerAutosaveFixture: public AlgorithmRunnerFixture protected: TemporaryDirectory m_tempDir; - string const m_autosavePath = (m_tempDir.path() / "population-autosave.txt").string(); + std::string const m_autosavePath = (m_tempDir.path() / "population-autosave.txt").string(); RandomisingAlgorithm m_algorithm; }; @@ -153,12 +152,12 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_round_summary_after_each_round, Algorit runner.run(algorithm); BOOST_TEST(nextLineMatches(m_output, RoundSummaryRegex)); for (auto const& individual: runner.population().individuals()) - BOOST_TEST(nextLineMatches(m_output, regex(individualPattern(individual)))); + BOOST_TEST(nextLineMatches(m_output, std::regex(individualPattern(individual)))); runner.run(algorithm); BOOST_TEST(nextLineMatches(m_output, RoundSummaryRegex)); for (auto const& individual: runner.population().individuals()) - BOOST_TEST(nextLineMatches(m_output, regex(individualPattern(individual)))); + BOOST_TEST(nextLineMatches(m_output, std::regex(individualPattern(individual)))); BOOST_TEST(m_output.peek() == EOF); } @@ -172,9 +171,9 @@ BOOST_FIXTURE_TEST_CASE(run_should_not_print_round_summary_if_not_requested, Alg RandomisingAlgorithm algorithm; runner.run(algorithm); - BOOST_TEST(nextLineMatches(m_output, regex(""))); + BOOST_TEST(nextLineMatches(m_output, std::regex(""))); for (auto const& individual: runner.population().individuals()) - BOOST_TEST(nextLineMatches(m_output, regex(individualPattern(individual)))); + BOOST_TEST(nextLineMatches(m_output, std::regex(individualPattern(individual)))); BOOST_TEST(m_output.peek() == EOF); } @@ -202,7 +201,7 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_only_top_chromosome_if_requested, Algor RandomisingAlgorithm algorithm; runner.run(algorithm); - BOOST_TEST(nextLineMatches(m_output, regex(topChromosomePattern(1, runner.population().individuals()[0])))); + BOOST_TEST(nextLineMatches(m_output, std::regex(topChromosomePattern(1, runner.population().individuals()[0])))); BOOST_TEST(m_output.peek() == EOF); } @@ -216,7 +215,7 @@ BOOST_FIXTURE_TEST_CASE(run_should_not_print_round_number_for_top_chromosome_if_ RandomisingAlgorithm algorithm; runner.run(algorithm); - BOOST_TEST(nextLineMatches(m_output, regex(individualPattern(runner.population().individuals()[0])))); + BOOST_TEST(nextLineMatches(m_output, std::regex(individualPattern(runner.population().individuals()[0])))); BOOST_TEST(m_output.peek() == EOF); } @@ -246,7 +245,7 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_initial_population_if_requested, Algori BOOST_TEST(nextLineMatches(m_output, InitialPopulationHeaderRegex)); for (auto const& individual: m_population.individuals()) - BOOST_TEST(nextLineMatches(m_output, regex(individualPattern(individual)))); + BOOST_TEST(nextLineMatches(m_output, std::regex(individualPattern(individual)))); BOOST_TEST(m_output.peek() == EOF); } @@ -277,7 +276,7 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_whole_initial_population_even_if_only_t BOOST_TEST(nextLineMatches(m_output, InitialPopulationHeaderRegex)); for (auto const& individual: m_population.individuals()) - BOOST_TEST(nextLineMatches(m_output, regex(individualPattern(individual)))); + BOOST_TEST(nextLineMatches(m_output, std::regex(individualPattern(individual)))); BOOST_TEST(m_output.peek() == EOF); } @@ -290,21 +289,21 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_cache_stats_if_requested, AlgorithmRunn m_options.showCacheStats = true; RandomisingAlgorithm algorithm; - vector sourceStreams = { + std::vector sourceStreams = { CharStream("{mstore(10, 20)}", ""), CharStream("{mstore(10, 20)\nsstore(10, 20)}", ""), }; - vector programs = { + std::vector programs = { get(Program::load(sourceStreams[0])), get(Program::load(sourceStreams[1])), }; - vector> caches = { - make_shared(programs[0]), - make_shared(programs[1]), + std::vector> caches = { + std::make_shared(programs[0]), + std::make_shared(programs[1]), }; - shared_ptr fitnessMetric = make_shared(vector>{ - make_shared(nullopt, caches[0], CodeWeights{}), - make_shared(nullopt, caches[1], CodeWeights{}), + std::shared_ptr fitnessMetric = std::make_shared(std::vector>{ + std::make_shared(std::nullopt, caches[0], CodeWeights{}), + std::make_shared(std::nullopt, caches[1], CodeWeights{}), }); Population population = Population::makeRandom(fitnessMetric, 2, 0, 5); @@ -318,14 +317,14 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_cache_stats_if_requested, AlgorithmRunn for (size_t i = 0; i < m_options.maxRounds.value() - 1; ++i) { - BOOST_TEST(nextLineMatches(m_output, regex(".*"))); - BOOST_TEST(nextLineMatches(m_output, regex("-+CACHESTATS-+"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(".*"))); + BOOST_TEST(nextLineMatches(m_output, std::regex("-+CACHESTATS-+"))); if (i > 0) - BOOST_TEST(nextLineMatches(m_output, regex(R"(Round\d+:\d+entries)"))); - BOOST_TEST(nextLineMatches(m_output, regex(R"(Round\d+:\d+entries)"))); - BOOST_TEST(nextLineMatches(m_output, regex(R"(Totalhits:\d+)"))); - BOOST_TEST(nextLineMatches(m_output, regex(R"(Totalmisses:\d+)"))); - BOOST_TEST(nextLineMatches(m_output, regex(R"(Sizeofcachedcode:\d+)"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(R"(Round\d+:\d+entries)"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(R"(Round\d+:\d+entries)"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(R"(Totalhits:\d+)"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(R"(Totalmisses:\d+)"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(R"(Sizeofcachedcode:\d+)"))); } BOOST_REQUIRE(stats.roundEntryCounts.size() == 2); @@ -333,13 +332,13 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_cache_stats_if_requested, AlgorithmRunn BOOST_REQUIRE(stats.roundEntryCounts.count(m_options.maxRounds.value()) == 1); size_t round = m_options.maxRounds.value(); - BOOST_TEST(nextLineMatches(m_output, regex(".*"))); - BOOST_TEST(nextLineMatches(m_output, regex("-+CACHESTATS-+"))); - BOOST_TEST(nextLineMatches(m_output, regex("Round" + toString(round - 1) + ":" + toString(stats.roundEntryCounts[round - 1]) + "entries"))); - BOOST_TEST(nextLineMatches(m_output, regex("Round" + toString(round) + ":" + toString(stats.roundEntryCounts[round]) + "entries"))); - BOOST_TEST(nextLineMatches(m_output, regex("Totalhits:" + toString(stats.hits)))); - BOOST_TEST(nextLineMatches(m_output, regex("Totalmisses:" + toString(stats.misses)))); - BOOST_TEST(nextLineMatches(m_output, regex("Sizeofcachedcode:" + toString(stats.totalCodeSize)))); + BOOST_TEST(nextLineMatches(m_output, std::regex(".*"))); + BOOST_TEST(nextLineMatches(m_output, std::regex("-+CACHESTATS-+"))); + BOOST_TEST(nextLineMatches(m_output, std::regex("Round" + toString(round - 1) + ":" + toString(stats.roundEntryCounts[round - 1]) + "entries"))); + BOOST_TEST(nextLineMatches(m_output, std::regex("Round" + toString(round) + ":" + toString(stats.roundEntryCounts[round]) + "entries"))); + BOOST_TEST(nextLineMatches(m_output, std::regex("Totalhits:" + toString(stats.hits)))); + BOOST_TEST(nextLineMatches(m_output, std::regex("Totalmisses:" + toString(stats.misses)))); + BOOST_TEST(nextLineMatches(m_output, std::regex("Sizeofcachedcode:" + toString(stats.totalCodeSize)))); BOOST_TEST(m_output.peek() == EOF); } @@ -355,9 +354,9 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_message_if_cache_stats_requested_but_ca AlgorithmRunner runner(m_population, {nullptr}, m_options, m_output); runner.run(algorithm); - BOOST_TEST(nextLineMatches(m_output, regex(".*"))); - BOOST_TEST(nextLineMatches(m_output, regex("-+CACHESTATS-+"))); - BOOST_TEST(nextLineMatches(m_output, regex(stripWhitespace("Program cache disabled")))); + BOOST_TEST(nextLineMatches(m_output, std::regex(".*"))); + BOOST_TEST(nextLineMatches(m_output, std::regex("-+CACHESTATS-+"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(stripWhitespace("Program cache disabled")))); BOOST_TEST(m_output.peek() == EOF); } @@ -371,18 +370,18 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_partial_stats_and_message_if_some_cache RandomisingAlgorithm algorithm; CharStream sourceStream = CharStream("{}", ""); - shared_ptr cache = make_shared(get(Program::load(sourceStream))); + std::shared_ptr cache = std::make_shared(std::get(Program::load(sourceStream))); AlgorithmRunner runner(m_population, {cache, nullptr}, m_options, m_output); BOOST_REQUIRE(cache->gatherStats().roundEntryCounts.size() == 0); runner.run(algorithm); - BOOST_TEST(nextLineMatches(m_output, regex(".*"))); - BOOST_TEST(nextLineMatches(m_output, regex("-+CACHESTATS-+"))); - BOOST_TEST(nextLineMatches(m_output, regex(R"(Totalhits:\d+)"))); - BOOST_TEST(nextLineMatches(m_output, regex(R"(Totalmisses:\d+)"))); - BOOST_TEST(nextLineMatches(m_output, regex(R"(Sizeofcachedcode:\d+)"))); - BOOST_TEST(nextLineMatches(m_output, regex(stripWhitespace("Program cache disabled for 1 out of 2 programs")))); + BOOST_TEST(nextLineMatches(m_output, std::regex(".*"))); + BOOST_TEST(nextLineMatches(m_output, std::regex("-+CACHESTATS-+"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(R"(Totalhits:\d+)"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(R"(Totalmisses:\d+)"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(R"(Sizeofcachedcode:\d+)"))); + BOOST_TEST(nextLineMatches(m_output, std::regex(stripWhitespace("Program cache disabled for 1 out of 2 programs")))); BOOST_TEST(m_output.peek() == EOF); } @@ -421,10 +420,10 @@ BOOST_FIXTURE_TEST_CASE(run_should_overwrite_existing_file_if_autosave_file_spec AlgorithmRunner runner(m_population, {}, m_options, m_output); assert(!fs::exists(m_autosavePath)); - vector originalContent = {"Original content"}; + std::vector originalContent = {"Original content"}; { - ofstream tmpFile(m_autosavePath); - tmpFile << originalContent[0] << endl; + std::ofstream tmpFile(m_autosavePath); + tmpFile << originalContent[0] << std::endl; } assert(fs::exists(m_autosavePath)); assert(readLinesFromFile(m_autosavePath) == originalContent); @@ -438,7 +437,7 @@ BOOST_FIXTURE_TEST_CASE(run_should_overwrite_existing_file_if_autosave_file_spec BOOST_FIXTURE_TEST_CASE(run_should_not_save_population_to_file_if_autosave_file_not_specified, AlgorithmRunnerAutosaveFixture) { m_options.maxRounds = 5; - m_options.populationAutosaveFile = nullopt; + m_options.populationAutosaveFile = std::nullopt; AlgorithmRunner runner(m_population, {}, m_options, m_output); assert(!fs::exists(m_autosavePath)); @@ -499,9 +498,9 @@ BOOST_FIXTURE_TEST_CASE(run_should_not_randomise_duplicate_chromosomes_if_not_re BOOST_FIXTURE_TEST_CASE(run_should_clear_cache_at_the_beginning_and_update_it_before_each_round, AlgorithmRunnerFixture) { CharStream sourceStream = CharStream("{}", current_test_case().p_name); - vector> caches = { - make_shared(get(Program::load(sourceStream))), - make_shared(get(Program::load(sourceStream))), + std::vector> caches = { + std::make_shared(std::get(Program::load(sourceStream))), + std::make_shared(std::get(Program::load(sourceStream))), }; m_options.maxRounds = 10; diff --git a/test/yulPhaser/Chromosome.cpp b/test/yulPhaser/Chromosome.cpp index 1d12bf18c161..da109086a916 100644 --- a/test/yulPhaser/Chromosome.cpp +++ b/test/yulPhaser/Chromosome.cpp @@ -40,14 +40,13 @@ #include -using namespace std; using namespace solidity::yul; using namespace solidity::util; namespace solidity::phaser::test { -vector const ChrOmOsoMeSteps{ +std::vector const ChrOmOsoMeSteps{ ConditionalSimplifier::name, FunctionHoister::name, UnusedAssignEliminator::name, @@ -76,10 +75,10 @@ BOOST_AUTO_TEST_CASE(makeRandom_should_use_every_possible_step_with_the_same_pro constexpr int samplesPerStep = 500; constexpr double relativeTolerance = 0.02; - map stepIndices = enumerateOptmisationSteps(); + std::map stepIndices = enumerateOptmisationSteps(); auto chromosome = Chromosome::makeRandom(stepIndices.size() * samplesPerStep); - vector samples; + std::vector samples; for (auto& step: chromosome.optimisationSteps()) samples.push_back(stepIndices.at(step)); @@ -97,7 +96,7 @@ BOOST_AUTO_TEST_CASE(constructor_should_store_genes) BOOST_AUTO_TEST_CASE(constructor_should_store_optimisation_steps) { - vector steps = { + std::vector steps = { StructuralSimplifier::name, BlockFlattener::name, UnusedPruner::name, @@ -108,7 +107,7 @@ BOOST_AUTO_TEST_CASE(constructor_should_store_optimisation_steps) BOOST_AUTO_TEST_CASE(constructor_should_allow_duplicate_steps) { - vector steps = { + std::vector steps = { StructuralSimplifier::name, StructuralSimplifier::name, BlockFlattener::name, @@ -131,7 +130,7 @@ BOOST_AUTO_TEST_CASE(constructor_should_allow_genes_that_do_not_correspond_to_an BOOST_AUTO_TEST_CASE(output_operator_should_create_concise_and_unambiguous_string_representation) { - vector allSteps; + std::vector allSteps; for (auto const& step: OptimiserSuite::allSteps()) allSteps.push_back(step.first); Chromosome chromosome(allSteps); @@ -152,8 +151,8 @@ BOOST_AUTO_TEST_CASE(randomOptimisationStep_should_return_each_step_with_same_pr constexpr int samplesPerStep = 500; constexpr double relativeTolerance = 0.02; - map stepIndices = enumerateOptmisationSteps(); - vector samples; + std::map stepIndices = enumerateOptmisationSteps(); + std::vector samples; for (size_t i = 0; i <= stepIndices.size() * samplesPerStep; ++i) samples.push_back(stepIndices.at(Chromosome::randomOptimisationStep())); @@ -172,7 +171,7 @@ BOOST_AUTO_TEST_CASE(stepsToGenes_should_translate_optimisation_step_names_to_ab BOOST_AUTO_TEST_CASE(genesToSteps_should_translate_optimisation_step_abbreviations_to_names) { - BOOST_TEST(Chromosome::genesToSteps("") == vector{}); + BOOST_TEST(Chromosome::genesToSteps("") == std::vector{}); BOOST_TEST(Chromosome::genesToSteps("ChrOmOsoMe") == ChrOmOsoMeSteps); } diff --git a/test/yulPhaser/Common.cpp b/test/yulPhaser/Common.cpp index 734738483547..c4842045fa3f 100644 --- a/test/yulPhaser/Common.cpp +++ b/test/yulPhaser/Common.cpp @@ -30,7 +30,6 @@ #include #include -using namespace std; using namespace boost::test_tools; using namespace solidity::util; @@ -56,7 +55,7 @@ enum class TestEnum GH, }; -map const TestEnumToStringMap = +std::map const TestEnumToStringMap = { {TestEnum::A, "a"}, {TestEnum::B, "b"}, @@ -64,7 +63,7 @@ map const TestEnumToStringMap = {TestEnum::CD, "c-d"}, {TestEnum::EF, "e f"}, }; -map const StringToTestEnumMap = invertMap(TestEnumToStringMap); +std::map const StringToTestEnumMap = invertMap(TestEnumToStringMap); } @@ -74,29 +73,29 @@ BOOST_AUTO_TEST_SUITE(CommonTest) BOOST_FIXTURE_TEST_CASE(readLinesFromFile_should_return_all_lines_from_a_text_file_as_strings_without_newlines, ReadLinesFromFileFixture) { { - ofstream tmpFile((m_tempDir.path() / "test-file.txt").string()); - tmpFile << endl << "Line 1" << endl << endl << endl << "Line 2" << endl << "#" << endl << endl; + std::ofstream tmpFile((m_tempDir.path() / "test-file.txt").string()); + tmpFile << std::endl << "Line 1" << std::endl << std::endl << std::endl << "Line 2" << std::endl << "#" << std::endl << std::endl; } - vector lines = readLinesFromFile((m_tempDir.path() / "test-file.txt").string()); - BOOST_TEST((lines == vector{"", "Line 1", "", "", "Line 2", "#", ""})); + std::vector lines = readLinesFromFile((m_tempDir.path() / "test-file.txt").string()); + BOOST_TEST((lines == std::vector{"", "Line 1", "", "", "Line 2", "#", ""})); } BOOST_AUTO_TEST_CASE(deserializeChoice_should_convert_string_to_enum) { - istringstream aStream("a"); + std::istringstream aStream("a"); TestEnum aResult; deserializeChoice(aStream, aResult, StringToTestEnumMap); BOOST_CHECK(aResult == TestEnum::A); BOOST_TEST(!aStream.fail()); - istringstream bStream("b"); + std::istringstream bStream("b"); TestEnum bResult; deserializeChoice(bStream, bResult, StringToTestEnumMap); BOOST_CHECK(bResult == TestEnum::B); BOOST_TEST(!bStream.fail()); - istringstream cdStream("c-d"); + std::istringstream cdStream("c-d"); TestEnum cdResult; deserializeChoice(cdStream, cdResult, StringToTestEnumMap); BOOST_CHECK(cdResult == TestEnum::CD); @@ -105,7 +104,7 @@ BOOST_AUTO_TEST_CASE(deserializeChoice_should_convert_string_to_enum) BOOST_AUTO_TEST_CASE(deserializeChoice_should_set_failbit_if_there_is_no_enum_corresponding_to_string) { - istringstream xyzStream("xyz"); + std::istringstream xyzStream("xyz"); TestEnum xyzResult; deserializeChoice(xyzStream, xyzResult, StringToTestEnumMap); BOOST_TEST(xyzStream.fail()); @@ -113,13 +112,13 @@ BOOST_AUTO_TEST_CASE(deserializeChoice_should_set_failbit_if_there_is_no_enum_co BOOST_AUTO_TEST_CASE(deserializeChoice_does_not_have_to_support_strings_with_spaces) { - istringstream abStream("a b"); + std::istringstream abStream("a b"); TestEnum abResult; deserializeChoice(abStream, abResult, StringToTestEnumMap); BOOST_CHECK(abResult == TestEnum::A); BOOST_TEST(!abStream.fail()); - istringstream efStream("e f"); + std::istringstream efStream("e f"); TestEnum efResult; deserializeChoice(efStream, efResult, StringToTestEnumMap); BOOST_TEST(efStream.fail()); diff --git a/test/yulPhaser/FitnessMetrics.cpp b/test/yulPhaser/FitnessMetrics.cpp index bde15a537fd8..7fab2e18935e 100644 --- a/test/yulPhaser/FitnessMetrics.cpp +++ b/test/yulPhaser/FitnessMetrics.cpp @@ -29,7 +29,6 @@ #include -using namespace std; using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; @@ -74,22 +73,22 @@ class ProgramBasedMetricFixture } CharStream m_sourceStream = CharStream(SampleSourceCode, ""); - Chromosome m_chromosome{vector{UnusedPruner::name, EquivalentFunctionCombiner::name}}; - Program m_program = get(Program::load(m_sourceStream)); + Chromosome m_chromosome{std::vector{UnusedPruner::name, EquivalentFunctionCombiner::name}}; + Program m_program = std::get(Program::load(m_sourceStream)); Program m_optimisedProgram = optimisedProgram(m_program); - shared_ptr m_programCache = make_shared(m_program); + std::shared_ptr m_programCache = std::make_shared(m_program); static constexpr CodeWeights m_weights{}; }; class FitnessMetricCombinationFixture: public ProgramBasedMetricFixture { protected: - vector> m_simpleMetrics = { - make_shared(m_program, nullptr, m_weights, 1), - make_shared(m_program, nullptr, m_weights, 2), - make_shared(m_program, nullptr, m_weights, 3), + std::vector> m_simpleMetrics = { + std::make_shared(m_program, nullptr, m_weights, 1), + std::make_shared(m_program, nullptr, m_weights, 2), + std::make_shared(m_program, nullptr, m_weights, 3), }; - vector m_fitness = { + std::vector m_fitness = { m_simpleMetrics[0]->evaluate(m_chromosome), m_simpleMetrics[1]->evaluate(m_chromosome), m_simpleMetrics[2]->evaluate(m_chromosome), @@ -102,7 +101,7 @@ BOOST_AUTO_TEST_SUITE(ProgramBasedMetricTest) BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_return_optimised_program_even_if_cache_not_available, ProgramBasedMetricFixture) { - string code = toString(DummyProgramBasedMetric(m_program, nullptr, m_weights).optimisedProgram(m_chromosome)); + std::string code = toString(DummyProgramBasedMetric(m_program, nullptr, m_weights).optimisedProgram(m_chromosome)); BOOST_TEST(code != toString(m_program)); BOOST_TEST(code == toString(m_optimisedProgram)); @@ -110,7 +109,7 @@ BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_return_optimised_program_even_if BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_use_cache_if_available, ProgramBasedMetricFixture) { - string code = toString(DummyProgramBasedMetric(nullopt, m_programCache, m_weights).optimisedProgram(m_chromosome)); + std::string code = toString(DummyProgramBasedMetric(std::nullopt, m_programCache, m_weights).optimisedProgram(m_chromosome)); BOOST_TEST(code != toString(m_program)); BOOST_TEST(code == toString(m_optimisedProgram)); @@ -119,7 +118,7 @@ BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_use_cache_if_available, ProgramB BOOST_FIXTURE_TEST_CASE(optimisedProgramNoCache_should_return_optimised_program_even_if_cache_not_available, ProgramBasedMetricFixture) { - string code = toString(DummyProgramBasedMetric(m_program, nullptr, m_weights).optimisedProgramNoCache(m_chromosome)); + std::string code = toString(DummyProgramBasedMetric(m_program, nullptr, m_weights).optimisedProgramNoCache(m_chromosome)); BOOST_TEST(code != toString(m_program)); BOOST_TEST(code == toString(m_optimisedProgram)); @@ -127,7 +126,7 @@ BOOST_FIXTURE_TEST_CASE(optimisedProgramNoCache_should_return_optimised_program_ BOOST_FIXTURE_TEST_CASE(optimisedProgramNoCache_should_not_use_cache_even_if_available, ProgramBasedMetricFixture) { - string code = toString(DummyProgramBasedMetric(nullopt, m_programCache, m_weights).optimisedProgramNoCache(m_chromosome)); + std::string code = toString(DummyProgramBasedMetric(std::nullopt, m_programCache, m_weights).optimisedProgramNoCache(m_chromosome)); BOOST_TEST(code != toString(m_program)); BOOST_TEST(code == toString(m_optimisedProgram)); @@ -147,7 +146,7 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_size_of_the_optimised_program, P BOOST_FIXTURE_TEST_CASE(evaluate_should_be_able_to_use_program_cache_if_available, ProgramBasedMetricFixture) { - size_t fitness = ProgramSize(nullopt, m_programCache, m_weights).evaluate(m_chromosome); + size_t fitness = ProgramSize(std::nullopt, m_programCache, m_weights).evaluate(m_chromosome); BOOST_TEST(fitness != m_program.codeSize(m_weights)); BOOST_TEST(fitness == m_optimisedProgram.codeSize(m_weights)); @@ -190,7 +189,7 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_the_size_ratio_between_optimised BOOST_FIXTURE_TEST_CASE(evaluate_should_be_able_to_use_program_cache_if_available, ProgramBasedMetricFixture) { BOOST_TEST( - RelativeProgramSize(nullopt, m_programCache, 3, m_weights).evaluate(m_chromosome) == + RelativeProgramSize(std::nullopt, m_programCache, 3, m_weights).evaluate(m_chromosome) == round(1000.0 * double(m_optimisedProgram.codeSize(m_weights)) / double(m_program.codeSize(m_weights))) ); BOOST_TEST(m_programCache->size() == m_chromosome.length()); @@ -219,7 +218,7 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_number_of_repetitions_is_z BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_the_original_program_size_is_zero, ProgramBasedMetricFixture) { CharStream sourceStream = CharStream("{}", ""); - Program program = get(Program::load(sourceStream)); + Program program = std::get(Program::load(sourceStream)); RelativeProgramSize metric(program, nullptr, 3, m_weights); @@ -264,7 +263,7 @@ BOOST_FIXTURE_TEST_CASE(FitnessMetricMaximum_evaluate_should_compute_maximum_of_ FitnessMetricMaximum metric(m_simpleMetrics); assert(m_simpleMetrics.size() == 3); - BOOST_TEST(metric.evaluate(m_chromosome) == max(m_fitness[0], max(m_fitness[1], m_fitness[2]))); + BOOST_TEST(metric.evaluate(m_chromosome) == std::max(m_fitness[0], std::max(m_fitness[1], m_fitness[2]))); BOOST_TEST(metric.metrics() == m_simpleMetrics); } @@ -273,7 +272,7 @@ BOOST_FIXTURE_TEST_CASE(FitnessMetricMinimum_evaluate_should_compute_minimum_of_ FitnessMetricMinimum metric(m_simpleMetrics); assert(m_simpleMetrics.size() == 3); - BOOST_TEST(metric.evaluate(m_chromosome) == min(m_fitness[0], min(m_fitness[1], m_fitness[2]))); + BOOST_TEST(metric.evaluate(m_chromosome) == std::min(m_fitness[0], std::min(m_fitness[1], m_fitness[2]))); BOOST_TEST(metric.metrics() == m_simpleMetrics); } diff --git a/test/yulPhaser/GeneticAlgorithms.cpp b/test/yulPhaser/GeneticAlgorithms.cpp index 29c9cfa2ecaf..c3b661334499 100644 --- a/test/yulPhaser/GeneticAlgorithms.cpp +++ b/test/yulPhaser/GeneticAlgorithms.cpp @@ -29,7 +29,6 @@ #include #include -using namespace std; using namespace boost::unit_test::framework; using namespace boost::test_tools; using namespace solidity::util; @@ -40,7 +39,7 @@ namespace solidity::phaser::test class GeneticAlgorithmFixture { protected: - shared_ptr m_fitnessMetric = make_shared(); + std::shared_ptr m_fitnessMetric = std::make_shared(); }; class ClassicGeneticAlgorithmFixture: public GeneticAlgorithmFixture @@ -64,41 +63,41 @@ BOOST_AUTO_TEST_SUITE(RandomAlgorithmTest) BOOST_FIXTURE_TEST_CASE(runNextRound_should_preserve_elite_and_randomise_rest_of_population, GeneticAlgorithmFixture) { auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5); - assert((chromosomeLengths(population) == vector{3, 3, 3, 3, 5, 5, 5, 5})); + assert((chromosomeLengths(population) == std::vector{3, 3, 3, 3, 5, 5, 5, 5})); RandomAlgorithm algorithm({0.5, 1, 1}); Population newPopulation = algorithm.runNextRound(population); - BOOST_TEST((chromosomeLengths(newPopulation) == vector{1, 1, 1, 1, 3, 3, 3, 3})); + BOOST_TEST((chromosomeLengths(newPopulation) == std::vector{1, 1, 1, 1, 3, 3, 3, 3})); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_not_replace_elite_with_worse_individuals, GeneticAlgorithmFixture) { auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5); - assert((chromosomeLengths(population) == vector{3, 3, 3, 3, 5, 5, 5, 5})); + assert((chromosomeLengths(population) == std::vector{3, 3, 3, 3, 5, 5, 5, 5})); RandomAlgorithm algorithm({0.5, 7, 7}); Population newPopulation = algorithm.runNextRound(population); - BOOST_TEST((chromosomeLengths(newPopulation) == vector{3, 3, 3, 3, 7, 7, 7, 7})); + BOOST_TEST((chromosomeLengths(newPopulation) == std::vector{3, 3, 3, 3, 7, 7, 7, 7})); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_replace_all_chromosomes_if_zero_size_elite, GeneticAlgorithmFixture) { auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5); - assert((chromosomeLengths(population) == vector{3, 3, 3, 3, 5, 5, 5, 5})); + assert((chromosomeLengths(population) == std::vector{3, 3, 3, 3, 5, 5, 5, 5})); RandomAlgorithm algorithm({0.0, 1, 1}); Population newPopulation = algorithm.runNextRound(population); - BOOST_TEST((chromosomeLengths(newPopulation) == vector{1, 1, 1, 1, 1, 1, 1, 1})); + BOOST_TEST((chromosomeLengths(newPopulation) == std::vector{1, 1, 1, 1, 1, 1, 1, 1})); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_not_replace_any_chromosomes_if_whole_population_is_the_elite, GeneticAlgorithmFixture) { auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5); - assert((chromosomeLengths(population) == vector{3, 3, 3, 3, 5, 5, 5, 5})); + assert((chromosomeLengths(population) == std::vector{3, 3, 3, 3, 5, 5, 5, 5})); RandomAlgorithm algorithm({1.0, 1, 1}); Population newPopulation = algorithm.runNextRound(population); - BOOST_TEST((chromosomeLengths(newPopulation) == vector{3, 3, 3, 3, 5, 5, 5, 5})); + BOOST_TEST((chromosomeLengths(newPopulation) == std::vector{3, 3, 3, 3, 5, 5, 5, 5})); } BOOST_AUTO_TEST_SUITE_END() @@ -107,7 +106,7 @@ BOOST_AUTO_TEST_SUITE(GenerationalElitistWithExclusivePoolsTest) BOOST_FIXTURE_TEST_CASE(runNextRound_should_preserve_elite_and_regenerate_rest_of_population, GeneticAlgorithmFixture) { auto population = Population::makeRandom(m_fitnessMetric, 6, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5); - assert((chromosomeLengths(population) == vector{3, 3, 3, 3, 3, 3, 5, 5, 5, 5})); + assert((chromosomeLengths(population) == std::vector{3, 3, 3, 3, 3, 3, 5, 5, 5, 5})); GenerationalElitistWithExclusivePools::Options options = { /* mutationPoolSize = */ 0.2, @@ -123,13 +122,13 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_preserve_elite_and_regenerate_rest_o Population newPopulation = algorithm.runNextRound(population); - BOOST_TEST((chromosomeLengths(newPopulation) == vector{0, 0, 3, 3, 3, 3, 3, 3, 3, 3})); + BOOST_TEST((chromosomeLengths(newPopulation) == std::vector{0, 0, 3, 3, 3, 3, 3, 3, 3, 3})); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_not_replace_elite_with_worse_individuals, GeneticAlgorithmFixture) { auto population = Population::makeRandom(m_fitnessMetric, 6, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5); - assert(chromosomeLengths(population) == (vector{3, 3, 3, 3, 3, 3, 5, 5, 5, 5})); + assert(chromosomeLengths(population) == (std::vector{3, 3, 3, 3, 3, 3, 5, 5, 5, 5})); GenerationalElitistWithExclusivePools::Options options = { /* mutationPoolSize = */ 0.2, @@ -145,7 +144,7 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_not_replace_elite_with_worse_individ Population newPopulation = algorithm.runNextRound(population); - BOOST_TEST((chromosomeLengths(newPopulation) == vector{3, 3, 3, 3, 3, 3, 3, 3, 7, 7})); + BOOST_TEST((chromosomeLengths(newPopulation) == std::vector{3, 3, 3, 3, 3, 3, 3, 3, 7, 7})); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_generate_individuals_in_the_crossover_pool_by_mutating_the_elite, GeneticAlgorithmFixture) @@ -169,7 +168,7 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_generate_individuals_in_the_crossove BOOST_TEST(( chromosomeLengths(newPopulation) == - vector{0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 11, 11} + std::vector{0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 11, 11} )); } @@ -179,7 +178,7 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_generate_individuals_in_the_crossove Population(m_fitnessMetric, {Chromosome("aa"), Chromosome("ff")}) + Population::makeRandom(m_fitnessMetric, 8, 6, 6) ); - assert((chromosomeLengths(population) == vector{2, 2, 6, 6, 6, 6, 6, 6, 6, 6})); + assert((chromosomeLengths(population) == std::vector{2, 2, 6, 6, 6, 6, 6, 6, 6, 6})); GenerationalElitistWithExclusivePools::Options options = { /* mutationPoolSize = */ 0.0, @@ -196,8 +195,8 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_generate_individuals_in_the_crossove SimulationRNG::reset(1); Population newPopulation = algorithm.runNextRound(population); - vector const& newIndividuals = newPopulation.individuals(); - BOOST_TEST((chromosomeLengths(newPopulation) == vector{2, 2, 2, 2, 2, 2, 2, 2, 2, 2})); + std::vector const& newIndividuals = newPopulation.individuals(); + BOOST_TEST((chromosomeLengths(newPopulation) == std::vector{2, 2, 2, 2, 2, 2, 2, 2, 2, 2})); for (auto& individual: newIndividuals) BOOST_TEST(( individual.chromosome == Chromosome("aa") || @@ -228,7 +227,7 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_individuals_with_probability_ Population::makeRandom(m_fitnessMetric, populationSize / 4, 2, 2) + Population::makeRandom(m_fitnessMetric, populationSize / 4, 3, 3); - map expectedProbabilities = { + std::map expectedProbabilities = { {0, 4.0 / (4 + 3 + 2 + 1)}, {1, 3.0 / (4 + 3 + 2 + 1)}, {2, 2.0 / (4 + 3 + 2 + 1)}, @@ -252,9 +251,9 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_individuals_with_probability_ BOOST_TEST(newPopulation.individuals().size() == population.individuals().size()); - vector newFitness = chromosomeLengths(newPopulation); - BOOST_TEST(abs(mean(newFitness) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(newFitness, expectedValue) - variance) < variance * relativeTolerance); + std::vector newFitness = chromosomeLengths(newPopulation); + BOOST_TEST(std::abs(mean(newFitness) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(newFitness, expectedValue) - variance) < variance * relativeTolerance); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_only_individuals_existing_in_the_original_population, ClassicGeneticAlgorithmFixture) @@ -262,7 +261,7 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_only_individuals_existing_in_ constexpr size_t populationSize = 1000; auto population = Population::makeRandom(m_fitnessMetric, populationSize, 1, 10); - set originalSteps; + std::set originalSteps; for (auto const& individual: population.individuals()) originalSteps.insert(toString(individual.chromosome)); @@ -281,8 +280,8 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_crossover, ClassicGeneticAlgorith Chromosome("gg"), Chromosome("gg"), Chromosome("gg"), }); - set originalSteps{"aa", "ff", "gg"}; - set crossedSteps{"af", "fa", "fg", "gf", "ga", "ag"}; + std::set originalSteps{"aa", "ff", "gg"}; + std::set crossedSteps{"af", "fa", "fg", "gf", "ga", "ag"}; m_options.crossoverChance = 0.8; ClassicGeneticAlgorithm algorithm(m_options); @@ -312,22 +311,22 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_mutation, ClassicGeneticAlgorithm double const variance = m_options.mutationChance * (1 - m_options.mutationChance); Chromosome chromosome("aaaaaaaaaa"); - vector chromosomes(populationSize, chromosome); + std::vector chromosomes(populationSize, chromosome); Population population(m_fitnessMetric, chromosomes); SimulationRNG::reset(1); Population newPopulation = algorithm.runNextRound(population); - vector bernoulliTrials; + std::vector bernoulliTrials; for (auto const& individual: newPopulation.individuals()) { - string steps = toString(individual.chromosome); + std::string steps = toString(individual.chromosome); for (char step: steps) bernoulliTrials.push_back(static_cast(step != 'a')); } - BOOST_TEST(abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_deletion, ClassicGeneticAlgorithmFixture) @@ -341,22 +340,22 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_deletion, ClassicGeneticAlgorithm double const variance = m_options.deletionChance * (1 - m_options.deletionChance); Chromosome chromosome("aaaaaaaaaa"); - vector chromosomes(populationSize, chromosome); + std::vector chromosomes(populationSize, chromosome); Population population(m_fitnessMetric, chromosomes); SimulationRNG::reset(1); Population newPopulation = algorithm.runNextRound(population); - vector bernoulliTrials; + std::vector bernoulliTrials; for (auto const& individual: newPopulation.individuals()) { - string steps = toString(individual.chromosome); + std::string steps = toString(individual.chromosome); for (size_t i = 0; i < chromosome.length(); ++i) bernoulliTrials.push_back(static_cast(i >= steps.size())); } - BOOST_TEST(abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_addition, ClassicGeneticAlgorithmFixture) @@ -370,16 +369,16 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_addition, ClassicGeneticAlgorithm double const variance = m_options.additionChance * (1 - m_options.additionChance); Chromosome chromosome("aaaaaaaaaa"); - vector chromosomes(populationSize, chromosome); + std::vector chromosomes(populationSize, chromosome); Population population(m_fitnessMetric, chromosomes); SimulationRNG::reset(1); Population newPopulation = algorithm.runNextRound(population); - vector bernoulliTrials; + std::vector bernoulliTrials; for (auto const& individual: newPopulation.individuals()) { - string steps = toString(individual.chromosome); + std::string steps = toString(individual.chromosome); for (size_t i = 0; i < chromosome.length() + 1; ++i) { BOOST_REQUIRE(chromosome.length() <= steps.size() && steps.size() <= 2 * chromosome.length() + 1); @@ -387,21 +386,21 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_addition, ClassicGeneticAlgorithm } } - BOOST_TEST(abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } BOOST_FIXTURE_TEST_CASE(runNextRound_should_preserve_elite, ClassicGeneticAlgorithmFixture) { auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 6, 5, 5); - assert((chromosomeLengths(population) == vector{3, 3, 3, 3, 5, 5, 5, 5, 5, 5})); + assert((chromosomeLengths(population) == std::vector{3, 3, 3, 3, 5, 5, 5, 5, 5, 5})); m_options.elitePoolSize = 0.5; m_options.deletionChance = 1.0; ClassicGeneticAlgorithm algorithm(m_options); Population newPopulation = algorithm.runNextRound(population); - BOOST_TEST((chromosomeLengths(newPopulation) == vector{0, 0, 0, 0, 0, 3, 3, 3, 3, 5})); + BOOST_TEST((chromosomeLengths(newPopulation) == std::vector{0, 0, 0, 0, 0, 3, 3, 3, 3, 5})); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/yulPhaser/Mutations.cpp b/test/yulPhaser/Mutations.cpp index 8e1d0238b3ef..a5a715e23a2a 100644 --- a/test/yulPhaser/Mutations.cpp +++ b/test/yulPhaser/Mutations.cpp @@ -30,7 +30,6 @@ #include #include -using namespace std; using namespace solidity::util; using namespace solidity::yul; @@ -48,7 +47,7 @@ BOOST_AUTO_TEST_CASE(geneRandomisation_should_iterate_over_genes_and_replace_the // Use genes that do not represent valid step abbreviations to be able to easily spot added steps. assert(OptimiserSuite::stepAbbreviationToNameMap().count('.') == 0); - Chromosome input = Chromosome(string(inputLength, '.')); + Chromosome input = Chromosome(std::string(inputLength, '.')); SimulationRNG::reset(1); for (size_t randomisationChancePercent = 20; randomisationChancePercent <= 100; randomisationChancePercent += 20) @@ -56,7 +55,7 @@ BOOST_AUTO_TEST_CASE(geneRandomisation_should_iterate_over_genes_and_replace_the double const randomisationChance = double(randomisationChancePercent) / 100.0; Chromosome output = geneRandomisation(randomisationChance)(input); - string outputGenes = output.genes(); + std::string outputGenes = output.genes(); BOOST_REQUIRE(output.length() == input.length()); double const expectedValue = randomisationChance; @@ -66,15 +65,15 @@ BOOST_AUTO_TEST_CASE(geneRandomisation_should_iterate_over_genes_and_replace_the (inputLength - randomisedGeneCount) * expectedValue * expectedValue + randomisedGeneCount * (1 - expectedValue) * (1 - expectedValue); - BOOST_TEST(abs(randomisedGeneCount / inputLength - expectedValue) < tolerance); - BOOST_TEST(abs(squaredError / inputLength - variance) < tolerance); + BOOST_TEST(std::abs(randomisedGeneCount / inputLength - expectedValue) < tolerance); + BOOST_TEST(std::abs(squaredError / inputLength - variance) < tolerance); } } BOOST_AUTO_TEST_CASE(geneRandomisation_should_return_identical_chromosome_if_probability_is_zero) { Chromosome chromosome("fcCUnDvejsrmV"); - function mutation = geneRandomisation(0.0); + std::function mutation = geneRandomisation(0.0); BOOST_TEST(mutation(chromosome) == chromosome); } @@ -86,7 +85,7 @@ BOOST_AUTO_TEST_CASE(geneDeletion_should_iterate_over_genes_and_delete_them_with // Use genes that do not represent valid step abbreviations to be able to easily spot added steps. assert(OptimiserSuite::stepAbbreviationToNameMap().count('.') == 0); - Chromosome input = Chromosome(string(inputLength, '.')); + Chromosome input = Chromosome(std::string(inputLength, '.')); SimulationRNG::reset(1); for (size_t deletionChancePercent = 20; deletionChancePercent < 100; deletionChancePercent += 20) @@ -94,7 +93,7 @@ BOOST_AUTO_TEST_CASE(geneDeletion_should_iterate_over_genes_and_delete_them_with double const deletionChance = double(deletionChancePercent) / 100.0; Chromosome output = geneDeletion(deletionChance)(input); - string outputGenes = output.genes(); + std::string outputGenes = output.genes(); BOOST_REQUIRE(output.length() <= input.length()); BOOST_REQUIRE(static_cast(count(outputGenes.begin(), outputGenes.end(), '.')) == output.length()); @@ -105,15 +104,15 @@ BOOST_AUTO_TEST_CASE(geneDeletion_should_iterate_over_genes_and_delete_them_with (double(inputLength) - deletedGeneCount) * expectedValue * expectedValue + deletedGeneCount * (1.0 - expectedValue) * (1.0 - expectedValue); - BOOST_TEST(abs(deletedGeneCount / double(inputLength) - expectedValue) < tolerance); - BOOST_TEST(abs(squaredError / double(inputLength) - variance) < tolerance); + BOOST_TEST(std::abs(deletedGeneCount / double(inputLength) - expectedValue) < tolerance); + BOOST_TEST(std::abs(squaredError / double(inputLength) - variance) < tolerance); } } BOOST_AUTO_TEST_CASE(geneDeletion_should_return_identical_chromosome_if_probability_is_zero) { Chromosome chromosome("fcCUnDvejsrmV"); - function mutation = geneDeletion(0.0); + std::function mutation = geneDeletion(0.0); BOOST_TEST(mutation(chromosome) == chromosome); } @@ -121,7 +120,7 @@ BOOST_AUTO_TEST_CASE(geneDeletion_should_return_identical_chromosome_if_probabil BOOST_AUTO_TEST_CASE(geneDeletion_should_delete_all_genes_if_probability_is_one) { Chromosome chromosome("fcCUnDvejsrmV"); - function mutation = geneDeletion(1.0); + std::function mutation = geneDeletion(1.0); BOOST_TEST(mutation(chromosome) == Chromosome("")); } @@ -134,7 +133,7 @@ BOOST_AUTO_TEST_CASE(geneAddition_should_iterate_over_gene_positions_and_insert_ // Use genes that do not represent valid step abbreviations to be able to easily spot added steps. assert(OptimiserSuite::stepAbbreviationToNameMap().count('.') == 0); - Chromosome input = Chromosome(string(inputLength, '.')); + Chromosome input = Chromosome(std::string(inputLength, '.')); SimulationRNG::reset(1); for (size_t additionChancePercent = 20; additionChancePercent < 100; additionChancePercent += 20) @@ -145,8 +144,8 @@ BOOST_AUTO_TEST_CASE(geneAddition_should_iterate_over_gene_positions_and_insert_ BOOST_REQUIRE(output.length() >= input.length()); BOOST_REQUIRE(output.length() <= inputLength + maxAdditions); - string_view outputGenes = output.genes(); - size_t preservedGeneCount = static_cast(count(outputGenes.begin(), outputGenes.end(), '.')); + std::string_view outputGenes = output.genes(); + size_t preservedGeneCount = static_cast(std::count(outputGenes.begin(), outputGenes.end(), '.')); BOOST_REQUIRE(preservedGeneCount == input.length()); double const expectedValue = additionChance; @@ -156,8 +155,8 @@ BOOST_AUTO_TEST_CASE(geneAddition_should_iterate_over_gene_positions_and_insert_ (double(maxAdditions) - addedGeneCount) * expectedValue * expectedValue + addedGeneCount * (1.0 - expectedValue) * (1.0 - expectedValue); - BOOST_TEST(abs(addedGeneCount / double(maxAdditions) - expectedValue) < tolerance); - BOOST_TEST(abs(squaredError / double(maxAdditions) - variance) < tolerance); + BOOST_TEST(std::abs(addedGeneCount / double(maxAdditions) - expectedValue) < tolerance); + BOOST_TEST(std::abs(squaredError / double(maxAdditions) - variance) < tolerance); } } @@ -165,7 +164,7 @@ BOOST_AUTO_TEST_CASE(geneAddition_should_be_able_to_insert_before_first_position { SimulationRNG::reset(7); Chromosome chromosome("fcCUnDvejs"); - function mutation = geneAddition(0.1); + std::function mutation = geneAddition(0.1); Chromosome mutatedChromosome = mutation(chromosome); BOOST_TEST(mutatedChromosome.length() > chromosome.length()); @@ -176,7 +175,7 @@ BOOST_AUTO_TEST_CASE(geneAddition_should_be_able_to_insert_after_last_position) { SimulationRNG::reset(81); Chromosome chromosome("fcCUnDvejs"); - function mutation = geneAddition(0.1); + std::function mutation = geneAddition(0.1); Chromosome mutatedChromosome = mutation(chromosome); BOOST_TEST(mutatedChromosome.length() > chromosome.length()); @@ -186,7 +185,7 @@ BOOST_AUTO_TEST_CASE(geneAddition_should_be_able_to_insert_after_last_position) BOOST_AUTO_TEST_CASE(geneAddition_should_return_identical_chromosome_if_probability_is_zero) { Chromosome chromosome("fcCUnDvejsrmV"); - function mutation = geneAddition(0.0); + std::function mutation = geneAddition(0.0); BOOST_TEST(mutation(chromosome) == chromosome); } @@ -194,12 +193,12 @@ BOOST_AUTO_TEST_CASE(geneAddition_should_return_identical_chromosome_if_probabil BOOST_AUTO_TEST_CASE(geneAddition_should_insert_genes_at_all_positions_if_probability_is_one) { Chromosome chromosome("fcCUnDvejsrmV"); - function mutation = geneAddition(1.0); + std::function mutation = geneAddition(1.0); Chromosome mutatedChromosome = mutation(chromosome); BOOST_TEST(mutatedChromosome.length() == chromosome.length() * 2 + 1); - vector originalGenes; + std::vector originalGenes; for (size_t i = 0; i < mutatedChromosome.length() - 1; ++i) if (i % 2 == 1) originalGenes.push_back(mutatedChromosome.optimisationSteps()[i]); @@ -211,7 +210,7 @@ BOOST_AUTO_TEST_CASE(alternativeMutations_should_choose_between_mutations_with_g { SimulationRNG::reset(1); Chromosome chromosome("a"); - function mutation = alternativeMutations( + std::function mutation = alternativeMutations( 0.8, wholeChromosomeReplacement(Chromosome("c")), wholeChromosomeReplacement(Chromosome("f")) @@ -234,7 +233,7 @@ BOOST_AUTO_TEST_CASE(alternativeMutations_should_choose_between_mutations_with_g BOOST_AUTO_TEST_CASE(alternativeMutations_should_always_choose_first_mutation_if_probability_is_one) { Chromosome chromosome("a"); - function mutation = alternativeMutations( + std::function mutation = alternativeMutations( 1.0, wholeChromosomeReplacement(Chromosome("c")), wholeChromosomeReplacement(Chromosome("f")) @@ -247,7 +246,7 @@ BOOST_AUTO_TEST_CASE(alternativeMutations_should_always_choose_first_mutation_if BOOST_AUTO_TEST_CASE(alternativeMutations_should_always_choose_second_mutation_if_probability_is_zero) { Chromosome chromosome("a"); - function mutation = alternativeMutations( + std::function mutation = alternativeMutations( 0.0, wholeChromosomeReplacement(Chromosome("c")), wholeChromosomeReplacement(Chromosome("f")) @@ -260,8 +259,8 @@ BOOST_AUTO_TEST_CASE(alternativeMutations_should_always_choose_second_mutation_i BOOST_AUTO_TEST_CASE(mutationSequence_should_apply_all_mutations) { Chromosome chromosome("aaaaa"); - vector steps = Chromosome::genesToSteps("gfc"); - function mutation = mutationSequence({ + std::vector steps = Chromosome::genesToSteps("gfc"); + std::function mutation = mutationSequence({ geneSubstitution(3, steps[0]), geneSubstitution(2, steps[1]), geneSubstitution(1, steps[2]), @@ -273,8 +272,8 @@ BOOST_AUTO_TEST_CASE(mutationSequence_should_apply_all_mutations) BOOST_AUTO_TEST_CASE(mutationSequence_apply_mutations_in_the_order_they_are_given) { Chromosome chromosome("aa"); - vector steps = Chromosome::genesToSteps("gcfo"); - function mutation = mutationSequence({ + std::vector steps = Chromosome::genesToSteps("gcfo"); + std::function mutation = mutationSequence({ geneSubstitution(0, steps[0]), geneSubstitution(1, steps[1]), geneSubstitution(0, steps[2]), @@ -287,14 +286,14 @@ BOOST_AUTO_TEST_CASE(mutationSequence_apply_mutations_in_the_order_they_are_give BOOST_AUTO_TEST_CASE(mutationSequence_should_return_unmodified_chromosome_if_given_no_mutations) { Chromosome chromosome("aa"); - function mutation = mutationSequence({}); + std::function mutation = mutationSequence({}); BOOST_TEST(mutation(chromosome) == chromosome); } BOOST_AUTO_TEST_CASE(randomPointCrossover_should_swap_chromosome_parts_at_random_point) { - function crossover = randomPointCrossover(); + std::function crossover = randomPointCrossover(); SimulationRNG::reset(1); Chromosome result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); @@ -307,22 +306,22 @@ BOOST_AUTO_TEST_CASE(randomPointCrossover_should_swap_chromosome_parts_at_random BOOST_AUTO_TEST_CASE(symmetricRandomPointCrossover_should_swap_chromosome_parts_at_random_point) { - function crossover = symmetricRandomPointCrossover(); + std::function crossover = symmetricRandomPointCrossover(); SimulationRNG::reset(1); - tuple result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); - tuple expectedPair1 = {Chromosome("aaaccc"), Chromosome("cccaaaaaaa")}; + std::tuple result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); + std::tuple expectedPair1 = {Chromosome("aaaccc"), Chromosome("cccaaaaaaa")}; BOOST_TEST(result1 == expectedPair1); - tuple result2 = crossover(Chromosome("cccccc"), Chromosome("aaaaaaaaaa")); - tuple expectedPair2 = {Chromosome("ccccccaaaa"), Chromosome("aaaaaa")}; + std::tuple result2 = crossover(Chromosome("cccccc"), Chromosome("aaaaaaaaaa")); + std::tuple expectedPair2 = {Chromosome("ccccccaaaa"), Chromosome("aaaaaa")}; BOOST_TEST(result2 == expectedPair2); } BOOST_AUTO_TEST_CASE(randomPointCrossover_should_only_consider_points_available_on_both_chromosomes) { SimulationRNG::reset(1); - function crossover = randomPointCrossover(); + std::function crossover = randomPointCrossover(); for (size_t i = 0; i < 30; ++i) { @@ -346,7 +345,7 @@ BOOST_AUTO_TEST_CASE(randomPointCrossover_should_only_consider_points_available_ BOOST_AUTO_TEST_CASE(randomPointCrossover_should_never_split_at_position_zero_if_chromosomes_are_splittable) { SimulationRNG::reset(1); - function crossover = randomPointCrossover(); + std::function crossover = randomPointCrossover(); for (size_t i = 0; i < 30; ++i) { @@ -360,7 +359,7 @@ BOOST_AUTO_TEST_CASE(randomPointCrossover_should_never_split_at_position_zero_if BOOST_AUTO_TEST_CASE(randomPointCrossover_should_never_split_at_position_zero_if_chromosomes_are_not_empty) { SimulationRNG::reset(1); - function crossover = randomPointCrossover(); + std::function crossover = randomPointCrossover(); for (size_t i = 0; i < 30; ++i) { @@ -373,7 +372,7 @@ BOOST_AUTO_TEST_CASE(randomPointCrossover_should_never_split_at_position_zero_if BOOST_AUTO_TEST_CASE(randomPointCrossover_should_work_even_if_one_chromosome_is_unsplittable) { - function crossover = randomPointCrossover(); + std::function crossover = randomPointCrossover(); SimulationRNG::reset(1); BOOST_CHECK(crossover(Chromosome("ff"), Chromosome("a")) == Chromosome("f")); @@ -385,7 +384,7 @@ BOOST_AUTO_TEST_CASE(randomPointCrossover_should_split_at_position_zero_only_if_ Chromosome empty(""); Chromosome unsplittable("a"); Chromosome splittable("aaaa"); - function crossover = randomPointCrossover(); + std::function crossover = randomPointCrossover(); SimulationRNG::reset(1); BOOST_CHECK(crossover(empty, empty) == empty); @@ -447,13 +446,13 @@ BOOST_AUTO_TEST_CASE(fixedPointCrossover_should_split_at_end_of_shorter_chromoso BOOST_AUTO_TEST_CASE(fixedPointCrossover_should_select_correct_split_point_for_unsplittable_chromosomes) { - function crossover00 = fixedPointCrossover(0.0); + std::function crossover00 = fixedPointCrossover(0.0); BOOST_CHECK(crossover00(Chromosome("fff"), Chromosome("a")) == Chromosome("a")); BOOST_CHECK(crossover00(Chromosome("a"), Chromosome("fff")) == Chromosome("fff")); BOOST_CHECK(crossover00(Chromosome("f"), Chromosome("a")) == Chromosome("a")); - function crossover10 = fixedPointCrossover(1.0); + std::function crossover10 = fixedPointCrossover(1.0); BOOST_CHECK(crossover10(Chromosome("fff"), Chromosome("a")) == Chromosome("f")); BOOST_CHECK(crossover10(Chromosome("a"), Chromosome("fff")) == Chromosome("aff")); @@ -466,14 +465,14 @@ BOOST_AUTO_TEST_CASE(fixedPointCrossover_should_always_use_position_zero_as_spli Chromosome unsplittable("f"); Chromosome splittable("aaaa"); - function crossover00 = fixedPointCrossover(0.0); + std::function crossover00 = fixedPointCrossover(0.0); BOOST_CHECK(crossover00(empty, empty) == empty); BOOST_CHECK(crossover00(unsplittable, empty) == empty); BOOST_CHECK(crossover00(empty, unsplittable) == unsplittable); BOOST_CHECK(crossover00(splittable, empty) == empty); BOOST_CHECK(crossover00(empty, splittable) == splittable); - function crossover10 = fixedPointCrossover(1.0); + std::function crossover10 = fixedPointCrossover(1.0); BOOST_CHECK(crossover10(empty, empty) == empty); BOOST_CHECK(crossover10(unsplittable, empty) == empty); BOOST_CHECK(crossover10(empty, unsplittable) == unsplittable); @@ -483,7 +482,7 @@ BOOST_AUTO_TEST_CASE(fixedPointCrossover_should_always_use_position_zero_as_spli BOOST_AUTO_TEST_CASE(randomTwoPointCrossover_should_swap_chromosome_parts_between_two_random_points) { - function crossover = randomTwoPointCrossover(); + std::function crossover = randomTwoPointCrossover(); SimulationRNG::reset(1); Chromosome result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); @@ -496,21 +495,21 @@ BOOST_AUTO_TEST_CASE(randomTwoPointCrossover_should_swap_chromosome_parts_betwee BOOST_AUTO_TEST_CASE(symmetricRandomTwoPointCrossover_should_swap_chromosome_parts_at_random_point) { - function crossover = symmetricRandomTwoPointCrossover(); + std::function crossover = symmetricRandomTwoPointCrossover(); SimulationRNG::reset(1); - tuple result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); - tuple expectedPair1 = {Chromosome("aaacccaaaa"), Chromosome("cccaaa")}; + std::tuple result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); + std::tuple expectedPair1 = {Chromosome("aaacccaaaa"), Chromosome("cccaaa")}; BOOST_TEST(result1 == expectedPair1); - tuple result2 = crossover(Chromosome("cccccc"), Chromosome("aaaaaaaaaa")); - tuple expectedPair2 = {Chromosome("ccccca"), Chromosome("aaaaacaaaa")}; + std::tuple result2 = crossover(Chromosome("cccccc"), Chromosome("aaaaaaaaaa")); + std::tuple expectedPair2 = {Chromosome("ccccca"), Chromosome("aaaaacaaaa")}; BOOST_TEST(result2 == expectedPair2); } BOOST_AUTO_TEST_CASE(randomTwoPointCrossover_should_only_consider_points_available_on_both_chromosomes) { - function crossover = randomTwoPointCrossover(); + std::function crossover = randomTwoPointCrossover(); for (size_t i = 0; i < 30; ++i) { @@ -539,7 +538,7 @@ BOOST_AUTO_TEST_CASE(randomTwoPointCrossover_should_only_consider_points_availab BOOST_AUTO_TEST_CASE(uniformCrossover_should_swap_randomly_selected_genes) { - function crossover = uniformCrossover(0.7); + std::function crossover = uniformCrossover(0.7); SimulationRNG::reset(1); Chromosome result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); @@ -552,23 +551,23 @@ BOOST_AUTO_TEST_CASE(uniformCrossover_should_swap_randomly_selected_genes) BOOST_AUTO_TEST_CASE(symmetricUniformCrossover_should_swap_randomly_selected_genes) { - function crossover = symmetricUniformCrossover(0.7); + std::function crossover = symmetricUniformCrossover(0.7); SimulationRNG::reset(1); - tuple result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); - tuple expectedPair1 = {Chromosome("caaacc"), Chromosome("acccaaaaaa")}; + std::tuple result1 = crossover(Chromosome("aaaaaaaaaa"), Chromosome("cccccc")); + std::tuple expectedPair1 = {Chromosome("caaacc"), Chromosome("acccaaaaaa")}; BOOST_TEST(result1 == expectedPair1); - tuple result2 = crossover(Chromosome("cccccc"), Chromosome("aaaaaaaaaa")); - tuple expectedPair2 = {Chromosome("caaaaaaaaa"), Chromosome("accccc")}; + std::tuple result2 = crossover(Chromosome("cccccc"), Chromosome("aaaaaaaaaa")); + std::tuple expectedPair2 = {Chromosome("caaaaaaaaa"), Chromosome("accccc")}; BOOST_TEST(result2 == expectedPair2); } BOOST_AUTO_TEST_CASE(uniformCrossover_should_only_consider_points_available_on_both_chromosomes) { - function crossover = uniformCrossover(0.7); + std::function crossover = uniformCrossover(0.7); - set expectedPatterns = { + std::set expectedPatterns = { "TTTTTTTTTTTTTTTTTTTT", "aTTTTTTTTTTTTTTTTTTT", "TaTTTTTTTTTTTTTTTTTT", @@ -616,20 +615,20 @@ BOOST_AUTO_TEST_CASE(uniformCrossover_should_swap_genes_with_uniform_probability double const expectedValue = swapChance; double const variance = swapChance * (1 - swapChance); - function crossover = uniformCrossover(swapChance); + std::function crossover = uniformCrossover(swapChance); Chromosome chromosome1("aaaaaaaaaa"); Chromosome chromosome2("cccccccccc"); - vector bernoulliTrials; + std::vector bernoulliTrials; for (size_t i = 0; i < operationCount; ++i) { - string genes = toString(crossover(chromosome1, chromosome2)); + std::string genes = toString(crossover(chromosome1, chromosome2)); for (size_t j = 0; j < chromosome1.length(); ++j) bernoulliTrials.push_back(static_cast(genes[j] == 'c')); } - BOOST_TEST(abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(uniformCrossover_should_swap_tail_with_uniform_probability) @@ -640,22 +639,22 @@ BOOST_AUTO_TEST_CASE(uniformCrossover_should_swap_tail_with_uniform_probability) double const expectedValue = swapChance; double const variance = swapChance * (1 - swapChance); - function crossover = uniformCrossover(swapChance); + std::function crossover = uniformCrossover(swapChance); Chromosome chromosome1("aaaaa"); Chromosome chromosome2("cccccccccc"); SimulationRNG::reset(1); - vector bernoulliTrials; + std::vector bernoulliTrials; for (size_t i = 0; i < operationCount; ++i) { - string genes = toString(crossover(chromosome1, chromosome2)); + std::string genes = toString(crossover(chromosome1, chromosome2)); BOOST_REQUIRE(genes.size() == 5 || genes.size() == 10); bernoulliTrials.push_back(static_cast(genes.size() == 10)); } - BOOST_TEST(abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/yulPhaser/PairSelections.cpp b/test/yulPhaser/PairSelections.cpp index f3d13a5b3b27..82b9a900b68c 100644 --- a/test/yulPhaser/PairSelections.cpp +++ b/test/yulPhaser/PairSelections.cpp @@ -27,8 +27,6 @@ #include #include -using namespace std; - namespace solidity::phaser::test { @@ -45,35 +43,35 @@ BOOST_AUTO_TEST_CASE(materialise_should_return_random_values_with_equal_probabil constexpr double variance = (collectionSize * collectionSize - 1) / 12.0; SimulationRNG::reset(1); - vector> pairs = RandomPairSelection(selectionSize).materialise(collectionSize); - vector samples; + std::vector> pairs = RandomPairSelection(selectionSize).materialise(collectionSize); + std::vector samples; for (auto& [first, second]: pairs) { samples.push_back(first); samples.push_back(second); } - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(materialise_should_return_only_values_that_can_be_used_as_collection_indices) { const size_t collectionSize = 200; - vector> pairs = RandomPairSelection(0.5).materialise(collectionSize); + std::vector> pairs = RandomPairSelection(0.5).materialise(collectionSize); BOOST_TEST(pairs.size() == 100); - BOOST_TEST(all_of(pairs.begin(), pairs.end(), [&](auto const& pair){ return get<0>(pair) <= collectionSize; })); - BOOST_TEST(all_of(pairs.begin(), pairs.end(), [&](auto const& pair){ return get<1>(pair) <= collectionSize; })); + BOOST_TEST(all_of(pairs.begin(), pairs.end(), [&](auto const& pair){ return std::get<0>(pair) <= collectionSize; })); + BOOST_TEST(all_of(pairs.begin(), pairs.end(), [&](auto const& pair){ return std::get<1>(pair) <= collectionSize; })); } BOOST_AUTO_TEST_CASE(materialise_should_never_return_a_pair_of_identical_indices) { - vector> pairs = RandomPairSelection(0.5).materialise(100); + std::vector> pairs = RandomPairSelection(0.5).materialise(100); BOOST_TEST(pairs.size() == 50); - BOOST_TEST(all_of(pairs.begin(), pairs.end(), [](auto const& pair){ return get<0>(pair) != get<1>(pair); })); + BOOST_TEST(all_of(pairs.begin(), pairs.end(), [](auto const& pair){ return std::get<0>(pair) != std::get<1>(pair); })); } BOOST_AUTO_TEST_CASE(materialise_should_return_number_of_pairs_thats_a_fraction_of_collection_size) @@ -132,18 +130,18 @@ BOOST_AUTO_TEST_CASE(materialise_should_return_random_values_with_equal_probabil constexpr double variance = selectionChance * (1 - selectionChance); SimulationRNG::reset(1); - vector> pairs = PairsFromRandomSubset(selectionChance).materialise(collectionSize); - vector bernoulliTrials(collectionSize, 0); + std::vector> pairs = PairsFromRandomSubset(selectionChance).materialise(collectionSize); + std::vector bernoulliTrials(collectionSize, 0); for (auto& pair: pairs) { - BOOST_REQUIRE(get<1>(pair) < collectionSize); - BOOST_REQUIRE(get<1>(pair) < collectionSize); - bernoulliTrials[get<0>(pair)] = 1.0; - bernoulliTrials[get<1>(pair)] = 1.0; + BOOST_REQUIRE(std::get<1>(pair) < collectionSize); + BOOST_REQUIRE(std::get<1>(pair) < collectionSize); + bernoulliTrials[std::get<0>(pair)] = 1.0; + bernoulliTrials[std::get<1>(pair)] = 1.0; } - BOOST_TEST(abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(materialise_should_return_only_values_that_can_be_used_as_collection_indices) @@ -151,10 +149,10 @@ BOOST_AUTO_TEST_CASE(materialise_should_return_only_values_that_can_be_used_as_c const size_t collectionSize = 200; constexpr double selectionChance = 0.5; - vector> pairs = PairsFromRandomSubset(selectionChance).materialise(collectionSize); + std::vector> pairs = PairsFromRandomSubset(selectionChance).materialise(collectionSize); - BOOST_TEST(all_of(pairs.begin(), pairs.end(), [&](auto const& pair){ return get<0>(pair) <= collectionSize; })); - BOOST_TEST(all_of(pairs.begin(), pairs.end(), [&](auto const& pair){ return get<1>(pair) <= collectionSize; })); + BOOST_TEST(all_of(pairs.begin(), pairs.end(), [&](auto const& pair){ return std::get<0>(pair) <= collectionSize; })); + BOOST_TEST(all_of(pairs.begin(), pairs.end(), [&](auto const& pair){ return std::get<1>(pair) <= collectionSize; })); } BOOST_AUTO_TEST_CASE(materialise_should_use_unique_indices) @@ -162,12 +160,12 @@ BOOST_AUTO_TEST_CASE(materialise_should_use_unique_indices) constexpr size_t collectionSize = 200; constexpr double selectionChance = 0.5; - vector> pairs = PairsFromRandomSubset(selectionChance).materialise(collectionSize); - set indices; + std::vector> pairs = PairsFromRandomSubset(selectionChance).materialise(collectionSize); + std::set indices; for (auto& pair: pairs) { - indices.insert(get<0>(pair)); - indices.insert(get<1>(pair)); + indices.insert(std::get<0>(pair)); + indices.insert(std::get<1>(pair)); } BOOST_TEST(indices.size() == 2 * pairs.size()); @@ -195,7 +193,7 @@ BOOST_AUTO_TEST_CASE(materialise_should_return_all_pairs_if_selection_chance_is_ BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(PairMosaicSelectionTest) -using IndexPairs = vector>; +using IndexPairs = std::vector>; BOOST_AUTO_TEST_CASE(materialise) { diff --git a/test/yulPhaser/Phaser.cpp b/test/yulPhaser/Phaser.cpp index feee2269e761..671f75546305 100644 --- a/test/yulPhaser/Phaser.cpp +++ b/test/yulPhaser/Phaser.cpp @@ -32,7 +32,6 @@ #include #include -using namespace std; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -69,15 +68,15 @@ class GeneticAlgorithmFactoryFixture class FixtureWithPrograms { protected: - vector m_sourceStreams = { + std::vector m_sourceStreams = { CharStream("{}", ""), CharStream("{{}}", ""), CharStream("{{{}}}", ""), }; - vector m_programs = { - get(Program::load(m_sourceStreams[0])), - get(Program::load(m_sourceStreams[1])), - get(Program::load(m_sourceStreams[2])), + std::vector m_programs = { + std::get(Program::load(m_sourceStreams[0])), + std::get(Program::load(m_sourceStreams[1])), + std::get(Program::load(m_sourceStreams[2])), }; }; @@ -96,7 +95,7 @@ class FitnessMetricFactoryFixture: public FixtureWithPrograms class PoulationFactoryFixture { protected: - shared_ptr m_fitnessMetric = make_shared(); + std::shared_ptr m_fitnessMetric = std::make_shared(); PopulationFactory::Options m_options = { /* minChromosomeLength = */ 0, /* maxChromosomeLength = */ 0, @@ -113,7 +112,7 @@ BOOST_AUTO_TEST_SUITE(GeneticAlgorithmFactoryTest) BOOST_FIXTURE_TEST_CASE(build_should_select_the_right_algorithm_and_pass_the_options_to_it, GeneticAlgorithmFactoryFixture) { m_options.algorithm = Algorithm::Random; - unique_ptr algorithm1 = GeneticAlgorithmFactory::build(m_options, 100); + std::unique_ptr algorithm1 = GeneticAlgorithmFactory::build(m_options, 100); BOOST_REQUIRE(algorithm1 != nullptr); auto randomAlgorithm = dynamic_cast(algorithm1.get()); @@ -123,7 +122,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_select_the_right_algorithm_and_pass_the_opt BOOST_TEST(randomAlgorithm->options().maxChromosomeLength == m_options.maxChromosomeLength); m_options.algorithm = Algorithm::GEWEP; - unique_ptr algorithm2 = GeneticAlgorithmFactory::build(m_options, 100); + std::unique_ptr algorithm2 = GeneticAlgorithmFactory::build(m_options, 100); BOOST_REQUIRE(algorithm2 != nullptr); auto gewepAlgorithm = dynamic_cast(algorithm2.get()); @@ -139,7 +138,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_select_the_right_algorithm_and_pass_the_opt BOOST_TEST(gewepAlgorithm->options().percentGenesToAddOrDelete == m_options.gewepGenesToAddOrDelete.value()); m_options.algorithm = Algorithm::Classic; - unique_ptr algorithm3 = GeneticAlgorithmFactory::build(m_options, 100); + std::unique_ptr algorithm3 = GeneticAlgorithmFactory::build(m_options, 100); BOOST_REQUIRE(algorithm3 != nullptr); auto classicAlgorithm = dynamic_cast(algorithm3.get()); @@ -156,8 +155,8 @@ BOOST_FIXTURE_TEST_CASE(build_should_select_the_right_algorithm_and_pass_the_opt BOOST_FIXTURE_TEST_CASE(build_should_set_random_algorithm_elite_pool_size_based_on_population_size_if_not_specified, GeneticAlgorithmFactoryFixture) { m_options.algorithm = Algorithm::Random; - m_options.randomElitePoolSize = nullopt; - unique_ptr algorithm = GeneticAlgorithmFactory::build(m_options, 100); + m_options.randomElitePoolSize = std::nullopt; + std::unique_ptr algorithm = GeneticAlgorithmFactory::build(m_options, 100); BOOST_REQUIRE(algorithm != nullptr); auto randomAlgorithm = dynamic_cast(algorithm.get()); @@ -168,11 +167,11 @@ BOOST_FIXTURE_TEST_CASE(build_should_set_random_algorithm_elite_pool_size_based_ BOOST_FIXTURE_TEST_CASE(build_should_set_gewep_mutation_percentages_based_on_maximum_chromosome_length_if_not_specified, GeneticAlgorithmFactoryFixture) { m_options.algorithm = Algorithm::GEWEP; - m_options.gewepGenesToRandomise = nullopt; - m_options.gewepGenesToAddOrDelete = nullopt; + m_options.gewepGenesToRandomise = std::nullopt; + m_options.gewepGenesToAddOrDelete = std::nullopt; m_options.maxChromosomeLength = 125; - unique_ptr algorithm = GeneticAlgorithmFactory::build(m_options, 100); + std::unique_ptr algorithm = GeneticAlgorithmFactory::build(m_options, 100); BOOST_REQUIRE(algorithm != nullptr); auto gewepAlgorithm = dynamic_cast(algorithm.get()); @@ -188,7 +187,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_metric_of_the_right_type, FitnessMet { m_options.metric = MetricChoice::RelativeCodeSize; m_options.metricAggregator = MetricAggregatorChoice::Sum; - unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights); + std::unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights); BOOST_REQUIRE(metric != nullptr); auto sumMetric = dynamic_cast(metric.get()); @@ -206,7 +205,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_respect_chromosome_repetitions_option, Fitn m_options.metric = MetricChoice::CodeSize; m_options.metricAggregator = MetricAggregatorChoice::Average; m_options.chromosomeRepetitions = 5; - unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights); + std::unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights); BOOST_REQUIRE(metric != nullptr); auto averageMetric = dynamic_cast(metric.get()); @@ -224,7 +223,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_set_relative_metric_scale, FitnessMetricFac m_options.metric = MetricChoice::RelativeCodeSize; m_options.metricAggregator = MetricAggregatorChoice::Average; m_options.relativeMetricScale = 10; - unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights); + std::unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights); BOOST_REQUIRE(metric != nullptr); auto averageMetric = dynamic_cast(metric.get()); @@ -239,10 +238,10 @@ BOOST_FIXTURE_TEST_CASE(build_should_set_relative_metric_scale, FitnessMetricFac BOOST_FIXTURE_TEST_CASE(build_should_create_metric_for_each_input_program, FitnessMetricFactoryFixture) { - unique_ptr metric = FitnessMetricFactory::build( + std::unique_ptr metric = FitnessMetricFactory::build( m_options, m_programs, - vector>(m_programs.size(), nullptr), + std::vector>(m_programs.size(), nullptr), m_weights ); BOOST_REQUIRE(metric != nullptr); @@ -255,14 +254,14 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_metric_for_each_input_program, Fitne BOOST_FIXTURE_TEST_CASE(build_should_pass_program_caches_to_metrics, FitnessMetricFactoryFixture) { assert(m_programs.size() == 3); - vector> caches = { - make_shared(m_programs[0]), - make_shared(m_programs[1]), - make_shared(m_programs[2]), + std::vector> caches = { + std::make_shared(m_programs[0]), + std::make_shared(m_programs[1]), + std::make_shared(m_programs[2]), }; m_options.metric = MetricChoice::RelativeCodeSize; - unique_ptr metric = FitnessMetricFactory::build(m_options, m_programs, caches, m_weights); + std::unique_ptr metric = FitnessMetricFactory::build(m_options, m_programs, caches, m_weights); BOOST_REQUIRE(metric != nullptr); auto combinedMetric = dynamic_cast(metric.get()); @@ -287,7 +286,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_an_empty_population_if_no_specific_o m_options.populationFromFile = {}; BOOST_TEST( PopulationFactory::build(m_options, m_fitnessMetric) == - Population(m_fitnessMetric, vector{}) + Population(m_fitnessMetric, std::vector{}) ); } @@ -318,7 +317,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_respect_random_population_option, Poulation BOOST_FIXTURE_TEST_CASE(build_should_respect_population_from_file_option, PoulationFactoryFixture) { - map> fileContent = { + std::map> fileContent = { {"a.txt", {"a", "fff", "", "jxccLTa"}}, {"b.txt", {}}, {"c.txt", {""}}, @@ -328,9 +327,9 @@ BOOST_FIXTURE_TEST_CASE(build_should_respect_population_from_file_option, Poulat TemporaryDirectory tempDir; for (auto const& [fileName, chromosomes]: fileContent) { - ofstream tmpFile((tempDir.path() / fileName).string()); + std::ofstream tmpFile((tempDir.path() / fileName).string()); for (auto const& chromosome: chromosomes) - tmpFile << chromosome << endl; + tmpFile << chromosome << std::endl; m_options.populationFromFile.push_back((tempDir.path() / fileName).string()); } @@ -361,8 +360,8 @@ BOOST_FIXTURE_TEST_CASE(build_should_combine_populations_from_all_sources, Poula { TemporaryDirectory tempDir; { - ofstream tmpFile((tempDir.path() / "population.txt").string()); - tmpFile << "axc" << endl << "fcL" << endl; + std::ofstream tmpFile((tempDir.path() / "population.txt").string()); + tmpFile << "axc" << std::endl << "fcL" << std::endl; } m_options.population = {"axc", "fcL"}; @@ -388,7 +387,7 @@ BOOST_AUTO_TEST_SUITE(ProgramCacheFactoryTest) BOOST_FIXTURE_TEST_CASE(build_should_create_cache_for_each_input_program_if_cache_enabled, FixtureWithPrograms) { ProgramCacheFactory::Options options{/* programCacheEnabled = */ true}; - vector> caches = ProgramCacheFactory::build(options, m_programs); + std::vector> caches = ProgramCacheFactory::build(options, m_programs); assert(m_programs.size() >= 2 && "There must be at least 2 programs for this test to be meaningful"); BOOST_TEST(caches.size() == m_programs.size()); @@ -402,7 +401,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_cache_for_each_input_program_if_cach BOOST_FIXTURE_TEST_CASE(build_should_return_nullptr_for_each_input_program_if_cache_disabled, FixtureWithPrograms) { ProgramCacheFactory::Options options{/* programCacheEnabled = */ false}; - vector> caches = ProgramCacheFactory::build(options, m_programs); + std::vector> caches = ProgramCacheFactory::build(options, m_programs); assert(m_programs.size() >= 2 && "There must be at least 2 programs for this test to be meaningful"); BOOST_TEST(caches.size() == m_programs.size()); @@ -416,7 +415,7 @@ BOOST_AUTO_TEST_SUITE(ProgramFactoryTest) BOOST_AUTO_TEST_CASE(build_should_load_programs_from_files) { TemporaryDirectory tempDir; - vector sources{"{}", "{{}}", "{{{}}}"}; + std::vector sources{"{}", "{{}}", "{{{}}}"}; ProgramFactory::Options options{ /* inputFiles = */ { (tempDir.path() / "program1.yul").string(), @@ -428,17 +427,17 @@ BOOST_AUTO_TEST_CASE(build_should_load_programs_from_files) for (size_t i = 0; i < sources.size(); ++i) { - ofstream tmpFile(options.inputFiles[i]); - tmpFile << sources[i] << endl; + std::ofstream tmpFile(options.inputFiles[i]); + tmpFile << sources[i] << std::endl; } - vector programs = ProgramFactory::build(options); + std::vector programs = ProgramFactory::build(options); BOOST_TEST(programs.size() == sources.size()); for (size_t i = 0; i < sources.size(); ++i) { CharStream sourceStream(sources[i], options.inputFiles[i]); - BOOST_TEST(toString(programs[i]) == toString(get(Program::load(sourceStream)))); + BOOST_TEST(toString(programs[i]) == toString(std::get(Program::load(sourceStream)))); } } @@ -451,17 +450,17 @@ BOOST_AUTO_TEST_CASE(build_should_apply_prefix) }; CharStream nestedSource("{{{let x:= 1}}}", ""); - Program nestedProgram = get(Program::load(nestedSource)); - Program flatProgram = get(Program::load(nestedSource)); + Program nestedProgram = std::get(Program::load(nestedSource)); + Program flatProgram = std::get(Program::load(nestedSource)); flatProgram.optimise(Chromosome::genesToSteps("f")); assert(toString(nestedProgram) != toString(flatProgram)); { - ofstream tmpFile(options.inputFiles[0]); - tmpFile << nestedSource.source() << endl; + std::ofstream tmpFile(options.inputFiles[0]); + tmpFile << nestedSource.source() << std::endl; } - vector programs = ProgramFactory::build(options); + std::vector programs = ProgramFactory::build(options); BOOST_TEST(programs.size() == 1); BOOST_TEST(toString(programs[0]) == toString(flatProgram)); diff --git a/test/yulPhaser/Population.cpp b/test/yulPhaser/Population.cpp index 13d06b521030..aed014592c1b 100644 --- a/test/yulPhaser/Population.cpp +++ b/test/yulPhaser/Population.cpp @@ -38,7 +38,6 @@ #include #include -using namespace std; using namespace solidity::langutil; using namespace solidity::yul; using namespace boost::unit_test::framework; @@ -52,12 +51,12 @@ class PopulationFixture static ChromosomePair twoStepSwap(Chromosome const& _chromosome1, Chromosome const& _chromosome2) { return ChromosomePair{ - Chromosome(vector{_chromosome1.optimisationSteps()[0], _chromosome2.optimisationSteps()[1]}), - Chromosome(vector{_chromosome2.optimisationSteps()[0], _chromosome1.optimisationSteps()[1]}), + Chromosome(std::vector{_chromosome1.optimisationSteps()[0], _chromosome2.optimisationSteps()[1]}), + Chromosome(std::vector{_chromosome2.optimisationSteps()[0], _chromosome1.optimisationSteps()[1]}), }; } - shared_ptr m_fitnessMetric = make_shared(); + std::shared_ptr m_fitnessMetric = std::make_shared(); }; BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) @@ -95,14 +94,14 @@ BOOST_AUTO_TEST_CASE(isFitter_should_return_false_for_identical_individuals) BOOST_FIXTURE_TEST_CASE(constructor_should_copy_chromosomes_compute_fitness_and_sort_chromosomes, PopulationFixture) { - vector chromosomes = { + std::vector chromosomes = { Chromosome::makeRandom(5), Chromosome::makeRandom(15), Chromosome::makeRandom(10), }; Population population(m_fitnessMetric, chromosomes); - vector const& individuals = population.individuals(); + std::vector const& individuals = population.individuals(); BOOST_TEST(individuals.size() == 3); BOOST_TEST(individuals[0].fitness == 5); @@ -115,7 +114,7 @@ BOOST_FIXTURE_TEST_CASE(constructor_should_copy_chromosomes_compute_fitness_and_ BOOST_FIXTURE_TEST_CASE(constructor_should_accept_individuals_without_recalculating_fitness, PopulationFixture) { - vector customIndividuals = { + std::vector customIndividuals = { Individual(Chromosome("aaaccc"), 20), Individual(Chromosome("aaa"), 10), Individual(Chromosome("aaaf"), 30), @@ -126,7 +125,7 @@ BOOST_FIXTURE_TEST_CASE(constructor_should_accept_individuals_without_recalculat Population population(m_fitnessMetric, customIndividuals); - vector expectedIndividuals{customIndividuals[1], customIndividuals[0], customIndividuals[2]}; + std::vector expectedIndividuals{customIndividuals[1], customIndividuals[0], customIndividuals[2]}; BOOST_TEST(population.individuals() == expectedIndividuals); } @@ -170,13 +169,13 @@ BOOST_FIXTURE_TEST_CASE(makeRandom_should_use_random_chromosome_length, Populati constexpr double relativeTolerance = 0.05; auto population = Population::makeRandom(m_fitnessMetric, populationSize, minLength, maxLength); - vector samples = chromosomeLengths(population); + std::vector samples = chromosomeLengths(population); const double expectedValue = (maxLength + minLength) / 2.0; const double variance = ((maxLength - minLength + 1) * (maxLength - minLength + 1) - 1) / 12.0; - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_FIXTURE_TEST_CASE(makeRandom_should_return_population_with_random_chromosomes, PopulationFixture) @@ -186,10 +185,10 @@ BOOST_FIXTURE_TEST_CASE(makeRandom_should_return_population_with_random_chromoso constexpr int chromosomeLength = 30; constexpr double relativeTolerance = 0.01; - map stepIndices = enumerateOptmisationSteps(); + std::map stepIndices = enumerateOptmisationSteps(); auto population = Population::makeRandom(m_fitnessMetric, populationSize, chromosomeLength, chromosomeLength); - vector samples; + std::vector samples; for (auto& individual: population.individuals()) for (auto& step: individual.chromosome.optimisationSteps()) samples.push_back(stepIndices.at(step)); @@ -197,8 +196,8 @@ BOOST_FIXTURE_TEST_CASE(makeRandom_should_return_population_with_random_chromoso 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(std::abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_FIXTURE_TEST_CASE(makeRandom_should_compute_fitness, PopulationFixture) @@ -223,7 +222,7 @@ BOOST_FIXTURE_TEST_CASE(select_should_return_population_containing_individuals_i { Population population(m_fitnessMetric, {Chromosome("a"), Chromosome("c"), Chromosome("g"), Chromosome("h")}); RangeSelection selection(0.25, 0.75); - assert(selection.materialise(population.individuals().size()) == (vector{1, 2})); + assert(selection.materialise(population.individuals().size()) == (std::vector{1, 2})); BOOST_TEST( population.select(selection) == @@ -235,7 +234,7 @@ BOOST_FIXTURE_TEST_CASE(select_should_include_duplicates_if_selection_contains_d { Population population(m_fitnessMetric, {Chromosome("a"), Chromosome("c")}); MosaicSelection selection({0, 1}, 2.0); - assert(selection.materialise(population.individuals().size()) == (vector{0, 1, 0, 1})); + assert(selection.materialise(population.individuals().size()) == (std::vector{0, 1, 0, 1})); BOOST_TEST(population.select(selection) == Population(m_fitnessMetric, { population.individuals()[0].chromosome, @@ -258,7 +257,7 @@ BOOST_FIXTURE_TEST_CASE(mutate_should_return_population_containing_individuals_i { Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc"), Chromosome("gg"), Chromosome("hh")}); RangeSelection selection(0.25, 0.75); - assert(selection.materialise(population.individuals().size()) == (vector{1, 2})); + assert(selection.materialise(population.individuals().size()) == (std::vector{1, 2})); Population expectedPopulation(m_fitnessMetric, {Chromosome("fc"), Chromosome("fg")}); @@ -269,7 +268,7 @@ BOOST_FIXTURE_TEST_CASE(mutate_should_include_duplicates_if_selection_contains_d { Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("aa")}); RangeSelection selection(0.0, 1.0); - assert(selection.materialise(population.individuals().size()) == (vector{0, 1})); + assert(selection.materialise(population.individuals().size()) == (std::vector{0, 1})); BOOST_TEST( population.mutate(selection, geneSubstitution(0, BlockFlattener::name)) == @@ -290,7 +289,7 @@ BOOST_FIXTURE_TEST_CASE(crossover_should_return_population_containing_individual { Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc"), Chromosome("gg"), Chromosome("hh")}); PairMosaicSelection selection({{0, 1}, {2, 1}}, 1.0); - assert(selection.materialise(population.individuals().size()) == (vector>{{0, 1}, {2, 1}, {0, 1}, {2, 1}})); + assert(selection.materialise(population.individuals().size()) == (std::vector>{{0, 1}, {2, 1}, {0, 1}, {2, 1}})); Population expectedPopulation(m_fitnessMetric, {Chromosome("ac"), Chromosome("ac"), Chromosome("gc"), Chromosome("gc")}); @@ -301,7 +300,7 @@ BOOST_FIXTURE_TEST_CASE(crossover_should_include_duplicates_if_selection_contain { Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("aa")}); PairMosaicSelection selection({{0, 0}, {1, 1}}, 2.0); - assert(selection.materialise(population.individuals().size()) == (vector>{{0, 0}, {1, 1}, {0, 0}, {1, 1}})); + assert(selection.materialise(population.individuals().size()) == (std::vector>{{0, 0}, {1, 1}, {0, 0}, {1, 1}})); BOOST_TEST( population.crossover(selection, fixedPointCrossover(0.5)) == @@ -322,14 +321,14 @@ BOOST_FIXTURE_TEST_CASE(symmetricCrossoverWithRemainder_should_return_crossed_po { Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc"), Chromosome("gg"), Chromosome("hh")}); PairMosaicSelection selection({{2, 1}}, 0.25); - assert(selection.materialise(population.individuals().size()) == (vector>{{2, 1}})); + assert(selection.materialise(population.individuals().size()) == (std::vector>{{2, 1}})); Population expectedCrossedPopulation(m_fitnessMetric, {Chromosome("gc"), Chromosome("cg")}); Population expectedRemainder(m_fitnessMetric, {Chromosome("aa"), Chromosome("hh")}); BOOST_TEST( population.symmetricCrossoverWithRemainder(selection, twoStepSwap) == - (tuple{expectedCrossedPopulation, expectedRemainder}) + (std::tuple{expectedCrossedPopulation, expectedRemainder}) ); } @@ -337,7 +336,7 @@ BOOST_FIXTURE_TEST_CASE(symmetricCrossoverWithRemainder_should_allow_crossing_th { Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc"), Chromosome("gg"), Chromosome("hh")}); PairMosaicSelection selection({{0, 0}, {2, 1}}, 1.0); - assert(selection.materialise(population.individuals().size()) == (vector>{{0, 0}, {2, 1}, {0, 0}, {2, 1}})); + assert(selection.materialise(population.individuals().size()) == (std::vector>{{0, 0}, {2, 1}, {0, 0}, {2, 1}})); Population expectedCrossedPopulation(m_fitnessMetric, { Chromosome("aa"), Chromosome("aa"), @@ -349,7 +348,7 @@ BOOST_FIXTURE_TEST_CASE(symmetricCrossoverWithRemainder_should_allow_crossing_th BOOST_TEST( population.symmetricCrossoverWithRemainder(selection, twoStepSwap) == - (tuple{expectedCrossedPopulation, expectedRemainder}) + (std::tuple{expectedCrossedPopulation, expectedRemainder}) ); } @@ -361,7 +360,7 @@ BOOST_FIXTURE_TEST_CASE(symmetricCrossoverWithRemainder_should_return_empty_popu BOOST_TEST( population.symmetricCrossoverWithRemainder(selection, twoStepSwap) == - (tuple{Population(m_fitnessMetric), population}) + (std::tuple{Population(m_fitnessMetric), population}) ); } diff --git a/test/yulPhaser/Program.cpp b/test/yulPhaser/Program.cpp index 2e91926d059f..a54bf09af146 100644 --- a/test/yulPhaser/Program.cpp +++ b/test/yulPhaser/Program.cpp @@ -34,7 +34,6 @@ #include #include -using namespace std; using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; @@ -47,7 +46,7 @@ namespace /// If the block isn't redundant it just returns it immediately. Block const& skipRedundantBlocks(Block const& _block) { - if (_block.statements.size() == 1 && holds_alternative(_block.statements[0])) + if (_block.statements.size() == 1 && std::holds_alternative(_block.statements[0])) return skipRedundantBlocks(get(_block.statements[0])); else return _block; @@ -62,7 +61,7 @@ BOOST_AUTO_TEST_SUITE(ProgramTest) BOOST_AUTO_TEST_CASE(copy_constructor_should_make_deep_copy_of_ast) { - string sourceCode( + std::string sourceCode( "{\n" " let x := 1\n" "}\n" @@ -82,7 +81,7 @@ BOOST_AUTO_TEST_CASE(copy_constructor_should_make_deep_copy_of_ast) BOOST_AUTO_TEST_CASE(load_should_rewind_the_stream) { - string sourceCode( + std::string sourceCode( "{\n" " let x := 1\n" " let y := 2\n" @@ -98,7 +97,7 @@ BOOST_AUTO_TEST_CASE(load_should_rewind_the_stream) BOOST_AUTO_TEST_CASE(load_should_disambiguate) { - string sourceCode( + std::string sourceCode( "{\n" " {\n" " let x := 1\n" @@ -126,7 +125,7 @@ BOOST_AUTO_TEST_CASE(load_should_disambiguate) BOOST_AUTO_TEST_CASE(load_should_do_function_grouping_and_hoisting) { - string sourceCode( + std::string sourceCode( "{\n" " function foo() -> result\n" " {\n" @@ -144,14 +143,14 @@ BOOST_AUTO_TEST_CASE(load_should_do_function_grouping_and_hoisting) Program program = get(Program::load(sourceStream)); BOOST_TEST(program.ast().statements.size() == 3); - BOOST_TEST(holds_alternative(program.ast().statements[0])); - BOOST_TEST(holds_alternative(program.ast().statements[1])); - BOOST_TEST(holds_alternative(program.ast().statements[2])); + BOOST_TEST(std::holds_alternative(program.ast().statements[0])); + BOOST_TEST(std::holds_alternative(program.ast().statements[1])); + BOOST_TEST(std::holds_alternative(program.ast().statements[2])); } BOOST_AUTO_TEST_CASE(load_should_do_loop_init_rewriting) { - string sourceCode( + std::string sourceCode( "{\n" " for { let i := 0 } true {}\n" " {\n" @@ -163,35 +162,35 @@ BOOST_AUTO_TEST_CASE(load_should_do_loop_init_rewriting) // skipRedundantBlocks() makes the test independent of whether load() includes function grouping or not. Block const& parentBlock = skipRedundantBlocks(program.ast()); - BOOST_TEST(holds_alternative(parentBlock.statements[0])); - BOOST_TEST(holds_alternative(parentBlock.statements[1])); + BOOST_TEST(std::holds_alternative(parentBlock.statements[0])); + BOOST_TEST(std::holds_alternative(parentBlock.statements[1])); } BOOST_AUTO_TEST_CASE(load_should_throw_InvalidProgram_if_program_cant_be_parsed) { - string sourceCode("invalid program\n"); + std::string sourceCode("invalid program\n"); CharStream sourceStream(sourceCode, current_test_case().p_name); - BOOST_TEST(holds_alternative(Program::load(sourceStream))); + BOOST_TEST(std::holds_alternative(Program::load(sourceStream))); } BOOST_AUTO_TEST_CASE(load_should_throw_InvalidProgram_if_program_cant_be_analyzed) { // This should be parsed just fine but fail the analysis with: // Error: Variable not found or variable not lvalue. - string sourceCode( + std::string sourceCode( "{\n" " x := 1\n" "}\n" ); CharStream sourceStream(sourceCode, current_test_case().p_name); - BOOST_TEST(holds_alternative(Program::load(sourceStream))); + BOOST_TEST(std::holds_alternative(Program::load(sourceStream))); } BOOST_AUTO_TEST_CASE(load_should_accept_yul_objects_as_input) { - string sourceCode( + std::string sourceCode( "object \"C_178\" {\n" " code {\n" " mstore(64, 128)\n" @@ -203,12 +202,12 @@ BOOST_AUTO_TEST_CASE(load_should_accept_yul_objects_as_input) CharStream sourceStream(sourceCode, current_test_case().p_name); auto programOrErrors = Program::load(sourceStream); - BOOST_TEST(holds_alternative(programOrErrors)); + BOOST_TEST(std::holds_alternative(programOrErrors)); } BOOST_AUTO_TEST_CASE(load_should_return_errors_if_analysis_of_object_code_fails) { - string sourceCode( + std::string sourceCode( "object \"C_178\" {\n" " code {\n" " return(0, datasize(\"C_178_deployed\"))\n" @@ -218,12 +217,12 @@ BOOST_AUTO_TEST_CASE(load_should_return_errors_if_analysis_of_object_code_fails) CharStream sourceStream(sourceCode, current_test_case().p_name); auto programOrErrors = Program::load(sourceStream); - BOOST_TEST(holds_alternative(programOrErrors)); + BOOST_TEST(std::holds_alternative(programOrErrors)); } BOOST_AUTO_TEST_CASE(load_should_return_errors_if_parsing_of_nested_object_fails) { - string sourceCode( + std::string sourceCode( "object \"C_178\" {\n" " code {\n" " return(0, datasize(\"C_178_deployed\"))\n" @@ -243,12 +242,12 @@ BOOST_AUTO_TEST_CASE(load_should_return_errors_if_parsing_of_nested_object_fails CharStream sourceStream(sourceCode, current_test_case().p_name); auto programOrErrors = Program::load(sourceStream); - BOOST_TEST(holds_alternative(programOrErrors)); + BOOST_TEST(std::holds_alternative(programOrErrors)); } BOOST_AUTO_TEST_CASE(load_should_extract_nested_object_with_deployed_suffix_if_present) { - string sourceCode( + std::string sourceCode( "object \"C_178\" {\n" " code {\n" " return(0, datasize(\"C_178_deployed\"))\n" @@ -265,12 +264,12 @@ BOOST_AUTO_TEST_CASE(load_should_extract_nested_object_with_deployed_suffix_if_p CharStream sourceStream(sourceCode, current_test_case().p_name); auto programOrErrors = Program::load(sourceStream); - BOOST_TEST(holds_alternative(programOrErrors)); + BOOST_TEST(std::holds_alternative(programOrErrors)); } BOOST_AUTO_TEST_CASE(load_should_fall_back_to_parsing_the_whole_object_if_there_is_no_subobject_with_the_right_name) { - string sourceCode( + std::string sourceCode( "object \"C_178\" {\n" " code {\n" " mstore(64, 128)\n" @@ -292,16 +291,16 @@ BOOST_AUTO_TEST_CASE(load_should_fall_back_to_parsing_the_whole_object_if_there_ CharStream sourceStream(sourceCode, current_test_case().p_name); auto programOrErrors = Program::load(sourceStream); - BOOST_TEST(holds_alternative(programOrErrors)); + BOOST_TEST(std::holds_alternative(programOrErrors)); Block const& parentBlock = skipRedundantBlocks(get(programOrErrors).ast()); BOOST_TEST(parentBlock.statements.size() == 1); - BOOST_TEST(holds_alternative(parentBlock.statements[0])); + BOOST_TEST(std::holds_alternative(parentBlock.statements[0])); } BOOST_AUTO_TEST_CASE(load_should_ignore_data_in_objects) { - string sourceCode( + std::string sourceCode( "object \"C_178\" {\n" " code {\n" " mstore(64, 128)\n" @@ -312,12 +311,12 @@ BOOST_AUTO_TEST_CASE(load_should_ignore_data_in_objects) CharStream sourceStream(sourceCode, current_test_case().p_name); auto programOrErrors = Program::load(sourceStream); - BOOST_TEST(holds_alternative(programOrErrors)); + BOOST_TEST(std::holds_alternative(programOrErrors)); } BOOST_AUTO_TEST_CASE(optimise) { - string sourceCode( + std::string sourceCode( "{\n" " {\n" " if 1 { let x := 1 }\n" @@ -330,22 +329,22 @@ BOOST_AUTO_TEST_CASE(optimise) [[maybe_unused]] Block const& parentBlockBefore = skipRedundantBlocks(program.ast()); assert(parentBlockBefore.statements.size() == 2); - assert(holds_alternative(parentBlockBefore.statements[0])); - assert(holds_alternative(parentBlockBefore.statements[1])); + assert(std::holds_alternative(parentBlockBefore.statements[0])); + assert(std::holds_alternative(parentBlockBefore.statements[1])); program.optimise({StructuralSimplifier::name, BlockFlattener::name}); Block const& parentBlockAfter = program.ast(); BOOST_TEST(parentBlockAfter.statements.size() == 1); - BOOST_TEST(holds_alternative(parentBlockAfter.statements[0])); + BOOST_TEST(std::holds_alternative(parentBlockAfter.statements[0])); Block const& innerBlock = get(parentBlockAfter.statements[0]); BOOST_TEST(innerBlock.statements.size() == 1); - BOOST_TEST(holds_alternative(innerBlock.statements[0])); + BOOST_TEST(std::holds_alternative(innerBlock.statements[0])); } BOOST_AUTO_TEST_CASE(output_operator) { - string sourceCode( + std::string sourceCode( "{\n" " let factor := 13\n" " {\n" @@ -369,7 +368,7 @@ BOOST_AUTO_TEST_CASE(output_operator) BOOST_AUTO_TEST_CASE(toJson) { - string sourceCode( + std::string sourceCode( "{\n" " let a := 3\n" " if a\n" @@ -382,14 +381,14 @@ BOOST_AUTO_TEST_CASE(toJson) Program program = get(Program::load(sourceStream)); Json::Value parsingResult; - string errors; + std::string errors; BOOST_TEST(jsonParseStrict(program.toJson(), parsingResult, &errors)); BOOST_TEST(errors.empty()); } BOOST_AUTO_TEST_CASE(codeSize) { - string sourceCode( + std::string sourceCode( "{\n" " function foo() -> result\n" " {\n" diff --git a/test/yulPhaser/ProgramCache.cpp b/test/yulPhaser/ProgramCache.cpp index 2dab86fcda17..c4bf7f609e61 100644 --- a/test/yulPhaser/ProgramCache.cpp +++ b/test/yulPhaser/ProgramCache.cpp @@ -30,7 +30,6 @@ #include #include -using namespace std; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -50,16 +49,16 @@ class ProgramCacheFixture " }\n" "}\n"; - Program optimisedProgram(Program _program, string _abbreviatedOptimisationSteps) const + Program optimisedProgram(Program _program, std::string _abbreviatedOptimisationSteps) const { Program result = std::move(_program); result.optimise(Chromosome::genesToSteps(_abbreviatedOptimisationSteps)); return result; } - static set cachedKeys(ProgramCache const& _programCache) + static std::set cachedKeys(ProgramCache const& _programCache) { - set keys; + std::set keys; for (auto pair = _programCache.entries().begin(); pair != _programCache.entries().end(); ++pair) keys.insert(pair->first); @@ -67,7 +66,7 @@ class ProgramCacheFixture } CharStream m_sourceStream = CharStream(SampleSourceCode, "program-cache-test"); - Program m_program = get(Program::load(m_sourceStream)); + Program m_program = std::get(Program::load(m_sourceStream)); ProgramCache m_programCache{m_program}; }; @@ -111,7 +110,7 @@ BOOST_FIXTURE_TEST_CASE(optimiseProgram_should_store_programs_for_all_prefixes, BOOST_TEST(toString(cachedProgram) == toString(programIuO)); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"I", "Iu", "IuO"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"I", "Iu", "IuO"})); BOOST_TEST(toString(*m_programCache.find("I")) == toString(programI)); BOOST_TEST(toString(*m_programCache.find("Iu")) == toString(programIu)); BOOST_TEST(toString(*m_programCache.find("IuO")) == toString(programIuO)); @@ -119,7 +118,7 @@ BOOST_FIXTURE_TEST_CASE(optimiseProgram_should_store_programs_for_all_prefixes, BOOST_FIXTURE_TEST_CASE(optimiseProgram_should_repeat_the_chromosome_requested_number_of_times, ProgramCacheFixture) { - string steps = "IuOIuO"; + std::string steps = "IuOIuO"; Program cachedProgram = m_programCache.optimiseProgram("IuO", 2); @@ -148,14 +147,14 @@ BOOST_FIXTURE_TEST_CASE(optimiseProgram_should_reuse_the_longest_prefix_and_move m_programCache.startRound(1); BOOST_TEST(m_programCache.currentRound() == 1); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"I", "Iu", "Ia"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"I", "Iu", "Ia"})); BOOST_TEST(m_programCache.entries().find("I")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("Iu")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("Ia")->second.roundNumber == 0); m_programCache.optimiseProgram("IuOI"); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"I", "Iu", "Ia", "IuO", "IuOI"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"I", "Iu", "Ia", "IuO", "IuOI"})); BOOST_TEST(m_programCache.entries().find("I")->second.roundNumber == 1); BOOST_TEST(m_programCache.entries().find("Iu")->second.roundNumber == 1); BOOST_TEST(m_programCache.entries().find("Ia")->second.roundNumber == 0); @@ -171,14 +170,14 @@ BOOST_FIXTURE_TEST_CASE(startRound_should_remove_entries_older_than_two_rounds, m_programCache.optimiseProgram("Iu"); BOOST_TEST(m_programCache.currentRound() == 0); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"I", "Iu"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"I", "Iu"})); BOOST_TEST(m_programCache.entries().find("I")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("Iu")->second.roundNumber == 0); m_programCache.optimiseProgram("a"); BOOST_TEST(m_programCache.currentRound() == 0); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"I", "Iu", "a"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"I", "Iu", "a"})); BOOST_TEST(m_programCache.entries().find("I")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("Iu")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("a")->second.roundNumber == 0); @@ -186,7 +185,7 @@ BOOST_FIXTURE_TEST_CASE(startRound_should_remove_entries_older_than_two_rounds, m_programCache.startRound(1); BOOST_TEST(m_programCache.currentRound() == 1); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"I", "Iu", "a"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"I", "Iu", "a"})); BOOST_TEST(m_programCache.entries().find("I")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("Iu")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("a")->second.roundNumber == 0); @@ -194,7 +193,7 @@ BOOST_FIXTURE_TEST_CASE(startRound_should_remove_entries_older_than_two_rounds, m_programCache.optimiseProgram("af"); BOOST_TEST(m_programCache.currentRound() == 1); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"I", "Iu", "a", "af"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"I", "Iu", "a", "af"})); BOOST_TEST(m_programCache.entries().find("I")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("Iu")->second.roundNumber == 0); BOOST_TEST(m_programCache.entries().find("a")->second.roundNumber == 1); @@ -203,7 +202,7 @@ BOOST_FIXTURE_TEST_CASE(startRound_should_remove_entries_older_than_two_rounds, m_programCache.startRound(2); BOOST_TEST(m_programCache.currentRound() == 2); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"a", "af"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"a", "af"})); BOOST_TEST(m_programCache.entries().find("a")->second.roundNumber == 1); BOOST_TEST(m_programCache.entries().find("af")->second.roundNumber == 1); @@ -223,31 +222,31 @@ BOOST_FIXTURE_TEST_CASE(gatherStats_should_return_cache_statistics, ProgramCache m_programCache.optimiseProgram("L"); m_programCache.optimiseProgram("Iu"); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"L", "I", "Iu"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"L", "I", "Iu"})); CacheStats expectedStats1{0, 3, sizeL + sizeI + sizeIu, {{0, 3}}}; BOOST_CHECK(m_programCache.gatherStats() == expectedStats1); m_programCache.optimiseProgram("IuO"); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"L", "I", "Iu", "IuO"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"L", "I", "Iu", "IuO"})); CacheStats expectedStats2{2, 4, sizeL + sizeI + sizeIu + sizeIuO, {{0, 4}}}; BOOST_CHECK(m_programCache.gatherStats() == expectedStats2); m_programCache.startRound(1); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"L", "I", "Iu", "IuO"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"L", "I", "Iu", "IuO"})); BOOST_CHECK(m_programCache.gatherStats() == expectedStats2); m_programCache.optimiseProgram("IuO"); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"L", "I", "Iu", "IuO"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"L", "I", "Iu", "IuO"})); CacheStats expectedStats3{5, 4, sizeL + sizeI + sizeIu + sizeIuO, {{0, 1}, {1, 3}}}; BOOST_CHECK(m_programCache.gatherStats() == expectedStats3); m_programCache.startRound(2); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"I", "Iu", "IuO"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"I", "Iu", "IuO"})); CacheStats expectedStats4{5, 4, sizeI + sizeIu + sizeIuO, {{1, 3}}}; BOOST_CHECK(m_programCache.gatherStats() == expectedStats4); m_programCache.optimiseProgram("LT"); - BOOST_REQUIRE((cachedKeys(m_programCache) == set{"L", "LT", "I", "Iu", "IuO"})); + BOOST_REQUIRE((cachedKeys(m_programCache) == std::set{"L", "LT", "I", "Iu", "IuO"})); CacheStats expectedStats5{5, 6, sizeL + sizeLT + sizeI + sizeIu + sizeIuO, {{1, 3}, {2, 2}}}; BOOST_CHECK(m_programCache.gatherStats() == expectedStats5); } diff --git a/test/yulPhaser/Selections.cpp b/test/yulPhaser/Selections.cpp index 28c8b8a879dc..866234978590 100644 --- a/test/yulPhaser/Selections.cpp +++ b/test/yulPhaser/Selections.cpp @@ -29,7 +29,6 @@ #include #include -using namespace std; using namespace solidity::util; namespace solidity::phaser::test @@ -41,28 +40,28 @@ BOOST_AUTO_TEST_SUITE(RangeSelectionTest) BOOST_AUTO_TEST_CASE(materialise) { - BOOST_TEST(RangeSelection(0.0, 1.0).materialise(10) == vector({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); - BOOST_TEST(RangeSelection(0.0, 0.1).materialise(10) == vector({0})); - BOOST_TEST(RangeSelection(0.0, 0.2).materialise(10) == vector({0, 1})); - BOOST_TEST(RangeSelection(0.0, 0.7).materialise(10) == vector({0, 1, 2, 3, 4, 5, 6})); + BOOST_TEST(RangeSelection(0.0, 1.0).materialise(10) == std::vector({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + BOOST_TEST(RangeSelection(0.0, 0.1).materialise(10) == std::vector({0})); + BOOST_TEST(RangeSelection(0.0, 0.2).materialise(10) == std::vector({0, 1})); + BOOST_TEST(RangeSelection(0.0, 0.7).materialise(10) == std::vector({0, 1, 2, 3, 4, 5, 6})); - BOOST_TEST(RangeSelection(0.9, 1.0).materialise(10) == vector({ 9})); - BOOST_TEST(RangeSelection(0.8, 1.0).materialise(10) == vector({ 8, 9})); - BOOST_TEST(RangeSelection(0.5, 1.0).materialise(10) == vector({ 5, 6, 7, 8, 9})); + BOOST_TEST(RangeSelection(0.9, 1.0).materialise(10) == std::vector({ 9})); + BOOST_TEST(RangeSelection(0.8, 1.0).materialise(10) == std::vector({ 8, 9})); + BOOST_TEST(RangeSelection(0.5, 1.0).materialise(10) == std::vector({ 5, 6, 7, 8, 9})); - BOOST_TEST(RangeSelection(0.3, 0.6).materialise(10) == vector({ 3, 4, 5 })); - BOOST_TEST(RangeSelection(0.2, 0.7).materialise(10) == vector({ 2, 3, 4, 5, 6 })); - BOOST_TEST(RangeSelection(0.4, 0.7).materialise(10) == vector({ 4, 5, 6 })); + BOOST_TEST(RangeSelection(0.3, 0.6).materialise(10) == std::vector({ 3, 4, 5 })); + BOOST_TEST(RangeSelection(0.2, 0.7).materialise(10) == std::vector({ 2, 3, 4, 5, 6 })); + BOOST_TEST(RangeSelection(0.4, 0.7).materialise(10) == std::vector({ 4, 5, 6 })); - BOOST_TEST(RangeSelection(0.4, 0.7).materialise(5) == vector({2, 3})); + BOOST_TEST(RangeSelection(0.4, 0.7).materialise(5) == std::vector({2, 3})); } BOOST_AUTO_TEST_CASE(materialise_should_round_indices) { - BOOST_TEST(RangeSelection(0.01, 0.99).materialise(10) == vector({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); - BOOST_TEST(RangeSelection(0.04, 0.96).materialise(10) == vector({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); - BOOST_TEST(RangeSelection(0.05, 0.95).materialise(10) == vector({ 1, 2, 3, 4, 5, 6, 7, 8, 9})); - BOOST_TEST(RangeSelection(0.06, 0.94).materialise(10) == vector({ 1, 2, 3, 4, 5, 6, 7, 8 })); + BOOST_TEST(RangeSelection(0.01, 0.99).materialise(10) == std::vector({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + BOOST_TEST(RangeSelection(0.04, 0.96).materialise(10) == std::vector({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + BOOST_TEST(RangeSelection(0.05, 0.95).materialise(10) == std::vector({ 1, 2, 3, 4, 5, 6, 7, 8, 9})); + BOOST_TEST(RangeSelection(0.06, 0.94).materialise(10) == std::vector({ 1, 2, 3, 4, 5, 6, 7, 8 })); } BOOST_AUTO_TEST_CASE(materialise_should_handle_empty_collections) @@ -93,27 +92,27 @@ BOOST_AUTO_TEST_SUITE(MosaicSelectionTest) BOOST_AUTO_TEST_CASE(materialise) { - BOOST_TEST(MosaicSelection({1}, 0.5).materialise(4) == vector({1, 1})); - BOOST_TEST(MosaicSelection({1}, 1.0).materialise(4) == vector({1, 1, 1, 1})); - BOOST_TEST(MosaicSelection({1}, 2.0).materialise(4) == vector({1, 1, 1, 1, 1, 1, 1, 1})); - BOOST_TEST(MosaicSelection({1}, 1.0).materialise(2) == vector({1, 1})); - - BOOST_TEST(MosaicSelection({0, 1}, 0.5).materialise(4) == vector({0, 1})); - BOOST_TEST(MosaicSelection({0, 1}, 1.0).materialise(4) == vector({0, 1, 0, 1})); - BOOST_TEST(MosaicSelection({0, 1}, 2.0).materialise(4) == vector({0, 1, 0, 1, 0, 1, 0, 1})); - BOOST_TEST(MosaicSelection({0, 1}, 1.0).materialise(2) == vector({0, 1})); - - BOOST_TEST(MosaicSelection({3, 2, 1, 0}, 0.5).materialise(4) == vector({3, 2})); - BOOST_TEST(MosaicSelection({3, 2, 1, 0}, 1.0).materialise(4) == vector({3, 2, 1, 0})); - BOOST_TEST(MosaicSelection({3, 2, 1, 0}, 2.0).materialise(4) == vector({3, 2, 1, 0, 3, 2, 1, 0})); - BOOST_TEST(MosaicSelection({1, 0, 1, 0}, 1.0).materialise(2) == vector({1, 0})); + BOOST_TEST(MosaicSelection({1}, 0.5).materialise(4) == std::vector({1, 1})); + BOOST_TEST(MosaicSelection({1}, 1.0).materialise(4) == std::vector({1, 1, 1, 1})); + BOOST_TEST(MosaicSelection({1}, 2.0).materialise(4) == std::vector({1, 1, 1, 1, 1, 1, 1, 1})); + BOOST_TEST(MosaicSelection({1}, 1.0).materialise(2) == std::vector({1, 1})); + + BOOST_TEST(MosaicSelection({0, 1}, 0.5).materialise(4) == std::vector({0, 1})); + BOOST_TEST(MosaicSelection({0, 1}, 1.0).materialise(4) == std::vector({0, 1, 0, 1})); + BOOST_TEST(MosaicSelection({0, 1}, 2.0).materialise(4) == std::vector({0, 1, 0, 1, 0, 1, 0, 1})); + BOOST_TEST(MosaicSelection({0, 1}, 1.0).materialise(2) == std::vector({0, 1})); + + BOOST_TEST(MosaicSelection({3, 2, 1, 0}, 0.5).materialise(4) == std::vector({3, 2})); + BOOST_TEST(MosaicSelection({3, 2, 1, 0}, 1.0).materialise(4) == std::vector({3, 2, 1, 0})); + BOOST_TEST(MosaicSelection({3, 2, 1, 0}, 2.0).materialise(4) == std::vector({3, 2, 1, 0, 3, 2, 1, 0})); + BOOST_TEST(MosaicSelection({1, 0, 1, 0}, 1.0).materialise(2) == std::vector({1, 0})); } BOOST_AUTO_TEST_CASE(materialise_should_round_indices) { - BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 0.49).materialise(5) == vector({4, 3})); - BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 0.50).materialise(5) == vector({4, 3, 2})); - BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 0.51).materialise(5) == vector({4, 3, 2})); + BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 0.49).materialise(5) == std::vector({4, 3})); + BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 0.50).materialise(5) == std::vector({4, 3, 2})); + BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 0.51).materialise(5) == std::vector({4, 3, 2})); } BOOST_AUTO_TEST_CASE(materialise_should_handle_empty_collections) @@ -132,10 +131,10 @@ BOOST_AUTO_TEST_CASE(materialise_should_handle_empty_selections) BOOST_AUTO_TEST_CASE(materialise_should_clamp_indices_at_collection_size) { - BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 1.0).materialise(4) == vector({3, 3, 2, 1})); - BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 2.0).materialise(3) == vector({2, 2, 2, 1, 0, 2})); - BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 1.0).materialise(1) == vector({0})); - BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 7.0).materialise(1) == vector({0, 0, 0, 0, 0, 0, 0})); + BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 1.0).materialise(4) == std::vector({3, 3, 2, 1})); + BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 2.0).materialise(3) == std::vector({2, 2, 2, 1, 0, 2})); + BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 1.0).materialise(1) == std::vector({0})); + BOOST_TEST(MosaicSelection({4, 3, 2, 1, 0}, 7.0).materialise(1) == std::vector({0, 0, 0, 0, 0, 0, 0})); } BOOST_AUTO_TEST_SUITE_END() @@ -150,17 +149,17 @@ BOOST_AUTO_TEST_CASE(materialise_should_return_random_values_with_equal_probabil constexpr double variance = (collectionSize * collectionSize - 1) / 12.0; SimulationRNG::reset(1); - vector samples = RandomSelection(selectionSize).materialise(collectionSize); + std::vector samples = RandomSelection(selectionSize).materialise(collectionSize); - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(materialise_should_return_only_values_that_can_be_used_as_collection_indices) { const size_t collectionSize = 200; - vector indices = RandomSelection(0.5).materialise(collectionSize); + std::vector indices = RandomSelection(0.5).materialise(collectionSize); BOOST_TEST(indices.size() == 100); BOOST_TEST(all_of(indices.begin(), indices.end(), [&](auto const& index){ return index <= collectionSize; })); @@ -214,20 +213,20 @@ BOOST_AUTO_TEST_CASE(materialise_should_return_random_values_with_equal_probabil constexpr double variance = selectionChance * (1 - selectionChance); SimulationRNG::reset(1); - auto indices = convertContainer>(RandomSubset(selectionChance).materialise(collectionSize)); + auto indices = convertContainer>(RandomSubset(selectionChance).materialise(collectionSize)); - vector bernoulliTrials(collectionSize); + std::vector bernoulliTrials(collectionSize); for (size_t i = 0; i < collectionSize; ++i) bernoulliTrials[i] = double(indices.count(i)); - BOOST_TEST(abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(bernoulliTrials) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(materialise_should_return_only_values_that_can_be_used_as_collection_indices) { const size_t collectionSize = 200; - vector indices = RandomSubset(0.5).materialise(collectionSize); + std::vector indices = RandomSubset(0.5).materialise(collectionSize); BOOST_TEST(all_of(indices.begin(), indices.end(), [&](auto const& index){ return index <= collectionSize; })); } @@ -235,7 +234,7 @@ BOOST_AUTO_TEST_CASE(materialise_should_return_only_values_that_can_be_used_as_c BOOST_AUTO_TEST_CASE(materialise_should_return_indices_in_the_same_order_they_are_in_the_container) { const size_t collectionSize = 200; - vector indices = RandomSubset(0.5).materialise(collectionSize); + std::vector indices = RandomSubset(0.5).materialise(collectionSize); for (size_t i = 1; i < indices.size(); ++i) BOOST_TEST(indices[i - 1] < indices[i]); diff --git a/test/yulPhaser/SimulationRNG.cpp b/test/yulPhaser/SimulationRNG.cpp index d6e8c3a81150..ff91846e30d8 100644 --- a/test/yulPhaser/SimulationRNG.cpp +++ b/test/yulPhaser/SimulationRNG.cpp @@ -24,8 +24,6 @@ #include -using namespace std; - namespace solidity::phaser::test { @@ -43,12 +41,12 @@ BOOST_AUTO_TEST_CASE(bernoulliTrial_should_produce_samples_with_right_expected_v constexpr double expectedValue = successProbability; constexpr double variance = successProbability * (1 - successProbability); - vector samples; + std::vector samples; for (uint32_t i = 0; i < numSamples; ++i) samples.push_back(static_cast(SimulationRNG::bernoulliTrial(successProbability))); - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(bernoulliTrial_can_be_reset) @@ -57,21 +55,21 @@ BOOST_AUTO_TEST_CASE(bernoulliTrial_can_be_reset) constexpr double successProbability = 0.4; SimulationRNG::reset(1); - vector samples1; + std::vector samples1; for (uint32_t i = 0; i < numSamples; ++i) samples1.push_back(static_cast(SimulationRNG::bernoulliTrial(successProbability))); - vector samples2; + std::vector samples2; for (uint32_t i = 0; i < numSamples; ++i) samples2.push_back(static_cast(SimulationRNG::bernoulliTrial(successProbability))); SimulationRNG::reset(1); - vector samples3; + std::vector samples3; for (uint32_t i = 0; i < numSamples; ++i) samples3.push_back(static_cast(SimulationRNG::bernoulliTrial(successProbability))); SimulationRNG::reset(2); - vector samples4; + std::vector samples4; for (uint32_t i = 0; i < numSamples; ++i) samples4.push_back(static_cast(SimulationRNG::bernoulliTrial(successProbability))); @@ -95,12 +93,12 @@ BOOST_AUTO_TEST_CASE(uniformInt_returns_different_values_when_called_multiple_ti constexpr double expectedValue = (minValue + maxValue) / 2.0; constexpr double variance = ((maxValue - minValue + 1) * (maxValue - minValue + 1) - 1) / 12.0; - vector samples; + std::vector samples; for (uint32_t i = 0; i < numSamples; ++i) samples.push_back(SimulationRNG::uniformInt(minValue, maxValue)); - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(uniformInt_can_be_reset) @@ -110,21 +108,21 @@ BOOST_AUTO_TEST_CASE(uniformInt_can_be_reset) constexpr uint32_t maxValue = 80; SimulationRNG::reset(1); - vector samples1; + std::vector samples1; for (uint32_t i = 0; i < numSamples; ++i) samples1.push_back(SimulationRNG::uniformInt(minValue, maxValue)); - vector samples2; + std::vector samples2; for (uint32_t i = 0; i < numSamples; ++i) samples2.push_back(SimulationRNG::uniformInt(minValue, maxValue)); SimulationRNG::reset(1); - vector samples3; + std::vector samples3; for (uint32_t i = 0; i < numSamples; ++i) samples3.push_back(SimulationRNG::uniformInt(minValue, maxValue)); SimulationRNG::reset(2); - vector samples4; + std::vector samples4; for (uint32_t i = 0; i < numSamples; ++i) samples4.push_back(SimulationRNG::uniformInt(minValue, maxValue)); @@ -148,12 +146,12 @@ BOOST_AUTO_TEST_CASE(binomialInt_should_produce_samples_with_right_expected_valu constexpr double expectedValue = numTrials * successProbability; constexpr double variance = numTrials * successProbability * (1 - successProbability); - vector samples; + std::vector samples; for (uint32_t i = 0; i < numSamples; ++i) samples.push_back(SimulationRNG::binomialInt(numTrials, successProbability)); - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(std::abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(std::abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(binomialInt_can_be_reset) @@ -163,21 +161,21 @@ BOOST_AUTO_TEST_CASE(binomialInt_can_be_reset) constexpr double successProbability = 0.6; SimulationRNG::reset(1); - vector samples1; + std::vector samples1; for (uint32_t i = 0; i < numSamples; ++i) samples1.push_back(SimulationRNG::binomialInt(numTrials, successProbability)); - vector samples2; + std::vector samples2; for (uint32_t i = 0; i < numSamples; ++i) samples2.push_back(SimulationRNG::binomialInt(numTrials, successProbability)); SimulationRNG::reset(1); - vector samples3; + std::vector samples3; for (uint32_t i = 0; i < numSamples; ++i) samples3.push_back(SimulationRNG::binomialInt(numTrials, successProbability)); SimulationRNG::reset(2); - vector samples4; + std::vector samples4; for (uint32_t i = 0; i < numSamples; ++i) samples4.push_back(SimulationRNG::binomialInt(numTrials, successProbability)); diff --git a/test/yulPhaser/TestHelpers.cpp b/test/yulPhaser/TestHelpers.cpp index 50afd70a3eb3..d75b63b4ac8b 100644 --- a/test/yulPhaser/TestHelpers.cpp +++ b/test/yulPhaser/TestHelpers.cpp @@ -22,22 +22,21 @@ #include -using namespace std; using namespace solidity; using namespace solidity::yul; using namespace solidity::phaser; using namespace solidity::phaser::test; -function phaser::test::wholeChromosomeReplacement(Chromosome _newChromosome) +std::function phaser::test::wholeChromosomeReplacement(Chromosome _newChromosome) { return [_newChromosome = std::move(_newChromosome)](Chromosome const&) { return _newChromosome; }; } -function phaser::test::geneSubstitution(size_t _geneIndex, string _geneValue) +std::function phaser::test::geneSubstitution(size_t _geneIndex, std::string _geneValue) { return [=](Chromosome const& _chromosome) { - vector newGenes = _chromosome.optimisationSteps(); + std::vector newGenes = _chromosome.optimisationSteps(); assert(_geneIndex < newGenes.size()); newGenes[_geneIndex] = _geneValue; @@ -45,18 +44,18 @@ function phaser::test::geneSubstitution(size_t _geneIndex, string _gen }; } -vector phaser::test::chromosomeLengths(Population const& _population) +std::vector phaser::test::chromosomeLengths(Population const& _population) { - vector lengths; + std::vector lengths; for (auto const& individual: _population.individuals()) lengths.push_back(individual.chromosome.length()); return lengths; } -map phaser::test::enumerateOptmisationSteps() +std::map phaser::test::enumerateOptmisationSteps() { - map stepIndices; + std::map stepIndices; size_t i = 0; for (auto const& nameAndAbbreviation: OptimiserSuite::stepNameToAbbreviationMap()) stepIndices.insert({nameAndAbbreviation.first, i++}); @@ -67,29 +66,29 @@ map phaser::test::enumerateOptmisationSteps() size_t phaser::test::countDifferences(Chromosome const& _chromosome1, Chromosome const& _chromosome2) { size_t count = 0; - for (size_t i = 0; i < min(_chromosome1.length(), _chromosome2.length()); ++i) + for (size_t i = 0; i < std::min(_chromosome1.length(), _chromosome2.length()); ++i) if (_chromosome1.optimisationSteps()[i] != _chromosome2.optimisationSteps()[i]) ++count; - return count + static_cast(abs( + return count + static_cast(std::abs( static_cast(_chromosome1.length()) - static_cast(_chromosome2.length()) )); } -string phaser::test::stripWhitespace(string const& input) +std::string phaser::test::stripWhitespace(std::string const& input) { - regex whitespaceRegex("\\s+"); + std::regex whitespaceRegex("\\s+"); return regex_replace(input, whitespaceRegex, ""); } -size_t phaser::test::countSubstringOccurrences(string const& _inputString, string const& _substring) +size_t phaser::test::countSubstringOccurrences(std::string const& _inputString, std::string const& _substring) { assert(_substring.size() > 0); size_t count = 0; size_t lastOccurrence = 0; - while ((lastOccurrence = _inputString.find(_substring, lastOccurrence)) != string::npos) + while ((lastOccurrence = _inputString.find(_substring, lastOccurrence)) != std::string::npos) { ++count; lastOccurrence += _substring.size(); diff --git a/test/yulPhaser/TestHelpersTest.cpp b/test/yulPhaser/TestHelpersTest.cpp index 89b98ecad7aa..23be74230cca 100644 --- a/test/yulPhaser/TestHelpersTest.cpp +++ b/test/yulPhaser/TestHelpersTest.cpp @@ -24,7 +24,6 @@ #include -using namespace std; using namespace solidity::yul; using namespace boost::test_tools; @@ -43,7 +42,7 @@ BOOST_AUTO_TEST_CASE(ChromosomeLengthMetric_evaluate_should_return_chromosome_le BOOST_AUTO_TEST_CASE(wholeChromosomeReplacement_should_replace_whole_chromosome_with_another) { - function mutation = wholeChromosomeReplacement(Chromosome("aaa")); + std::function mutation = wholeChromosomeReplacement(Chromosome("aaa")); BOOST_TEST(mutation(Chromosome("ccc")) == Chromosome("aaa")); } @@ -51,22 +50,22 @@ BOOST_AUTO_TEST_CASE(geneSubstitution_should_change_a_single_gene_at_a_given_ind { Chromosome chromosome("aaccff"); - function mutation1 = geneSubstitution(0, chromosome.optimisationSteps()[5]); + std::function mutation1 = geneSubstitution(0, chromosome.optimisationSteps()[5]); BOOST_TEST(mutation1(chromosome) == Chromosome("faccff")); - function mutation2 = geneSubstitution(5, chromosome.optimisationSteps()[0]); + std::function mutation2 = geneSubstitution(5, chromosome.optimisationSteps()[0]); BOOST_TEST(mutation2(chromosome) == Chromosome("aaccfa")); } BOOST_AUTO_TEST_CASE(chromosomeLengths_should_return_lengths_of_all_chromosomes_in_a_population) { - shared_ptr fitnessMetric = make_shared(); + std::shared_ptr fitnessMetric = std::make_shared(); Population population1(fitnessMetric, {Chromosome(), Chromosome("a"), Chromosome("aa"), Chromosome("aaa")}); - BOOST_TEST((chromosomeLengths(population1) == vector{0, 1, 2, 3})); + BOOST_TEST((chromosomeLengths(population1) == std::vector{0, 1, 2, 3})); Population population2(fitnessMetric); - BOOST_TEST((chromosomeLengths(population2) == vector{})); + BOOST_TEST((chromosomeLengths(population2) == std::vector{})); } BOOST_AUTO_TEST_CASE(countDifferences_should_return_zero_for_identical_chromosomes) @@ -99,11 +98,11 @@ BOOST_AUTO_TEST_CASE(countDifferences_should_count_missing_characters_as_differe BOOST_AUTO_TEST_CASE(enumerateOptimisationSteps_should_assing_indices_to_all_available_optimisation_steps) { - map stepsAndAbbreviations = OptimiserSuite::stepNameToAbbreviationMap(); - map stepsAndIndices = enumerateOptmisationSteps(); + std::map stepsAndAbbreviations = OptimiserSuite::stepNameToAbbreviationMap(); + std::map stepsAndIndices = enumerateOptmisationSteps(); BOOST_TEST(stepsAndIndices.size() == stepsAndAbbreviations.size()); - set stepsSoFar; + std::set stepsSoFar; for (auto& [name, index]: stepsAndIndices) { BOOST_TEST(index >= 0);