mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into breaking
This commit is contained in:
commit
0801c48e11
@ -214,6 +214,16 @@ defaults:
|
|||||||
command: ./test/lsp.py ./build/solc/solc
|
command: ./test/lsp.py ./build/solc/solc
|
||||||
- gitter_notify_failure_unless_pr
|
- gitter_notify_failure_unless_pr
|
||||||
|
|
||||||
|
- steps_build: &steps_build
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: *run_build
|
||||||
|
- store_artifacts: *artifacts_solc
|
||||||
|
- store_artifacts: *artifact_solidity_upgrade
|
||||||
|
- store_artifacts: *artifact_yul_phaser
|
||||||
|
- persist_to_workspace: *artifacts_executables
|
||||||
|
- gitter_notify_failure_unless_pr
|
||||||
|
|
||||||
- steps_soltest_all: &steps_soltest_all
|
- steps_soltest_all: &steps_soltest_all
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
@ -234,6 +244,14 @@ defaults:
|
|||||||
- store_artifacts: *artifacts_test_results
|
- store_artifacts: *artifacts_test_results
|
||||||
- gitter_notify_failure_unless_pr
|
- gitter_notify_failure_unless_pr
|
||||||
|
|
||||||
|
- steps_install_dependencies_osx: &steps_install_dependencies_osx
|
||||||
|
steps:
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }}
|
||||||
|
- attach_workspace:
|
||||||
|
at: .
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# Base Image Templates
|
# Base Image Templates
|
||||||
|
|
||||||
@ -565,7 +583,7 @@ defaults:
|
|||||||
project: uniswap
|
project: uniswap
|
||||||
binary_type: native
|
binary_type: native
|
||||||
nodejs_version: '16'
|
nodejs_version: '16'
|
||||||
- job_native_test_prb_math: &job_native_test_prb_math
|
- job_native_test_ext_prb_math: &job_native_test_ext_prb_math
|
||||||
<<: *workflow_ubuntu2004_static
|
<<: *workflow_ubuntu2004_static
|
||||||
name: t_native_test_ext_prb_math
|
name: t_native_test_ext_prb_math
|
||||||
project: prb-math
|
project: prb-math
|
||||||
@ -586,6 +604,15 @@ defaults:
|
|||||||
nodejs_version: '14'
|
nodejs_version: '14'
|
||||||
resource_class: medium
|
resource_class: medium
|
||||||
|
|
||||||
|
- job_b_ubu_asan_clang: &job_b_ubu_asan_clang
|
||||||
|
<<: *workflow_trigger_on_tags
|
||||||
|
name: b_ubu_asan_clang
|
||||||
|
cmake_options: -DSANITIZE=address
|
||||||
|
- job_b_ubu_ubsan_clang: &job_b_ubu_ubsan_clang
|
||||||
|
<<: *workflow_trigger_on_tags
|
||||||
|
name: b_ubu_ubsan_clang
|
||||||
|
cmake_options: -DSANITIZE=address
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
@ -731,14 +758,7 @@ jobs:
|
|||||||
# this runs 2x faster on xlarge but takes 4x more resources (compared to medium).
|
# this runs 2x faster on xlarge but takes 4x more resources (compared to medium).
|
||||||
# Enough other jobs depend on it that it's worth it though.
|
# Enough other jobs depend on it that it's worth it though.
|
||||||
<<: *base_ubuntu2004_xlarge
|
<<: *base_ubuntu2004_xlarge
|
||||||
steps:
|
<<: *steps_build
|
||||||
- checkout
|
|
||||||
- run: *run_build
|
|
||||||
- store_artifacts: *artifacts_solc
|
|
||||||
- store_artifacts: *artifact_solidity_upgrade
|
|
||||||
- store_artifacts: *artifact_yul_phaser
|
|
||||||
- persist_to_workspace: *artifacts_executables
|
|
||||||
- gitter_notify_failure_unless_pr
|
|
||||||
|
|
||||||
# x64 ASAN build, for testing for memory related bugs
|
# x64 ASAN build, for testing for memory related bugs
|
||||||
b_ubu_asan: &b_ubu_asan
|
b_ubu_asan: &b_ubu_asan
|
||||||
@ -748,12 +768,7 @@ jobs:
|
|||||||
CMAKE_OPTIONS: -DSANITIZE=address
|
CMAKE_OPTIONS: -DSANITIZE=address
|
||||||
MAKEFLAGS: -j 3
|
MAKEFLAGS: -j 3
|
||||||
CMAKE_BUILD_TYPE: Release
|
CMAKE_BUILD_TYPE: Release
|
||||||
steps:
|
<<: *steps_build
|
||||||
- checkout
|
|
||||||
- run: *run_build
|
|
||||||
- store_artifacts: *artifacts_solc
|
|
||||||
- persist_to_workspace: *artifacts_executables
|
|
||||||
- gitter_notify_failure_unless_pr
|
|
||||||
|
|
||||||
b_ubu_clang: &b_ubu_clang
|
b_ubu_clang: &b_ubu_clang
|
||||||
<<: *base_ubuntu2004_clang_large
|
<<: *base_ubuntu2004_clang_large
|
||||||
@ -762,42 +777,21 @@ jobs:
|
|||||||
CC: clang
|
CC: clang
|
||||||
CXX: clang++
|
CXX: clang++
|
||||||
MAKEFLAGS: -j 10
|
MAKEFLAGS: -j 10
|
||||||
steps:
|
<<: *steps_build
|
||||||
- checkout
|
|
||||||
- run: *run_build
|
|
||||||
- store_artifacts: *artifacts_solc
|
|
||||||
- persist_to_workspace: *artifacts_executables
|
|
||||||
- gitter_notify_failure_unless_pr
|
|
||||||
|
|
||||||
b_ubu_asan_clang: &b_ubu_asan_clang
|
b_ubu_san_clang:
|
||||||
# This runs a bit faster on large and xlarge but on nightly efficiency matters more.
|
# This runs a bit faster on large and xlarge but on nightly efficiency matters more.
|
||||||
|
parameters:
|
||||||
|
cmake_options:
|
||||||
|
type: string
|
||||||
<<: *base_ubuntu2004_clang
|
<<: *base_ubuntu2004_clang
|
||||||
environment:
|
environment:
|
||||||
|
TERM: xterm
|
||||||
CC: clang
|
CC: clang
|
||||||
CXX: clang++
|
CXX: clang++
|
||||||
CMAKE_OPTIONS: -DSANITIZE=address
|
|
||||||
MAKEFLAGS: -j 3
|
MAKEFLAGS: -j 3
|
||||||
steps:
|
CMAKE_OPTIONS: << parameters.cmake_options >>
|
||||||
- checkout
|
<<: *steps_build
|
||||||
- run: *run_build
|
|
||||||
- store_artifacts: *artifacts_solc
|
|
||||||
- persist_to_workspace: *artifacts_executables
|
|
||||||
- gitter_notify_failure_unless_pr
|
|
||||||
|
|
||||||
b_ubu_ubsan_clang: &b_ubu_ubsan_clang
|
|
||||||
# This runs a bit faster on large and xlarge but on nightly efficiency matters more.
|
|
||||||
<<: *base_ubuntu2004_clang
|
|
||||||
environment:
|
|
||||||
CC: clang
|
|
||||||
CXX: clang++
|
|
||||||
CMAKE_OPTIONS: -DSANITIZE=undefined
|
|
||||||
MAKEFLAGS: -j 3
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
- run: *run_build
|
|
||||||
- store_artifacts: *artifacts_solc
|
|
||||||
- persist_to_workspace: *artifacts_executables
|
|
||||||
- gitter_notify_failure_unless_pr
|
|
||||||
|
|
||||||
b_ubu_release: &b_ubu_release
|
b_ubu_release: &b_ubu_release
|
||||||
<<: *b_ubu
|
<<: *b_ubu
|
||||||
@ -949,7 +943,7 @@ jobs:
|
|||||||
- build/test/tools/solfuzzer
|
- build/test/tools/solfuzzer
|
||||||
- gitter_notify_failure_unless_pr
|
- gitter_notify_failure_unless_pr
|
||||||
|
|
||||||
t_osx_soltest:
|
t_osx_soltest: &t_osx_soltest
|
||||||
<<: *base_osx
|
<<: *base_osx
|
||||||
environment:
|
environment:
|
||||||
EVM: << pipeline.parameters.evm-version >>
|
EVM: << pipeline.parameters.evm-version >>
|
||||||
@ -957,11 +951,9 @@ jobs:
|
|||||||
TERM: xterm
|
TERM: xterm
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- when:
|
||||||
keys:
|
condition: true
|
||||||
- dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }}
|
<<: *steps_install_dependencies_osx
|
||||||
- attach_workspace:
|
|
||||||
at: .
|
|
||||||
- run: *run_soltest
|
- run: *run_soltest
|
||||||
- store_test_results: *store_test_results
|
- store_test_results: *store_test_results
|
||||||
- store_artifacts: *artifacts_test_results
|
- store_artifacts: *artifacts_test_results
|
||||||
@ -971,11 +963,9 @@ jobs:
|
|||||||
<<: *base_osx
|
<<: *base_osx
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- when:
|
||||||
keys:
|
condition: true
|
||||||
- dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }}
|
<<: *steps_install_dependencies_osx
|
||||||
- attach_workspace:
|
|
||||||
at: .
|
|
||||||
- run: *run_cmdline_tests
|
- run: *run_cmdline_tests
|
||||||
- store_artifacts: *artifacts_test_results
|
- store_artifacts: *artifacts_test_results
|
||||||
- gitter_notify_failure_unless_pr
|
- gitter_notify_failure_unless_pr
|
||||||
@ -992,10 +982,10 @@ jobs:
|
|||||||
command: |
|
command: |
|
||||||
scripts/ci/build_emscripten.sh
|
scripts/ci/build_emscripten.sh
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: emscripten_build/libsolc/soljson.js
|
path: upload/soljson.js
|
||||||
destination: soljson.js
|
destination: soljson.js
|
||||||
- run: mkdir -p workspace
|
- run: mkdir -p workspace
|
||||||
- run: cp emscripten_build/libsolc/soljson.js workspace/soljson.js
|
- run: cp upload/soljson.js workspace/soljson.js
|
||||||
- run: scripts/get_version.sh > workspace/version.txt
|
- run: scripts/get_version.sh > workspace/version.txt
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: workspace
|
root: workspace
|
||||||
@ -1108,6 +1098,7 @@ jobs:
|
|||||||
parallelism: 20
|
parallelism: 20
|
||||||
environment:
|
environment:
|
||||||
EVM: << pipeline.parameters.evm-version >>
|
EVM: << pipeline.parameters.evm-version >>
|
||||||
|
SOLTEST_FLAGS: --no-smt
|
||||||
<<: *steps_soltest
|
<<: *steps_soltest
|
||||||
|
|
||||||
t_ubu_ubsan_clang_cli:
|
t_ubu_ubsan_clang_cli:
|
||||||
@ -1215,8 +1206,34 @@ jobs:
|
|||||||
name: External <<parameters.project>> tests (native)
|
name: External <<parameters.project>> tests (native)
|
||||||
command: |
|
command: |
|
||||||
test/externalTests/<<parameters.project>>.sh native /tmp/workspace/solc/solc
|
test/externalTests/<<parameters.project>>.sh native /tmp/workspace/solc/solc
|
||||||
|
- store_artifacts:
|
||||||
|
path: reports/externalTests/
|
||||||
|
# persist_to_workspace fails if the directory does not exist and the test script will create
|
||||||
|
# it only if it actually has benchmark results.
|
||||||
|
- run: mkdir -p reports/externalTests/
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: .
|
||||||
|
paths:
|
||||||
|
- reports/externalTests/
|
||||||
- gitter_notify_failure_unless_pr
|
- gitter_notify_failure_unless_pr
|
||||||
|
|
||||||
|
c_ext_benchmarks:
|
||||||
|
<<: *base_node_small
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- attach_workspace:
|
||||||
|
at: .
|
||||||
|
- run:
|
||||||
|
name: Combine benchmark reports
|
||||||
|
command: cat reports/externalTests/benchmark-*.json | scripts/externalTests/merge_benchmarks.sh > reports/externalTests/all-benchmarks.json
|
||||||
|
- run:
|
||||||
|
name: Summarize reports
|
||||||
|
command: cat reports/externalTests/all-benchmarks.json | scripts/externalTests/summarize_benchmarks.sh > reports/externalTests/summarized-benchmarks.json
|
||||||
|
- store_artifacts:
|
||||||
|
path: reports/externalTests/all-benchmarks.json
|
||||||
|
- store_artifacts:
|
||||||
|
path: reports/externalTests/summarized-benchmarks.json
|
||||||
|
|
||||||
b_win: &b_win
|
b_win: &b_win
|
||||||
<<: *base_win_powershell_large
|
<<: *base_win_powershell_large
|
||||||
steps:
|
steps:
|
||||||
@ -1464,9 +1481,27 @@ workflows:
|
|||||||
- t_ems_ext: *job_native_test_ext_pool_together
|
- t_ems_ext: *job_native_test_ext_pool_together
|
||||||
- t_ems_ext: *job_native_test_ext_perpetual_pools
|
- t_ems_ext: *job_native_test_ext_perpetual_pools
|
||||||
- t_ems_ext: *job_native_test_ext_uniswap
|
- t_ems_ext: *job_native_test_ext_uniswap
|
||||||
- t_ems_ext: *job_native_test_prb_math
|
- t_ems_ext: *job_native_test_ext_prb_math
|
||||||
- t_ems_ext: *job_native_test_ext_elementfi
|
- t_ems_ext: *job_native_test_ext_elementfi
|
||||||
|
|
||||||
|
- c_ext_benchmarks:
|
||||||
|
<<: *workflow_trigger_on_tags
|
||||||
|
requires:
|
||||||
|
- t_ems_compile_ext_colony
|
||||||
|
- t_native_compile_ext_gnosis
|
||||||
|
- t_native_test_ext_gnosis_v2
|
||||||
|
- t_native_test_ext_zeppelin
|
||||||
|
- t_native_test_ext_ens
|
||||||
|
- t_native_test_ext_trident
|
||||||
|
- t_native_test_ext_euler
|
||||||
|
- t_native_test_ext_yield_liquidator
|
||||||
|
- t_native_test_ext_bleeps
|
||||||
|
- t_native_test_ext_pool_together
|
||||||
|
- t_native_test_ext_perpetual_pools
|
||||||
|
- t_native_test_ext_uniswap
|
||||||
|
- t_native_test_ext_prb_math
|
||||||
|
- t_native_test_ext_elementfi
|
||||||
|
|
||||||
# Windows build and tests
|
# Windows build and tests
|
||||||
- b_win: *workflow_trigger_on_tags
|
- b_win: *workflow_trigger_on_tags
|
||||||
- b_win_release: *workflow_trigger_on_tags
|
- b_win_release: *workflow_trigger_on_tags
|
||||||
@ -1519,13 +1554,13 @@ workflows:
|
|||||||
|
|
||||||
# ASan build and tests
|
# ASan build and tests
|
||||||
- b_ubu_asan: *workflow_trigger_on_tags
|
- b_ubu_asan: *workflow_trigger_on_tags
|
||||||
- b_ubu_asan_clang: *workflow_trigger_on_tags
|
- b_ubu_san_clang: *job_b_ubu_asan_clang
|
||||||
- t_ubu_asan_soltest: *workflow_ubuntu2004_asan
|
- t_ubu_asan_soltest: *workflow_ubuntu2004_asan
|
||||||
- t_ubu_asan_clang_soltest: *workflow_ubuntu2004_asan_clang
|
- t_ubu_asan_clang_soltest: *workflow_ubuntu2004_asan_clang
|
||||||
- t_ubu_asan_cli: *workflow_ubuntu2004_asan
|
- t_ubu_asan_cli: *workflow_ubuntu2004_asan
|
||||||
|
|
||||||
# UBSan build and tests
|
# UBSan build and tests
|
||||||
- b_ubu_ubsan_clang: *workflow_trigger_on_tags
|
- b_ubu_san_clang: *job_b_ubu_ubsan_clang
|
||||||
- t_ubu_ubsan_clang_soltest: *workflow_ubuntu2004_ubsan_clang
|
- t_ubu_ubsan_clang_soltest: *workflow_ubuntu2004_ubsan_clang
|
||||||
- t_ubu_ubsan_clang_cli: *workflow_ubuntu2004_ubsan_clang
|
- t_ubu_ubsan_clang_cli: *workflow_ubuntu2004_ubsan_clang
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ include(EthPolicy)
|
|||||||
eth_policy()
|
eth_policy()
|
||||||
|
|
||||||
# project name and version should be set after cmake_policy CMP0048
|
# project name and version should be set after cmake_policy CMP0048
|
||||||
set(PROJECT_VERSION "0.8.12")
|
set(PROJECT_VERSION "0.8.13")
|
||||||
# OSX target needed in order to support std::visit
|
# OSX target needed in order to support std::visit
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
|
||||||
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
|
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
|
||||||
|
34
Changelog.md
34
Changelog.md
@ -9,30 +9,46 @@ Breaking changes:
|
|||||||
* Commandline Interface: Assembler mode no longer enables all outputs by default.
|
* Commandline Interface: Assembler mode no longer enables all outputs by default.
|
||||||
|
|
||||||
|
|
||||||
### 0.8.12 (unreleased)
|
### 0.8.13 (unreleased)
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
* General: Support ``ContractName.functionName`` for ``abi.encodeCall``, in addition to external function pointers.
|
|
||||||
* General: Add equality-comparison operators for external function types.
|
|
||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 0.8.12 (2022-02-16)
|
||||||
|
|
||||||
|
Language Features:
|
||||||
|
* General: Add equality-comparison operators for external function types.
|
||||||
|
* General: Support ``ContractName.functionName`` for ``abi.encodeCall``, in addition to external function pointers.
|
||||||
|
|
||||||
|
|
||||||
|
Compiler Features:
|
||||||
|
* Commandline Interface: Event and error signatures are also returned when using ``--hashes``.
|
||||||
* Yul Optimizer: Remove ``mstore`` and ``sstore`` operations if the slot already contains the same value.
|
* Yul Optimizer: Remove ``mstore`` and ``sstore`` operations if the slot already contains the same value.
|
||||||
* Yul: Emit immutable references for pure yul code when requested.
|
* Yul: Emit immutable references for pure yul code when requested.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
* Antlr Grammar: Allow builtin names in ``yulPath`` to support ``.address`` in function pointers.
|
* Antlr Grammar: Allow builtin names in ``yulPath`` to support ``.address`` in function pointers.
|
||||||
* Code Generator: Fix ICE when accessing the members of external functions occupying more than two stack slots.
|
* Code Generator: Fix internal error when accessing the members of external functions occupying more than two stack slots.
|
||||||
* Code Generator: Fix ICE when doing an explicit conversion from ``string calldata`` to ``bytes``.
|
* Code Generator: Fix internal error when doing an explicit conversion from ``string calldata`` to ``bytes``.
|
||||||
* Control Flow Graph: Perform proper virtual lookup for modifiers for uninitialized variable and unreachable code analysis.
|
* Control Flow Graph: Perform proper virtual lookup for modifiers for uninitialized variable and unreachable code analysis.
|
||||||
|
* General: ``string.concat`` now properly takes strings as arguments and returns ``string memory``. It was accidentally introduced as a copy of ``bytes.concat`` before.
|
||||||
* Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the derived contract contains immutable variables.
|
* Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the derived contract contains immutable variables.
|
||||||
|
* Inheritance: Consider functions in all ancestors during override analysis.
|
||||||
* IR Generator: Add missing cleanup during the conversion of fixed bytes types to smaller fixed bytes types.
|
* IR Generator: Add missing cleanup during the conversion of fixed bytes types to smaller fixed bytes types.
|
||||||
* IR Generator: Add missing cleanup for indexed event arguments of value type.
|
* IR Generator: Add missing cleanup for indexed event arguments of value type.
|
||||||
* IR Generator: Fix internal error when copying reference types in calldata and storage to struct or array members in memory.
|
* IR Generator: Fix internal error when copying reference types in calldata and storage to struct or array members in memory.
|
||||||
* IR Generator: Fix IR syntax error when copying storage arrays of structs containing functions.
|
* IR Generator: Fix IR syntax error when copying storage arrays of structs containing functions.
|
||||||
* Natspec: Fix ICE when overriding a struct getter with a Natspec-documented return value and the name in the struct is different.
|
* Natspec: Fix internal error when overriding a struct getter with a Natspec-documented return value and the name in the struct is different.
|
||||||
* TypeChecker: Fix ICE when a constant variable declaration forward references a struct.
|
* Type Checker: Fix internal error when a constant variable declaration forward references a struct.
|
||||||
|
* Yul EVM Code Transform: Improved stack shuffling in corner cases.
|
||||||
|
|
||||||
|
|
||||||
Solc-Js:
|
Solc-Js:
|
||||||
@ -40,6 +56,10 @@ Solc-Js:
|
|||||||
* The code has been ported to TypeScript.
|
* The code has been ported to TypeScript.
|
||||||
|
|
||||||
|
|
||||||
|
Build System:
|
||||||
|
* Emscripten builds store the embedded WebAssembly binary in LZ4 compressed format and transparently decompress on loading.
|
||||||
|
|
||||||
|
|
||||||
### 0.8.11 (2021-12-20)
|
### 0.8.11 (2021-12-20)
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
|
@ -142,8 +142,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
|
|||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM=1")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM=1")
|
||||||
# Set webassembly build to synchronous loading.
|
# Set webassembly build to synchronous loading.
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM_ASYNC_COMPILATION=0")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM_ASYNC_COMPILATION=0")
|
||||||
# Output a single js file with the wasm binary embedded as base64 string.
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s SINGLE_FILE=1")
|
|
||||||
# Allow new functions to be added to the wasm module via addFunction.
|
# Allow new functions to be added to the wasm module via addFunction.
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_TABLE_GROWTH=1")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_TABLE_GROWTH=1")
|
||||||
# Disable warnings about not being pure asm.js due to memory growth.
|
# Disable warnings about not being pure asm.js due to memory growth.
|
||||||
@ -153,8 +151,11 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
|
|||||||
|
|
||||||
# The major alternative compiler to GCC/Clang is Microsoft's Visual C++ compiler, only available on Windows.
|
# The major alternative compiler to GCC/Clang is Microsoft's Visual C++ compiler, only available on Windows.
|
||||||
elseif (DEFINED MSVC)
|
elseif (DEFINED MSVC)
|
||||||
|
# Remove NDEBUG from RELWITHDEBINFO (to enable asserts)
|
||||||
|
# CMAKE_CXX_FLAGS_RELWITHDEBINFO for GCC/Clang does not include NDEBUG
|
||||||
|
string(REPLACE "/DNDEBUG" " " CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||||
|
|
||||||
add_compile_options(/MP) # enable parallel compilation
|
add_compile_options(/MP) # enable parallel compilation
|
||||||
add_compile_options(/EHsc) # specify Exception Handling Model in msvc
|
add_compile_options(/EHsc) # specify Exception Handling Model in msvc
|
||||||
add_compile_options(/WX) # enable warnings-as-errors
|
add_compile_options(/WX) # enable warnings-as-errors
|
||||||
add_compile_options(/wd4068) # disable unknown pragma warning (4068)
|
add_compile_options(/wd4068) # disable unknown pragma warning (4068)
|
||||||
|
@ -137,6 +137,36 @@ evmc:
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
|
mini-lz4:
|
||||||
|
The file scripts/ci/mini-lz4.js is derived from the emscripten adaptation of
|
||||||
|
node-lz4 and licensed under the following terms:
|
||||||
|
|
||||||
|
Copyright (c) 2012 Pierre Curto
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
base64:
|
||||||
|
The file scripts/ci/base64DecToArr.js is derived from a code example
|
||||||
|
in the MDN Web Docs, which permits use under CC0 terms:
|
||||||
|
|
||||||
|
Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
|
||||||
All other code is licensed under GPL version 3:
|
All other code is licensed under GPL version 3:
|
||||||
|
|
||||||
|
@ -1552,6 +1552,10 @@
|
|||||||
"bugs": [],
|
"bugs": [],
|
||||||
"released": "2021-12-20"
|
"released": "2021-12-20"
|
||||||
},
|
},
|
||||||
|
"0.8.12": {
|
||||||
|
"bugs": [],
|
||||||
|
"released": "2022-02-16"
|
||||||
|
},
|
||||||
"0.8.2": {
|
"0.8.2": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
"SignedImmutables",
|
"SignedImmutables",
|
||||||
|
@ -86,6 +86,8 @@ Global Variables
|
|||||||
to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``
|
to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``
|
||||||
- ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of
|
- ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of
|
||||||
arguments to one byte array<bytes-concat>`
|
arguments to one byte array<bytes-concat>`
|
||||||
|
- ``string.concat(...) returns (string memory)``: :ref:`Concatenates variable number of
|
||||||
|
arguments to one string array<string-concat>`
|
||||||
- ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/eip-1559>`_)
|
- ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/eip-1559>`_)
|
||||||
- ``block.chainid`` (``uint``): current chain id
|
- ``block.chainid`` (``uint``): current chain id
|
||||||
- ``block.coinbase`` (``address payable``): current block miner's address
|
- ``block.coinbase`` (``address payable``): current block miner's address
|
||||||
|
@ -94,6 +94,13 @@ dependencies (`evmone <https://github.com/ethereum/evmone/releases>`_,
|
|||||||
On macOS some of the testing scripts expect GNU coreutils to be installed.
|
On macOS some of the testing scripts expect GNU coreutils to be installed.
|
||||||
This can be easiest accomplished using Homebrew: ``brew install coreutils``.
|
This can be easiest accomplished using Homebrew: ``brew install coreutils``.
|
||||||
|
|
||||||
|
On Windows systems make sure that you have a privilege to create symlinks,
|
||||||
|
otherwise several tests may fail.
|
||||||
|
Administrators should have that privilege, but you may also
|
||||||
|
`grant it to other users <https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links#policy-management>`_
|
||||||
|
or
|
||||||
|
`enable Developer Mode <https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development>`_.
|
||||||
|
|
||||||
Running the Tests
|
Running the Tests
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
@ -130,9 +130,12 @@ of votes.
|
|||||||
|
|
||||||
// Since `sender` is a reference, this
|
// Since `sender` is a reference, this
|
||||||
// modifies `voters[msg.sender].voted`
|
// modifies `voters[msg.sender].voted`
|
||||||
|
Voter storage delegate_ = voters[to];
|
||||||
|
|
||||||
|
// Voters cannot delegate to wallets that cannot vote.
|
||||||
|
require(delegate_.weight >= 1);
|
||||||
sender.voted = true;
|
sender.voted = true;
|
||||||
sender.delegate = to;
|
sender.delegate = to;
|
||||||
Voter storage delegate_ = voters[to];
|
|
||||||
if (delegate_.voted) {
|
if (delegate_.voted) {
|
||||||
// If the delegate already voted,
|
// If the delegate already voted,
|
||||||
// directly add to the number of votes
|
// directly add to the number of votes
|
||||||
|
@ -24,7 +24,7 @@ actual release. They are not meant for production use.
|
|||||||
|
|
||||||
When deploying contracts, you should use the latest released version of Solidity. This
|
When deploying contracts, you should use the latest released version of Solidity. This
|
||||||
is because breaking changes, as well as new features and bug fixes are introduced regularly.
|
is because breaking changes, as well as new features and bug fixes are introduced regularly.
|
||||||
We currently use a 0.x version number [to indicate this fast pace of change](https://semver.org/#spec-item-4).
|
We currently use a 0.x version number `to indicate this fast pace of change <https://semver.org/#spec-item-4>`_.
|
||||||
|
|
||||||
Remix
|
Remix
|
||||||
=====
|
=====
|
||||||
|
@ -56,7 +56,8 @@ as individual values.
|
|||||||
of Solidity due to the fact that storage pointers can be passed to libraries. This means that
|
of Solidity due to the fact that storage pointers can be passed to libraries. This means that
|
||||||
any change to the rules outlined in this section is considered a breaking change
|
any change to the rules outlined in this section is considered a breaking change
|
||||||
of the language and due to its critical nature should be considered very carefully before
|
of the language and due to its critical nature should be considered very carefully before
|
||||||
being executed.
|
being executed. In the event of such a breaking change, we would want to release a
|
||||||
|
compatibility mode in which the compiler would generate bytecode supporting the old layout.
|
||||||
|
|
||||||
|
|
||||||
Mappings and Dynamic Arrays
|
Mappings and Dynamic Arrays
|
||||||
|
@ -222,7 +222,7 @@ than the maximum value of ``uint`` (``2**256 - 1``). This is also true for the s
|
|||||||
|
|
||||||
:ref:`Errors <errors>` allow you to provide more information to the caller about
|
:ref:`Errors <errors>` allow you to provide more information to the caller about
|
||||||
why a condition or operation failed. Errors are used together with the
|
why a condition or operation failed. Errors are used together with the
|
||||||
:ref:`revert statement <revert-statement>`. The revert statement unconditionally
|
:ref:`revert statement <revert-statement>`. The ``revert`` statement unconditionally
|
||||||
aborts and reverts all changes similar to the ``require`` function, but it also
|
aborts and reverts all changes similar to the ``require`` function, but it also
|
||||||
allows you to provide the name of an error and additional data which will be supplied to the caller
|
allows you to provide the name of an error and additional data which will be supplied to the caller
|
||||||
(and eventually to the front-end application or block explorer) so that
|
(and eventually to the front-end application or block explorer) so that
|
||||||
|
@ -27,6 +27,9 @@ it does include the supplied string in the :ref:`bytecode metadata <metadata>`.
|
|||||||
|
|
||||||
If you do not want to specify a license or if the source code is
|
If you do not want to specify a license or if the source code is
|
||||||
not open-source, please use the special value ``UNLICENSED``.
|
not open-source, please use the special value ``UNLICENSED``.
|
||||||
|
Note that ``UNLICENSED`` (no usage allowed, not present in SPDX license list)
|
||||||
|
is different from ``UNLICENSE`` (grants all rights to everyone).
|
||||||
|
Solidity follows `the npm recommendation <https://docs.npmjs.com/cli/v7/configuring-npm/package-json#license>`_.
|
||||||
|
|
||||||
Supplying this comment of course does not free you from other
|
Supplying this comment of course does not free you from other
|
||||||
obligations related to licensing like having to mention
|
obligations related to licensing like having to mention
|
||||||
|
@ -82,6 +82,9 @@ Editor Integrations
|
|||||||
* `Visual Studio Code extension <https://juan.blanco.ws/solidity-contracts-in-visual-studio-code/>`_
|
* `Visual Studio Code extension <https://juan.blanco.ws/solidity-contracts-in-visual-studio-code/>`_
|
||||||
Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler.
|
Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler.
|
||||||
|
|
||||||
|
* `Solidity Visual Auditor extension <https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor>`_
|
||||||
|
Adds security centric syntax and semantic highlighting to Visual Studio Code.
|
||||||
|
|
||||||
Solidity Tools
|
Solidity Tools
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ Style Guide
|
|||||||
Introduction
|
Introduction
|
||||||
************
|
************
|
||||||
|
|
||||||
This guide is intended to provide coding conventions for writing solidity code.
|
This guide is intended to provide coding conventions for writing Solidity code.
|
||||||
This guide should be thought of as an evolving document that will change over
|
This guide should be thought of as an evolving document that will change over
|
||||||
time as useful conventions are found and old conventions are rendered obsolete.
|
time as useful conventions are found and old conventions are rendered obsolete.
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ taken from python's
|
|||||||
`pep8 style guide <https://www.python.org/dev/peps/pep-0008/>`_.
|
`pep8 style guide <https://www.python.org/dev/peps/pep-0008/>`_.
|
||||||
|
|
||||||
The goal of this guide is *not* to be the right way or the best way to write
|
The goal of this guide is *not* to be the right way or the best way to write
|
||||||
solidity code. The goal of this guide is *consistency*. A quote from python's
|
Solidity code. The goal of this guide is *consistency*. A quote from python's
|
||||||
`pep8 <https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds>`_
|
`pep8 <https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds>`_
|
||||||
captures this concept well.
|
captures this concept well.
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ captures this concept well.
|
|||||||
|
|
||||||
A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.
|
A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.
|
||||||
|
|
||||||
But most importantly: **know when to be inconsistent** -- sometimes the style guide just doesn't apply. When in doubt, use your best judgement. Look at other examples and decide what looks best. And don't hesitate to ask!
|
But most importantly: **know when to be inconsistent** -- sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don't hesitate to ask!
|
||||||
|
|
||||||
|
|
||||||
***********
|
***********
|
||||||
@ -51,7 +51,7 @@ Mixing tabs and spaces should be avoided.
|
|||||||
Blank Lines
|
Blank Lines
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Surround top level declarations in solidity source with two blank lines.
|
Surround top level declarations in Solidity source with two blank lines.
|
||||||
|
|
||||||
Yes:
|
Yes:
|
||||||
|
|
||||||
@ -680,7 +680,7 @@ No:
|
|||||||
}
|
}
|
||||||
|
|
||||||
For long function declarations, it is recommended to drop each argument onto
|
For long function declarations, it is recommended to drop each argument onto
|
||||||
it's own line at the same indentation level as the function body. The closing
|
its own line at the same indentation level as the function body. The closing
|
||||||
parenthesis and opening bracket should be placed on their own line as well at
|
parenthesis and opening bracket should be placed on their own line as well at
|
||||||
the same indentation level as the function declaration.
|
the same indentation level as the function declaration.
|
||||||
|
|
||||||
@ -933,7 +933,7 @@ Permissible:
|
|||||||
function shortFunction() public { doSomething(); }
|
function shortFunction() public { doSomething(); }
|
||||||
|
|
||||||
These guidelines for function declarations are intended to improve readability.
|
These guidelines for function declarations are intended to improve readability.
|
||||||
Authors should use their best judgement as this guide does not try to cover all
|
Authors should use their best judgment as this guide does not try to cover all
|
||||||
possible permutations for function declarations.
|
possible permutations for function declarations.
|
||||||
|
|
||||||
Mappings
|
Mappings
|
||||||
@ -1023,7 +1023,7 @@ No:
|
|||||||
|
|
||||||
* Operators with a higher priority than others can exclude surrounding
|
* Operators with a higher priority than others can exclude surrounding
|
||||||
whitespace in order to denote precedence. This is meant to allow for
|
whitespace in order to denote precedence. This is meant to allow for
|
||||||
improved readability for complex statement. You should always use the same
|
improved readability for complex statements. You should always use the same
|
||||||
amount of whitespace on either side of an operator:
|
amount of whitespace on either side of an operator:
|
||||||
|
|
||||||
Yes:
|
Yes:
|
||||||
|
@ -150,7 +150,7 @@ length or index access.
|
|||||||
Solidity does not have string manipulation functions, but there are
|
Solidity does not have string manipulation functions, but there are
|
||||||
third-party string libraries. You can also compare two strings by their keccak256-hash using
|
third-party string libraries. You can also compare two strings by their keccak256-hash using
|
||||||
``keccak256(abi.encodePacked(s1)) == keccak256(abi.encodePacked(s2))`` and
|
``keccak256(abi.encodePacked(s1)) == keccak256(abi.encodePacked(s2))`` and
|
||||||
concatenate two strings using ``bytes.concat(bytes(s1), bytes(s2))``.
|
concatenate two strings using ``string.concat(s1, s2)``.
|
||||||
|
|
||||||
You should use ``bytes`` over ``bytes1[]`` because it is cheaper,
|
You should use ``bytes`` over ``bytes1[]`` because it is cheaper,
|
||||||
since using ``bytes1[]`` in ``memory`` adds 31 padding bytes between the elements. Note that in ``storage``, the
|
since using ``bytes1[]`` in ``memory`` adds 31 padding bytes between the elements. Note that in ``storage``, the
|
||||||
@ -165,31 +165,40 @@ always use one of the value types ``bytes1`` to ``bytes32`` because they are muc
|
|||||||
that you are accessing the low-level bytes of the UTF-8 representation,
|
that you are accessing the low-level bytes of the UTF-8 representation,
|
||||||
and not the individual characters.
|
and not the individual characters.
|
||||||
|
|
||||||
.. index:: ! bytes-concat
|
.. index:: ! bytes-concat, ! string-concat
|
||||||
|
|
||||||
.. _bytes-concat:
|
.. _bytes-concat:
|
||||||
|
.. _string-concat:
|
||||||
|
|
||||||
``bytes.concat`` function
|
The functions ``bytes.concat`` and ``string.concat``
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
You can concatenate a variable number of ``bytes`` or ``bytes1 ... bytes32`` using ``bytes.concat``.
|
You can concatenate an arbitrary number of ``string`` values using ``string.concat``.
|
||||||
|
The function returns a single ``string memory`` array that contains the contents of the arguments without padding.
|
||||||
|
If you want to use parameters of other types that are not implicitly convertible to ``string``, you need to convert them to ``string`` first.
|
||||||
|
|
||||||
|
Analogously, the ``bytes.concat`` function can concatenate an arbitrary number of ``bytes`` or ``bytes1 ... bytes32`` values.
|
||||||
The function returns a single ``bytes memory`` array that contains the contents of the arguments without padding.
|
The function returns a single ``bytes memory`` array that contains the contents of the arguments without padding.
|
||||||
If you want to use string parameters or other types, you need to convert them to ``bytes`` or ``bytes1``/.../``bytes32`` first.
|
If you want to use string parameters or other types that are not implicitly convertible to ``bytes``, you need to convert them to ``bytes`` or ``bytes1``/.../``bytes32`` first.
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: solidity
|
.. code-block:: solidity
|
||||||
|
|
||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
pragma solidity ^0.8.4;
|
pragma solidity ^0.8.12;
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
bytes s = "Storage";
|
string s = "Storage";
|
||||||
function f(bytes calldata c, string memory m, bytes16 b) public view {
|
function f(bytes calldata bc, string memory sm, bytes16 b) public view {
|
||||||
bytes memory a = bytes.concat(s, c, c[:2], "Literal", bytes(m), b);
|
string memory concat_string = string.concat(s, string(bc), "Literal", sm);
|
||||||
assert((s.length + c.length + 2 + 7 + bytes(m).length + 16) == a.length);
|
assert((bytes(s).length + bc.length + 7 + bytes(sm).length) == bytes(concat_string).length);
|
||||||
|
|
||||||
|
bytes memory concat_bytes = bytes.concat(bytes(s), bc, bc[:2], "Literal", bytes(sm), b);
|
||||||
|
assert((bytes(s).length + bc.length + 2 + 7 + bytes(sm).length + b.length) == concat_bytes.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
If you call ``bytes.concat`` without arguments it will return an empty ``bytes`` array.
|
If you call ``string.concat`` or ``bytes.concat`` without arguments they return an empty array.
|
||||||
|
|
||||||
.. index:: ! array;allocating, new
|
.. index:: ! array;allocating, new
|
||||||
|
|
||||||
|
@ -154,6 +154,14 @@ Members of bytes
|
|||||||
|
|
||||||
- ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of bytes and bytes1, ..., bytes32 arguments to one byte array<bytes-concat>`
|
- ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of bytes and bytes1, ..., bytes32 arguments to one byte array<bytes-concat>`
|
||||||
|
|
||||||
|
.. index:: string members
|
||||||
|
|
||||||
|
Members of string
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
- ``string.concat(...) returns (string memory)``: :ref:`Concatenates variable number of string arguments to one string array<string-concat>`
|
||||||
|
|
||||||
|
|
||||||
.. index:: assert, revert, require
|
.. index:: assert, revert, require
|
||||||
|
|
||||||
Error Handling
|
Error Handling
|
||||||
|
@ -897,10 +897,11 @@ OverrideChecker::OverrideProxyBySignatureMultiSet const& OverrideChecker::inheri
|
|||||||
if (var->isPublic())
|
if (var->isPublic())
|
||||||
functionsInBase.emplace(OverrideProxy{var});
|
functionsInBase.emplace(OverrideProxy{var});
|
||||||
|
|
||||||
for (OverrideProxy const& func: inheritedFunctions(*base))
|
|
||||||
functionsInBase.insert(func);
|
|
||||||
|
|
||||||
result += functionsInBase;
|
result += functionsInBase;
|
||||||
|
|
||||||
|
for (OverrideProxy const& func: inheritedFunctions(*base))
|
||||||
|
if (!functionsInBase.count(func))
|
||||||
|
result.insert(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_inheritedFunctions[&_contract] = result;
|
m_inheritedFunctions[&_contract] = result;
|
||||||
|
@ -2207,14 +2207,42 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TypeChecker::typeCheckStringConcatFunction(
|
||||||
|
FunctionCall const& _functionCall,
|
||||||
|
FunctionType const* _functionType
|
||||||
|
)
|
||||||
|
{
|
||||||
|
solAssert(_functionType);
|
||||||
|
solAssert(_functionType->kind() == FunctionType::Kind::StringConcat);
|
||||||
|
solAssert(_functionCall.names().empty());
|
||||||
|
|
||||||
|
typeCheckFunctionGeneralChecks(_functionCall, _functionType);
|
||||||
|
|
||||||
|
for (shared_ptr<Expression const> const& argument: _functionCall.arguments())
|
||||||
|
{
|
||||||
|
Type const* argumentType = type(*argument);
|
||||||
|
bool notConvertibleToString = !argumentType->isImplicitlyConvertibleTo(*TypeProvider::stringMemory());
|
||||||
|
|
||||||
|
if (notConvertibleToString)
|
||||||
|
m_errorReporter.typeError(
|
||||||
|
9977_error,
|
||||||
|
argument->location(),
|
||||||
|
"Invalid type for argument in the string.concat function call. "
|
||||||
|
"string type is required, but " +
|
||||||
|
argumentType->identifier() + " provided."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TypeChecker::typeCheckBytesConcatFunction(
|
void TypeChecker::typeCheckBytesConcatFunction(
|
||||||
FunctionCall const& _functionCall,
|
FunctionCall const& _functionCall,
|
||||||
FunctionType const* _functionType
|
FunctionType const* _functionType
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
solAssert(_functionType, "");
|
solAssert(_functionType);
|
||||||
solAssert(_functionType->kind() == FunctionType::Kind::BytesConcat, "");
|
solAssert(_functionType->kind() == FunctionType::Kind::BytesConcat);
|
||||||
solAssert(_functionCall.names().empty(), "");
|
solAssert(_functionCall.names().empty());
|
||||||
|
|
||||||
typeCheckFunctionGeneralChecks(_functionCall, _functionType);
|
typeCheckFunctionGeneralChecks(_functionCall, _functionType);
|
||||||
|
|
||||||
@ -2651,6 +2679,12 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
|||||||
returnTypes = functionType->returnParameterTypes();
|
returnTypes = functionType->returnParameterTypes();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FunctionType::Kind::StringConcat:
|
||||||
|
{
|
||||||
|
typeCheckStringConcatFunction(_functionCall, functionType);
|
||||||
|
returnTypes = functionType->returnParameterTypes();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case FunctionType::Kind::Wrap:
|
case FunctionType::Kind::Wrap:
|
||||||
case FunctionType::Kind::Unwrap:
|
case FunctionType::Kind::Unwrap:
|
||||||
{
|
{
|
||||||
|
@ -113,6 +113,12 @@ private:
|
|||||||
/// Performs checks specific to the ABI encode functions of type ABIEncodeCall
|
/// Performs checks specific to the ABI encode functions of type ABIEncodeCall
|
||||||
void typeCheckABIEncodeCallFunction(FunctionCall const& _functionCall);
|
void typeCheckABIEncodeCallFunction(FunctionCall const& _functionCall);
|
||||||
|
|
||||||
|
/// Performs general checks and checks specific to string concat function call
|
||||||
|
void typeCheckStringConcatFunction(
|
||||||
|
FunctionCall const& _functionCall,
|
||||||
|
FunctionType const* _functionType
|
||||||
|
);
|
||||||
|
|
||||||
/// Performs general checks and checks specific to bytes concat function call
|
/// Performs general checks and checks specific to bytes concat function call
|
||||||
void typeCheckBytesConcatFunction(
|
void typeCheckBytesConcatFunction(
|
||||||
FunctionCall const& _functionCall,
|
FunctionCall const& _functionCall,
|
||||||
|
@ -192,7 +192,7 @@ FunctionDefinition const* ContractDefinition::receiveFunction() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<EventDefinition const*> const& ContractDefinition::interfaceEvents() const
|
vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents() const
|
||||||
{
|
{
|
||||||
return m_interfaceEvents.init([&]{
|
return m_interfaceEvents.init([&]{
|
||||||
set<string> eventsSeen;
|
set<string> eventsSeen;
|
||||||
@ -213,11 +213,20 @@ vector<EventDefinition const*> const& ContractDefinition::interfaceEvents() cons
|
|||||||
interfaceEvents.push_back(e);
|
interfaceEvents.push_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return interfaceEvents;
|
return interfaceEvents;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<EventDefinition const*> const ContractDefinition::usedInterfaceEvents() const
|
||||||
|
{
|
||||||
|
solAssert(annotation().creationCallGraph.set(), "");
|
||||||
|
|
||||||
|
return convertContainer<std::vector<EventDefinition const*>>(
|
||||||
|
(*annotation().creationCallGraph)->emittedEvents +
|
||||||
|
(*annotation().deployedCallGraph)->emittedEvents
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const
|
vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const
|
||||||
{
|
{
|
||||||
set<ErrorDefinition const*, CompareByID> result;
|
set<ErrorDefinition const*, CompareByID> result;
|
||||||
@ -227,10 +236,9 @@ vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _require
|
|||||||
if (_requireCallGraph)
|
if (_requireCallGraph)
|
||||||
solAssert(annotation().creationCallGraph.set(), "");
|
solAssert(annotation().creationCallGraph.set(), "");
|
||||||
if (annotation().creationCallGraph.set())
|
if (annotation().creationCallGraph.set())
|
||||||
{
|
result +=
|
||||||
result += (*annotation().creationCallGraph)->usedErrors;
|
(*annotation().creationCallGraph)->usedErrors +
|
||||||
result += (*annotation().deployedCallGraph)->usedErrors;
|
(*annotation().deployedCallGraph)->usedErrors;
|
||||||
}
|
|
||||||
return convertContainer<vector<ErrorDefinition const*>>(move(result));
|
return convertContainer<vector<ErrorDefinition const*>>(move(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,7 +519,8 @@ public:
|
|||||||
return ranges::subrange<decltype(b)>(b, e) | ranges::views::values;
|
return ranges::subrange<decltype(b)>(b, e) | ranges::views::values;
|
||||||
}
|
}
|
||||||
std::vector<EventDefinition const*> events() const { return filteredNodes<EventDefinition>(m_subNodes); }
|
std::vector<EventDefinition const*> events() const { return filteredNodes<EventDefinition>(m_subNodes); }
|
||||||
std::vector<EventDefinition const*> const& interfaceEvents() const;
|
std::vector<EventDefinition const*> const& definedInterfaceEvents() const;
|
||||||
|
std::vector<EventDefinition const*> const usedInterfaceEvents() const;
|
||||||
/// @returns all errors defined in this contract or any base contract
|
/// @returns all errors defined in this contract or any base contract
|
||||||
/// and all errors referenced during execution.
|
/// and all errors referenced during execution.
|
||||||
/// @param _requireCallGraph if false, do not fail if the call graph has not been computed yet.
|
/// @param _requireCallGraph if false, do not fail if the call graph has not been computed yet.
|
||||||
|
@ -2932,6 +2932,7 @@ string FunctionType::richIdentifier() const
|
|||||||
case Kind::ArrayPush: id += "arraypush"; break;
|
case Kind::ArrayPush: id += "arraypush"; break;
|
||||||
case Kind::ArrayPop: id += "arraypop"; break;
|
case Kind::ArrayPop: id += "arraypop"; break;
|
||||||
case Kind::BytesConcat: id += "bytesconcat"; break;
|
case Kind::BytesConcat: id += "bytesconcat"; break;
|
||||||
|
case Kind::StringConcat: id += "stringconcat"; break;
|
||||||
case Kind::ObjectCreation: id += "objectcreation"; break;
|
case Kind::ObjectCreation: id += "objectcreation"; break;
|
||||||
case Kind::Assert: id += "assert"; break;
|
case Kind::Assert: id += "assert"; break;
|
||||||
case Kind::Require: id += "require"; break;
|
case Kind::Require: id += "require"; break;
|
||||||
@ -3821,15 +3822,14 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
|||||||
)
|
)
|
||||||
members.emplace_back("concat", TypeProvider::function(
|
members.emplace_back("concat", TypeProvider::function(
|
||||||
TypePointers{},
|
TypePointers{},
|
||||||
TypePointers{TypeProvider::bytesMemory()},
|
TypePointers{arrayType->isString() ? TypeProvider::stringMemory() : TypeProvider::bytesMemory()},
|
||||||
strings{},
|
strings{},
|
||||||
strings{string()},
|
strings{string{}},
|
||||||
FunctionType::Kind::BytesConcat,
|
arrayType->isString() ? FunctionType::Kind::StringConcat : FunctionType::Kind::BytesConcat,
|
||||||
StateMutability::Pure,
|
StateMutability::Pure,
|
||||||
nullptr,
|
nullptr,
|
||||||
FunctionType::Options::withArbitraryParameters()
|
FunctionType::Options::withArbitraryParameters()
|
||||||
));
|
));
|
||||||
|
|
||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1228,6 +1228,7 @@ public:
|
|||||||
ArrayPush, ///< .push() to a dynamically sized array in storage
|
ArrayPush, ///< .push() to a dynamically sized array in storage
|
||||||
ArrayPop, ///< .pop() from a dynamically sized array in storage
|
ArrayPop, ///< .pop() from a dynamically sized array in storage
|
||||||
BytesConcat, ///< .concat() on bytes (type type)
|
BytesConcat, ///< .concat() on bytes (type type)
|
||||||
|
StringConcat, ///< .concat() on string (type type)
|
||||||
ObjectCreation, ///< array creation using new
|
ObjectCreation, ///< array creation using new
|
||||||
Assert, ///< assert()
|
Assert, ///< assert()
|
||||||
Require, ///< require()
|
Require, ///< require()
|
||||||
|
@ -1101,6 +1101,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
ArrayUtils(m_context).popStorageArrayElement(*arrayType);
|
ArrayUtils(m_context).popStorageArrayElement(*arrayType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FunctionType::Kind::StringConcat:
|
||||||
case FunctionType::Kind::BytesConcat:
|
case FunctionType::Kind::BytesConcat:
|
||||||
{
|
{
|
||||||
_functionCall.expression().accept(*this);
|
_functionCall.expression().accept(*this);
|
||||||
@ -1121,8 +1122,16 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
solAssert(!dynamic_cast<RationalNumberType const*>(argument->annotation().type), "");
|
solAssert(!dynamic_cast<RationalNumberType const*>(argument->annotation().type), "");
|
||||||
solAssert(argument->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()), "");
|
if (function.kind() == FunctionType::Kind::StringConcat)
|
||||||
targetTypes.emplace_back(TypeProvider::bytesMemory());
|
{
|
||||||
|
solAssert(argument->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::stringMemory()), "");
|
||||||
|
targetTypes.emplace_back(TypeProvider::stringMemory());
|
||||||
|
}
|
||||||
|
else if (function.kind() == FunctionType::Kind::BytesConcat)
|
||||||
|
{
|
||||||
|
solAssert(argument->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()), "");
|
||||||
|
targetTypes.emplace_back(TypeProvider::bytesMemory());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
utils().fetchFreeMemoryPointer();
|
utils().fetchFreeMemoryPointer();
|
||||||
|
@ -2475,18 +2475,26 @@ string YulUtilFunctions::copyArrayFromStorageToMemoryFunction(ArrayType const& _
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
string YulUtilFunctions::bytesConcatFunction(vector<Type const*> const& _argumentTypes)
|
string YulUtilFunctions::bytesOrStringConcatFunction(
|
||||||
|
vector<Type const*> const& _argumentTypes,
|
||||||
|
FunctionType::Kind _functionTypeKind
|
||||||
|
)
|
||||||
{
|
{
|
||||||
string functionName = "bytes_concat";
|
solAssert(_functionTypeKind == FunctionType::Kind::BytesConcat || _functionTypeKind == FunctionType::Kind::StringConcat);
|
||||||
|
std::string functionName = (_functionTypeKind == FunctionType::Kind::StringConcat) ? "string_concat" : "bytes_concat";
|
||||||
size_t totalParams = 0;
|
size_t totalParams = 0;
|
||||||
vector<Type const*> targetTypes;
|
vector<Type const*> targetTypes;
|
||||||
|
|
||||||
for (Type const* argumentType: _argumentTypes)
|
for (Type const* argumentType: _argumentTypes)
|
||||||
{
|
{
|
||||||
solAssert(
|
if (_functionTypeKind == FunctionType::Kind::StringConcat)
|
||||||
argumentType->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()) ||
|
solAssert(argumentType->isImplicitlyConvertibleTo(*TypeProvider::stringMemory()));
|
||||||
argumentType->isImplicitlyConvertibleTo(*TypeProvider::fixedBytes(32)),
|
else if (_functionTypeKind == FunctionType::Kind::BytesConcat)
|
||||||
""
|
solAssert(
|
||||||
);
|
argumentType->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()) ||
|
||||||
|
argumentType->isImplicitlyConvertibleTo(*TypeProvider::fixedBytes(32))
|
||||||
|
);
|
||||||
|
|
||||||
if (argumentType->category() == Type::Category::FixedBytes)
|
if (argumentType->category() == Type::Category::FixedBytes)
|
||||||
targetTypes.emplace_back(argumentType);
|
targetTypes.emplace_back(argumentType);
|
||||||
else if (
|
else if (
|
||||||
@ -2496,15 +2504,16 @@ string YulUtilFunctions::bytesConcatFunction(vector<Type const*> const& _argumen
|
|||||||
targetTypes.emplace_back(TypeProvider::fixedBytes(static_cast<unsigned>(literalType->value().size())));
|
targetTypes.emplace_back(TypeProvider::fixedBytes(static_cast<unsigned>(literalType->value().size())));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
solAssert(!dynamic_cast<RationalNumberType const*>(argumentType), "");
|
solAssert(!dynamic_cast<RationalNumberType const*>(argumentType));
|
||||||
solAssert(argumentType->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()), "");
|
targetTypes.emplace_back(
|
||||||
targetTypes.emplace_back(TypeProvider::bytesMemory());
|
_functionTypeKind == FunctionType::Kind::StringConcat ?
|
||||||
|
TypeProvider::stringMemory() :
|
||||||
|
TypeProvider::bytesMemory()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
totalParams += argumentType->sizeOnStack();
|
totalParams += argumentType->sizeOnStack();
|
||||||
functionName += "_" + argumentType->identifier();
|
functionName += "_" + argumentType->identifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_functionCollector.createFunction(functionName, [&]() {
|
return m_functionCollector.createFunction(functionName, [&]() {
|
||||||
Whiskers templ(R"(
|
Whiskers templ(R"(
|
||||||
function <functionName>(<parameters>) -> outPtr {
|
function <functionName>(<parameters>) -> outPtr {
|
||||||
|
@ -312,9 +312,13 @@ public:
|
|||||||
/// of the storage array into it.
|
/// of the storage array into it.
|
||||||
std::string copyArrayFromStorageToMemoryFunction(ArrayType const& _from, ArrayType const& _to);
|
std::string copyArrayFromStorageToMemoryFunction(ArrayType const& _from, ArrayType const& _to);
|
||||||
|
|
||||||
/// @returns the name of a function that does concatenation of variadic number of bytes
|
/// @returns the name of a function that does concatenation of variadic number of
|
||||||
/// or fixed bytes
|
/// bytes if @a functionTypeKind is FunctionType::Kind::BytesConcat,
|
||||||
std::string bytesConcatFunction(std::vector<Type const*> const& _argumentTypes);
|
/// or of strings, if @a functionTypeKind is FunctionType::Kind::StringConcat.
|
||||||
|
std::string bytesOrStringConcatFunction(
|
||||||
|
std::vector<Type const*> const& _argumentTypes,
|
||||||
|
FunctionType::Kind _functionTypeKind
|
||||||
|
);
|
||||||
|
|
||||||
/// @returns the name of a function that performs index access for mappings.
|
/// @returns the name of a function that performs index access for mappings.
|
||||||
/// @param _mappingType the type of the mapping
|
/// @param _mappingType the type of the mapping
|
||||||
|
@ -1389,6 +1389,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FunctionType::Kind::StringConcat:
|
||||||
case FunctionType::Kind::BytesConcat:
|
case FunctionType::Kind::BytesConcat:
|
||||||
{
|
{
|
||||||
TypePointers argumentTypes;
|
TypePointers argumentTypes;
|
||||||
@ -1399,11 +1400,10 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
argumentVars += IRVariable(*argument).stackSlots();
|
argumentVars += IRVariable(*argument).stackSlots();
|
||||||
}
|
}
|
||||||
define(IRVariable(_functionCall)) <<
|
define(IRVariable(_functionCall)) <<
|
||||||
m_utils.bytesConcatFunction(argumentTypes) <<
|
m_utils.bytesOrStringConcatFunction(argumentTypes, functionType->kind()) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
joinHumanReadable(argumentVars) <<
|
joinHumanReadable(argumentVars) <<
|
||||||
")\n";
|
")\n";
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionType::Kind::MetaType:
|
case FunctionType::Kind::MetaType:
|
||||||
|
@ -101,7 +101,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
|
|||||||
method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability());
|
method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability());
|
||||||
abi.emplace(std::move(method));
|
abi.emplace(std::move(method));
|
||||||
}
|
}
|
||||||
for (auto const& it: _contractDef.interfaceEvents())
|
for (auto const& it: _contractDef.definedInterfaceEvents())
|
||||||
{
|
{
|
||||||
Json::Value event{Json::objectValue};
|
Json::Value event{Json::objectValue};
|
||||||
event["type"] = "event";
|
event["type"] = "event";
|
||||||
|
@ -75,11 +75,14 @@
|
|||||||
#include <libsolutil/IpfsHash.h>
|
#include <libsolutil/IpfsHash.h>
|
||||||
#include <libsolutil/JSON.h>
|
#include <libsolutil/JSON.h>
|
||||||
#include <libsolutil/Algorithms.h>
|
#include <libsolutil/Algorithms.h>
|
||||||
|
#include <libsolutil/FunctionSelector.h>
|
||||||
|
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
|
||||||
|
#include <range/v3/view/concat.hpp>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -1013,15 +1016,34 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const
|
|||||||
return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); });
|
return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); });
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value CompilerStack::methodIdentifiers(string const& _contractName) const
|
Json::Value CompilerStack::interfaceSymbols(string const& _contractName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisPerformed)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
Json::Value methodIdentifiers(Json::objectValue);
|
Json::Value interfaceSymbols(Json::objectValue);
|
||||||
|
// Always have a methods object
|
||||||
|
interfaceSymbols["methods"] = Json::objectValue;
|
||||||
|
|
||||||
for (auto const& it: contractDefinition(_contractName).interfaceFunctions())
|
for (auto const& it: contractDefinition(_contractName).interfaceFunctions())
|
||||||
methodIdentifiers[it.second->externalSignature()] = it.first.hex();
|
interfaceSymbols["methods"][it.second->externalSignature()] = it.first.hex();
|
||||||
return methodIdentifiers;
|
for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors())
|
||||||
|
{
|
||||||
|
string signature = error->functionType(true)->externalSignature();
|
||||||
|
interfaceSymbols["errors"][signature] = toHex(toCompactBigEndian(selectorFromSignature32(signature), 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (EventDefinition const* event: ranges::concat_view(
|
||||||
|
contractDefinition(_contractName).definedInterfaceEvents(),
|
||||||
|
contractDefinition(_contractName).usedInterfaceEvents()
|
||||||
|
))
|
||||||
|
if (!event->isAnonymous())
|
||||||
|
{
|
||||||
|
string signature = event->functionType(true)->externalSignature();
|
||||||
|
interfaceSymbols["events"][signature] = toHex(u256(h256::Arith(keccak256(signature))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return interfaceSymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) const
|
bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) const
|
||||||
|
@ -327,8 +327,8 @@ public:
|
|||||||
/// Prerequisite: Successful call to parse or compile.
|
/// Prerequisite: Successful call to parse or compile.
|
||||||
Json::Value const& natspecDev(std::string const& _contractName) const;
|
Json::Value const& natspecDev(std::string const& _contractName) const;
|
||||||
|
|
||||||
/// @returns a JSON representing a map of method identifiers (hashes) to function names.
|
/// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names.
|
||||||
Json::Value methodIdentifiers(std::string const& _contractName) const;
|
Json::Value interfaceSymbols(std::string const& _contractName) const;
|
||||||
|
|
||||||
/// @returns the Contract Metadata matching the pipeline selected using the viaIR setting.
|
/// @returns the Contract Metadata matching the pipeline selected using the viaIR setting.
|
||||||
std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); }
|
std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); }
|
||||||
|
@ -116,7 +116,6 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
|
|||||||
for (auto const& prefix: prefixes)
|
for (auto const& prefix: prefixes)
|
||||||
{
|
{
|
||||||
boost::filesystem::path canonicalPath = normalizeCLIPathForVFS(prefix / strippedSourceUnitName, SymlinkResolution::Enabled);
|
boost::filesystem::path canonicalPath = normalizeCLIPathForVFS(prefix / strippedSourceUnitName, SymlinkResolution::Enabled);
|
||||||
|
|
||||||
if (boost::filesystem::exists(canonicalPath))
|
if (boost::filesystem::exists(canonicalPath))
|
||||||
candidates.push_back(std::move(canonicalPath));
|
candidates.push_back(std::move(canonicalPath));
|
||||||
}
|
}
|
||||||
@ -124,7 +123,12 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
|
|||||||
auto pathToQuotedString = [](boost::filesystem::path const& _path){ return "\"" + _path.string() + "\""; };
|
auto pathToQuotedString = [](boost::filesystem::path const& _path){ return "\"" + _path.string() + "\""; };
|
||||||
|
|
||||||
if (candidates.empty())
|
if (candidates.empty())
|
||||||
return ReadCallback::Result{false, "File not found."};
|
return ReadCallback::Result{
|
||||||
|
false,
|
||||||
|
"File not found. Searched the following locations: " +
|
||||||
|
joinHumanReadable(prefixes | ranges::views::transform(pathToQuotedString), ", ") +
|
||||||
|
"."
|
||||||
|
};
|
||||||
|
|
||||||
if (candidates.size() >= 2)
|
if (candidates.size() >= 2)
|
||||||
return ReadCallback::Result{
|
return ReadCallback::Result{
|
||||||
@ -135,11 +139,13 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
|
|||||||
"."
|
"."
|
||||||
};
|
};
|
||||||
|
|
||||||
FileSystemPathSet extraAllowedPaths = {m_basePath.empty() ? "." : m_basePath};
|
FileSystemPathSet allowedPaths =
|
||||||
extraAllowedPaths += m_includePaths;
|
m_allowedDirectories +
|
||||||
|
decltype(allowedPaths){m_basePath.empty() ? "." : m_basePath} +
|
||||||
|
m_includePaths;
|
||||||
|
|
||||||
bool isAllowed = false;
|
bool isAllowed = false;
|
||||||
for (boost::filesystem::path const& allowedDir: m_allowedDirectories + extraAllowedPaths)
|
for (boost::filesystem::path const& allowedDir: allowedPaths)
|
||||||
if (isPathPrefix(normalizeCLIPathForVFS(allowedDir, SymlinkResolution::Enabled), candidates[0]))
|
if (isPathPrefix(normalizeCLIPathForVFS(allowedDir, SymlinkResolution::Enabled), candidates[0]))
|
||||||
{
|
{
|
||||||
isAllowed = true;
|
isAllowed = true;
|
||||||
@ -147,7 +153,12 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isAllowed)
|
if (!isAllowed)
|
||||||
return ReadCallback::Result{false, "File outside of allowed directories."};
|
return ReadCallback::Result{
|
||||||
|
false,
|
||||||
|
"File outside of allowed directories. The following are allowed: " +
|
||||||
|
joinHumanReadable(allowedPaths | ranges::views::transform(pathToQuotedString), ", ") +
|
||||||
|
"."
|
||||||
|
};
|
||||||
|
|
||||||
if (!boost::filesystem::is_regular_file(candidates[0]))
|
if (!boost::filesystem::is_regular_file(candidates[0]))
|
||||||
return ReadCallback::Result{false, "Not a valid file."};
|
return ReadCallback::Result{false, "Not a valid file."};
|
||||||
@ -269,7 +280,8 @@ boost::filesystem::path FileReader::normalizeCLIPathForVFS(
|
|||||||
if (!isUNCPath(normalizedPath))
|
if (!isUNCPath(normalizedPath))
|
||||||
{
|
{
|
||||||
boost::filesystem::path workingDirRootPath = canonicalWorkDir.root_path();
|
boost::filesystem::path workingDirRootPath = canonicalWorkDir.root_path();
|
||||||
if (normalizedRootPath == workingDirRootPath)
|
// Ignore drive letter case on Windows (C:\ <=> c:\).
|
||||||
|
if (boost::filesystem::equivalent(normalizedRootPath, workingDirRootPath))
|
||||||
normalizedRootPath = "/";
|
normalizedRootPath = "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
|
|||||||
doc["methods"][it.second->externalSignature()]["notice"] = value;
|
doc["methods"][it.second->externalSignature()]["notice"] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& event: _contractDef.interfaceEvents())
|
for (auto const& event: _contractDef.definedInterfaceEvents())
|
||||||
{
|
{
|
||||||
string value = extractDoc(event->annotation().docTags, "notice");
|
string value = extractDoc(event->annotation().docTags, "notice");
|
||||||
if (!value.empty())
|
if (!value.empty())
|
||||||
|
@ -1298,7 +1298,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
|||||||
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly", wildcardMatchesExperimental))
|
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly", wildcardMatchesExperimental))
|
||||||
evmData["legacyAssembly"] = compilerStack.assemblyJSON(contractName);
|
evmData["legacyAssembly"] = compilerStack.assemblyJSON(contractName);
|
||||||
if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.methodIdentifiers", wildcardMatchesExperimental))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.methodIdentifiers", wildcardMatchesExperimental))
|
||||||
evmData["methodIdentifiers"] = compilerStack.methodIdentifiers(contractName);
|
evmData["methodIdentifiers"] = compilerStack.interfaceSymbols(contractName)["methods"];
|
||||||
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.gasEstimates", wildcardMatchesExperimental))
|
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.gasEstimates", wildcardMatchesExperimental))
|
||||||
evmData["gasEstimates"] = compilerStack.gasEstimates(contractName);
|
evmData["gasEstimates"] = compilerStack.gasEstimates(contractName);
|
||||||
|
|
||||||
|
@ -262,6 +262,11 @@ private:
|
|||||||
if (ops.sourceMultiplicity(ops.sourceSize() - 1 - swapDepth) < 0)
|
if (ops.sourceMultiplicity(ops.sourceSize() - 1 - swapDepth) < 0)
|
||||||
{
|
{
|
||||||
ops.swap(swapDepth);
|
ops.swap(swapDepth);
|
||||||
|
if (ops.targetIsArbitrary(sourceTop))
|
||||||
|
// Usually we keep a slot that is to-be-removed, if the current top is arbitrary.
|
||||||
|
// However, since we are in a stack-too-deep situation, pop it immediately
|
||||||
|
// to compress the stack (we can always push back junk in the end).
|
||||||
|
ops.pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Otherwise we rely on stack compression or stack-to-memory.
|
// Otherwise we rely on stack compression or stack-to-memory.
|
||||||
@ -321,14 +326,44 @@ private:
|
|||||||
yulAssert(ops.sourceMultiplicity(i) == 0 && (ops.targetIsArbitrary(i) || ops.targetMultiplicity(i) == 0), "");
|
yulAssert(ops.sourceMultiplicity(i) == 0 && (ops.targetIsArbitrary(i) || ops.targetMultiplicity(i) == 0), "");
|
||||||
yulAssert(ops.isCompatible(sourceTop, sourceTop), "");
|
yulAssert(ops.isCompatible(sourceTop, sourceTop), "");
|
||||||
|
|
||||||
|
auto swappableOffsets = ranges::views::iota(size > 17 ? size - 17 : 0u, size);
|
||||||
|
|
||||||
// If we find a lower slot that is out of position, but also compatible with the top, swap that up.
|
// If we find a lower slot that is out of position, but also compatible with the top, swap that up.
|
||||||
|
for (size_t offset: swappableOffsets)
|
||||||
|
if (!ops.isCompatible(offset, offset) && ops.isCompatible(sourceTop, offset))
|
||||||
|
{
|
||||||
|
ops.swap(size - offset - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Swap up any reachable slot that is still out of position.
|
||||||
|
for (size_t offset: swappableOffsets)
|
||||||
|
if (!ops.isCompatible(offset, offset) && !ops.sourceIsSame(offset, sourceTop))
|
||||||
|
{
|
||||||
|
ops.swap(size - offset - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// We are in a stack-too-deep situation and try to reduce the stack size.
|
||||||
|
// If the current top is merely kept since the target slot is arbitrary, pop it.
|
||||||
|
if (ops.targetIsArbitrary(sourceTop) && ops.sourceMultiplicity(sourceTop) <= 0)
|
||||||
|
{
|
||||||
|
ops.pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If any reachable slot is merely kept, since the target slot is arbitrary, swap it up and pop it.
|
||||||
|
for (size_t offset: swappableOffsets)
|
||||||
|
if (ops.targetIsArbitrary(offset) && ops.sourceMultiplicity(offset) <= 0)
|
||||||
|
{
|
||||||
|
ops.swap(size - offset - 1);
|
||||||
|
ops.pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// We cannot avoid a stack-too-deep error. Repeat the above without restricting to reachable slots.
|
||||||
for (size_t offset: ranges::views::iota(0u, size))
|
for (size_t offset: ranges::views::iota(0u, size))
|
||||||
if (!ops.isCompatible(offset, offset) && ops.isCompatible(sourceTop, offset))
|
if (!ops.isCompatible(offset, offset) && ops.isCompatible(sourceTop, offset))
|
||||||
{
|
{
|
||||||
ops.swap(size - offset - 1);
|
ops.swap(size - offset - 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Swap up any slot that is still out of position.
|
|
||||||
for (size_t offset: ranges::views::iota(0u, size))
|
for (size_t offset: ranges::views::iota(0u, size))
|
||||||
if (!ops.isCompatible(offset, offset) && !ops.sourceIsSame(offset, sourceTop))
|
if (!ops.isCompatible(offset, offset) && !ops.sourceIsSame(offset, sourceTop))
|
||||||
{
|
{
|
||||||
|
46
scripts/ci/base64DecToArr.js
Normal file
46
scripts/ci/base64DecToArr.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
function base64DecToArr (sBase64) {
|
||||||
|
/*\
|
||||||
|
|*|
|
||||||
|
|*| Base64 / binary data / UTF-8 strings utilities
|
||||||
|
|*|
|
||||||
|
|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
|
||||||
|
|*|
|
||||||
|
\*/
|
||||||
|
|
||||||
|
/* Array of bytes to Base64 string decoding */
|
||||||
|
|
||||||
|
function b64ToUint6 (nChr) {
|
||||||
|
|
||||||
|
return nChr > 64 && nChr < 91 ?
|
||||||
|
nChr - 65
|
||||||
|
: nChr > 96 && nChr < 123 ?
|
||||||
|
nChr - 71
|
||||||
|
: nChr > 47 && nChr < 58 ?
|
||||||
|
nChr + 4
|
||||||
|
: nChr === 43 ?
|
||||||
|
62
|
||||||
|
: nChr === 47 ?
|
||||||
|
63
|
||||||
|
:
|
||||||
|
0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var
|
||||||
|
nInLen = sBase64.length,
|
||||||
|
nOutLen = nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen);
|
||||||
|
|
||||||
|
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
|
||||||
|
nMod4 = nInIdx & 3;
|
||||||
|
nUint24 |= b64ToUint6(sBase64.charCodeAt(nInIdx)) << 6 * (3 - nMod4);
|
||||||
|
if (nMod4 === 3 || nInLen - nInIdx === 1) {
|
||||||
|
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
|
||||||
|
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
|
||||||
|
}
|
||||||
|
nUint24 = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return taBytes;
|
||||||
|
}
|
@ -40,6 +40,8 @@ else
|
|||||||
BUILD_DIR="$1"
|
BUILD_DIR="$1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
apt-get update && apt-get install lz4
|
||||||
|
|
||||||
WORKSPACE=/root/project
|
WORKSPACE=/root/project
|
||||||
|
|
||||||
cd $WORKSPACE
|
cd $WORKSPACE
|
||||||
@ -71,8 +73,8 @@ make soljson
|
|||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
mkdir -p upload
|
mkdir -p upload
|
||||||
cp "$BUILD_DIR/libsolc/soljson.js" upload/
|
scripts/ci/pack_soljson.sh "$BUILD_DIR/libsolc/soljson.js" "$BUILD_DIR/libsolc/soljson.wasm" upload/soljson.js
|
||||||
cp "$BUILD_DIR/libsolc/soljson.js" ./
|
cp upload/soljson.js ./
|
||||||
|
|
||||||
OUTPUT_SIZE=$(ls -la soljson.js)
|
OUTPUT_SIZE=$(ls -la soljson.js)
|
||||||
|
|
||||||
|
116
scripts/ci/mini-lz4.js
Normal file
116
scripts/ci/mini-lz4.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
function uncompress(source, uncompressedSize) {
|
||||||
|
/*
|
||||||
|
based off https://github.com/emscripten-core/emscripten/blob/main/third_party/mini-lz4.js
|
||||||
|
The license only applies to the body of this function (``uncompress``).
|
||||||
|
====
|
||||||
|
MiniLZ4: Minimal LZ4 block decoding and encoding.
|
||||||
|
|
||||||
|
based off of node-lz4, https://github.com/pierrec/node-lz4
|
||||||
|
|
||||||
|
====
|
||||||
|
Copyright (c) 2012 Pierre Curto
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
====
|
||||||
|
|
||||||
|
changes have the same license
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Decode a block. Assumptions: input contains all sequences of a
|
||||||
|
* chunk, output is large enough to receive the decoded data.
|
||||||
|
* If the output buffer is too small, an error will be thrown.
|
||||||
|
* If the returned value is negative, an error occurred at the returned offset.
|
||||||
|
*
|
||||||
|
* @param {ArrayBufferView} input input data
|
||||||
|
* @param {ArrayBufferView} output output data
|
||||||
|
* @param {number=} sIdx
|
||||||
|
* @param {number=} eIdx
|
||||||
|
* @return {number} number of decoded bytes
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function uncompressBlock (input, output, sIdx, eIdx) {
|
||||||
|
sIdx = sIdx || 0
|
||||||
|
eIdx = eIdx || (input.length - sIdx)
|
||||||
|
// Process each sequence in the incoming data
|
||||||
|
for (var i = sIdx, n = eIdx, j = 0; i < n;) {
|
||||||
|
var token = input[i++]
|
||||||
|
|
||||||
|
// Literals
|
||||||
|
var literals_length = (token >> 4)
|
||||||
|
if (literals_length > 0) {
|
||||||
|
// length of literals
|
||||||
|
var l = literals_length + 240
|
||||||
|
while (l === 255) {
|
||||||
|
l = input[i++]
|
||||||
|
literals_length += l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the literals
|
||||||
|
var end = i + literals_length
|
||||||
|
while (i < end) output[j++] = input[i++]
|
||||||
|
|
||||||
|
// End of buffer?
|
||||||
|
if (i === n) return j
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match copy
|
||||||
|
// 2 bytes offset (little endian)
|
||||||
|
var offset = input[i++] | (input[i++] << 8)
|
||||||
|
|
||||||
|
// XXX 0 is an invalid offset value
|
||||||
|
if (offset === 0) return j
|
||||||
|
if (offset > j) return -(i-2)
|
||||||
|
|
||||||
|
// length of match copy
|
||||||
|
var match_length = (token & 0xf)
|
||||||
|
var l = match_length + 240
|
||||||
|
while (l === 255) {
|
||||||
|
l = input[i++]
|
||||||
|
match_length += l
|
||||||
|
}
|
||||||
|
// Copy the match
|
||||||
|
var pos = j - offset // position of the match copy in the current output
|
||||||
|
var end = j + match_length + 4 // minmatch = 4
|
||||||
|
while (j < end) output[j++] = output[pos++]
|
||||||
|
}
|
||||||
|
|
||||||
|
return j
|
||||||
|
}
|
||||||
|
var result = new ArrayBuffer(uncompressedSize);
|
||||||
|
var sourceIndex = 0;
|
||||||
|
var destIndex = 0;
|
||||||
|
var blockSize;
|
||||||
|
while((blockSize = (source[sourceIndex] | (source[sourceIndex + 1] << 8) | (source[sourceIndex + 2] << 16) | (source[sourceIndex + 3] << 24))) > 0)
|
||||||
|
{
|
||||||
|
sourceIndex += 4;
|
||||||
|
if (blockSize & 0x80000000)
|
||||||
|
{
|
||||||
|
blockSize &= 0x7FFFFFFFF;
|
||||||
|
for (var i = 0; i < blockSize; i++) {
|
||||||
|
result[destIndex++] = source[sourceIndex++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
destIndex += uncompressBlock(source, new Uint8Array(result, destIndex, uncompressedSize - destIndex), sourceIndex, sourceIndex + blockSize);
|
||||||
|
sourceIndex += blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Uint8Array(result, 0, uncompressedSize);
|
||||||
|
}
|
37
scripts/ci/pack_soljson.sh
Executable file
37
scripts/ci/pack_soljson.sh
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
script_dir="$(realpath "$(dirname "$0")")"
|
||||||
|
soljson_js="$1"
|
||||||
|
soljson_wasm="$2"
|
||||||
|
soljson_wasm_size=$(wc -c "${soljson_wasm}" | cut -d ' ' -f 1)
|
||||||
|
output="$3"
|
||||||
|
|
||||||
|
(( $# == 3 )) || { >&2 echo "Usage: $0 soljson.js soljson.wasm packed_soljson.js"; exit 1; }
|
||||||
|
|
||||||
|
# If this changes in an emscripten update, it's probably nothing to worry about,
|
||||||
|
# but we should double-check when it happens and adjust the tail command below.
|
||||||
|
[[ $(head -c 5 "${soljson_js}") == "null;" ]] || { >&2 echo 'Expected soljson.js to start with "null;"'; exit 1; }
|
||||||
|
|
||||||
|
echo "Packing $soljson_js and $soljson_wasm to $output."
|
||||||
|
(
|
||||||
|
echo -n 'var Module = Module || {}; Module["wasmBinary"] = '
|
||||||
|
echo -n '(function(source, uncompressedSize) {'
|
||||||
|
# Note that base64DecToArr assumes no trailing equals signs.
|
||||||
|
cpp "${script_dir}/base64DecToArr.js" | grep -v "^#.*"
|
||||||
|
# Note that mini-lz4.js assumes no file header and no frame crc checksums.
|
||||||
|
cpp "${script_dir}/mini-lz4.js" | grep -v "^#.*"
|
||||||
|
echo 'return uncompress(base64DecToArr(source), uncompressedSize);})('
|
||||||
|
echo -n '"'
|
||||||
|
# We fix lz4 format settings, remove the 8 bytes file header and remove the trailing equals signs of the base64 encoding.
|
||||||
|
lz4c --no-frame-crc --best --favor-decSpeed "${soljson_wasm}" - | tail -c +8 | base64 -w 0 | sed 's/[^A-Za-z0-9\+\/]//g'
|
||||||
|
echo '",'
|
||||||
|
echo -n "${soljson_wasm_size});"
|
||||||
|
# Remove "null;" from the js wrapper.
|
||||||
|
tail -c +6 "${soljson_js}"
|
||||||
|
) > "$output"
|
||||||
|
|
||||||
|
echo "Testing $output."
|
||||||
|
echo "process.stdout.write(require('$(realpath "${output}")').wasmBinary)" | node | cmp "${soljson_wasm}" && echo "Binaries match."
|
||||||
|
# Allow the wasm binary to be garbage collected after compilation.
|
||||||
|
echo 'Module["wasmBinary"] = undefined;' >> "${output}"
|
60
scripts/externalTests/merge_benchmarks.sh
Executable file
60
scripts/externalTests/merge_benchmarks.sh
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Reads multiple individual benchmark reports produced by scripts from
|
||||||
|
# test/externalTests/ from standard input and creates a combined report.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# <script name>.sh < <CONCATENATED_REPORTS>
|
||||||
|
#
|
||||||
|
# CONCATENATED_REPORTS: JSON report files concatenated into a single stream (e.g. using cat).
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# cat reports/externalTests/benchmark-*.json | <script name>.sh
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# This file is part of solidity.
|
||||||
|
#
|
||||||
|
# solidity is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# solidity is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with solidity. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
#
|
||||||
|
# (c) 2021 solidity contributors.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# We expect a series of dicts of the form {"<project>": {"<preset>": {...}}}.
|
||||||
|
# Unfortunately jq's built-in `add` filter can't handle nested dicts and
|
||||||
|
# would just overwrite values sharing a project name instead of merging them.
|
||||||
|
|
||||||
|
# This is done by first grouping the dicts into an array of the form
|
||||||
|
# [
|
||||||
|
# [{"key": "<project1>", "value": {"<preset1>": {...}}}, {"key": "<project1>", "value": {"<preset2>": {...}}, ...],
|
||||||
|
# [{"key": "<project2>", "value": {"<preset1>": {...}}}, {"key": "<project2>", "value": {"<preset2>": {...}}, ...],
|
||||||
|
# ...
|
||||||
|
# ]
|
||||||
|
# and then using reduce() on each group sharing the same project name to convert it into a
|
||||||
|
# dict having preset names as keys.
|
||||||
|
jq --slurp --indent 4 --sort-keys '
|
||||||
|
map(to_entries[]) |
|
||||||
|
group_by(.key) |
|
||||||
|
map({
|
||||||
|
(.[0].key): (
|
||||||
|
reduce (.[].value | to_entries[]) as {$key, $value} (
|
||||||
|
{}; . + {
|
||||||
|
($key): $value
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}) |
|
||||||
|
add
|
||||||
|
'
|
269
scripts/externalTests/parse_eth_gas_report.py
Executable file
269
scripts/externalTests/parse_eth_gas_report.py
Executable file
@ -0,0 +1,269 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from dataclasses import asdict, dataclass, field
|
||||||
|
from typing import Dict, Optional, Tuple
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
REPORT_HEADER_REGEX = re.compile(r'''
|
||||||
|
^[|\s]+ Solc[ ]version:\s*(?P<solc_version>[\w\d.]+)
|
||||||
|
[|\s]+ Optimizer[ ]enabled:\s*(?P<optimize>[\w]+)
|
||||||
|
[|\s]+ Runs:\s*(?P<runs>[\d]+)
|
||||||
|
[|\s]+ Block[ ]limit:\s*(?P<block_limit>[\d]+)\s*gas
|
||||||
|
[|\s]+$
|
||||||
|
''', re.VERBOSE)
|
||||||
|
METHOD_HEADER_REGEX = re.compile(r'^[|\s]+Methods[|\s]+$')
|
||||||
|
METHOD_COLUMN_HEADERS_REGEX = re.compile(r'''
|
||||||
|
^[|\s]+ Contract
|
||||||
|
[|\s]+ Method
|
||||||
|
[|\s]+ Min
|
||||||
|
[|\s]+ Max
|
||||||
|
[|\s]+ Avg
|
||||||
|
[|\s]+ \#[ ]calls
|
||||||
|
[|\s]+ \w+[ ]\(avg\)
|
||||||
|
[|\s]+$
|
||||||
|
''', re.VERBOSE)
|
||||||
|
METHOD_ROW_REGEX = re.compile(r'''
|
||||||
|
^[|\s]+ (?P<contract>[^|]+)
|
||||||
|
[|\s]+ (?P<method>[^|]+)
|
||||||
|
[|\s]+ (?P<min>[^|]+)
|
||||||
|
[|\s]+ (?P<max>[^|]+)
|
||||||
|
[|\s]+ (?P<avg>[^|]+)
|
||||||
|
[|\s]+ (?P<call_count>[^|]+)
|
||||||
|
[|\s]+ (?P<eur_avg>[^|]+)
|
||||||
|
[|\s]+$
|
||||||
|
''', re.VERBOSE)
|
||||||
|
FRAME_REGEX = re.compile(r'^[-|\s]+$')
|
||||||
|
DEPLOYMENT_HEADER_REGEX = re.compile(r'^[|\s]+Deployments[|\s]+% of limit[|\s]+$')
|
||||||
|
DEPLOYMENT_ROW_REGEX = re.compile(r'''
|
||||||
|
^[|\s]+ (?P<contract>[^|]+)
|
||||||
|
[|\s]+ (?P<min>[^|]+)
|
||||||
|
[|\s]+ (?P<max>[^|]+)
|
||||||
|
[|\s]+ (?P<avg>[^|]+)
|
||||||
|
[|\s]+ (?P<percent_of_limit>[^|]+)\s*%
|
||||||
|
[|\s]+ (?P<eur_avg>[^|]+)
|
||||||
|
[|\s]+$
|
||||||
|
''', re.VERBOSE)
|
||||||
|
|
||||||
|
|
||||||
|
class ReportError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ReportValidationError(ReportError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ReportParsingError(Exception):
|
||||||
|
def __init__(self, message: str, line: str, line_number: int):
|
||||||
|
# pylint: disable=useless-super-delegation # It's not useless, it adds type annotations.
|
||||||
|
super().__init__(message, line, line_number)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Parsing error on line {self.args[2] + 1}: {self.args[0]}\n{self.args[1]}"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class MethodGasReport:
|
||||||
|
min_gas: int
|
||||||
|
max_gas: int
|
||||||
|
avg_gas: int
|
||||||
|
call_count: int
|
||||||
|
total_gas: int = field(init=False)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
object.__setattr__(self, 'total_gas', self.avg_gas * self.call_count)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ContractGasReport:
|
||||||
|
min_deployment_gas: Optional[int]
|
||||||
|
max_deployment_gas: Optional[int]
|
||||||
|
avg_deployment_gas: Optional[int]
|
||||||
|
methods: Optional[Dict[str, MethodGasReport]]
|
||||||
|
total_method_gas: int = field(init=False, default=0)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.methods is not None:
|
||||||
|
object.__setattr__(self, 'total_method_gas', sum(method.total_gas for method in self.methods.values()))
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class GasReport:
|
||||||
|
solc_version: str
|
||||||
|
optimize: bool
|
||||||
|
runs: int
|
||||||
|
block_limit: int
|
||||||
|
contracts: Dict[str, ContractGasReport]
|
||||||
|
total_method_gas: int = field(init=False)
|
||||||
|
total_deployment_gas: int = field(init=False)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
object.__setattr__(self, 'total_method_gas', sum(
|
||||||
|
total_method_gas
|
||||||
|
for total_method_gas in (contract.total_method_gas for contract in self.contracts.values())
|
||||||
|
if total_method_gas is not None
|
||||||
|
))
|
||||||
|
object.__setattr__(self, 'total_deployment_gas', sum(
|
||||||
|
contract.avg_deployment_gas
|
||||||
|
for contract in self.contracts.values()
|
||||||
|
if contract.avg_deployment_gas is not None
|
||||||
|
))
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
return json.dumps(asdict(self), indent=4, sort_keys=True)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_bool(input_string: str) -> bool:
|
||||||
|
if input_string == 'true':
|
||||||
|
return True
|
||||||
|
elif input_string == 'false':
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Invalid boolean value: '{input_string}'")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_optional_int(input_string: str, default: Optional[int] = None) -> Optional[int]:
|
||||||
|
if input_string.strip() == '-':
|
||||||
|
return default
|
||||||
|
|
||||||
|
return int(input_string)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_report_header(line: str) -> Optional[dict]:
|
||||||
|
match = REPORT_HEADER_REGEX.match(line)
|
||||||
|
if match is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'solc_version': match.group('solc_version'),
|
||||||
|
'optimize': parse_bool(match.group('optimize')),
|
||||||
|
'runs': int(match.group('runs')),
|
||||||
|
'block_limit': int(match.group('block_limit')),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_method_row(line: str, line_number: int) -> Optional[Tuple[str, str, MethodGasReport]]:
|
||||||
|
match = METHOD_ROW_REGEX.match(line)
|
||||||
|
if match is None:
|
||||||
|
raise ReportParsingError("Expected a table row with method details.", line, line_number)
|
||||||
|
|
||||||
|
avg_gas = parse_optional_int(match['avg'])
|
||||||
|
call_count = int(match['call_count'])
|
||||||
|
|
||||||
|
if avg_gas is None and call_count == 0:
|
||||||
|
# No calls, no gas values. Uninteresting. Skip the row.
|
||||||
|
return None
|
||||||
|
|
||||||
|
return (
|
||||||
|
match['contract'].strip(),
|
||||||
|
match['method'].strip(),
|
||||||
|
MethodGasReport(
|
||||||
|
min_gas=parse_optional_int(match['min'], avg_gas),
|
||||||
|
max_gas=parse_optional_int(match['max'], avg_gas),
|
||||||
|
avg_gas=avg_gas,
|
||||||
|
call_count=call_count,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_deployment_row(line: str, line_number: int) -> Tuple[str, int, int, int]:
|
||||||
|
match = DEPLOYMENT_ROW_REGEX.match(line)
|
||||||
|
if match is None:
|
||||||
|
raise ReportParsingError("Expected a table row with deployment details.", line, line_number)
|
||||||
|
|
||||||
|
return (
|
||||||
|
match['contract'].strip(),
|
||||||
|
parse_optional_int(match['min'].strip()),
|
||||||
|
parse_optional_int(match['max'].strip()),
|
||||||
|
int(match['avg'].strip()),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def preprocess_unicode_frames(input_string: str) -> str:
|
||||||
|
# The report has a mix of normal pipe chars and its unicode variant.
|
||||||
|
# Let's just replace all frame chars with normal pipes for easier parsing.
|
||||||
|
return input_string.replace('\u2502', '|').replace('·', '|')
|
||||||
|
|
||||||
|
|
||||||
|
def parse_report(rst_report: str) -> GasReport:
|
||||||
|
report_params = None
|
||||||
|
methods_by_contract = {}
|
||||||
|
deployment_costs = {}
|
||||||
|
expected_row_type = None
|
||||||
|
|
||||||
|
for line_number, line in enumerate(preprocess_unicode_frames(rst_report).splitlines()):
|
||||||
|
try:
|
||||||
|
if (
|
||||||
|
line.strip() == "" or
|
||||||
|
FRAME_REGEX.match(line) is not None or
|
||||||
|
METHOD_COLUMN_HEADERS_REGEX.match(line) is not None
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
if METHOD_HEADER_REGEX.match(line) is not None:
|
||||||
|
expected_row_type = 'method'
|
||||||
|
continue
|
||||||
|
if DEPLOYMENT_HEADER_REGEX.match(line) is not None:
|
||||||
|
expected_row_type = 'deployment'
|
||||||
|
continue
|
||||||
|
|
||||||
|
new_report_params = parse_report_header(line)
|
||||||
|
if new_report_params is not None:
|
||||||
|
if report_params is not None:
|
||||||
|
raise ReportParsingError("Duplicate report header.", line, line_number)
|
||||||
|
|
||||||
|
report_params = new_report_params
|
||||||
|
continue
|
||||||
|
|
||||||
|
if expected_row_type == 'method':
|
||||||
|
parsed_row = parse_method_row(line, line_number)
|
||||||
|
if parsed_row is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
(contract, method, method_report) = parsed_row
|
||||||
|
|
||||||
|
if contract not in methods_by_contract:
|
||||||
|
methods_by_contract[contract] = {}
|
||||||
|
|
||||||
|
if method in methods_by_contract[contract]:
|
||||||
|
# Report must be generated with full signatures for method names to be unambiguous.
|
||||||
|
raise ReportParsingError(f"Duplicate method row for '{contract}.{method}'.", line, line_number)
|
||||||
|
|
||||||
|
methods_by_contract[contract][method] = method_report
|
||||||
|
elif expected_row_type == 'deployment':
|
||||||
|
(contract, min_gas, max_gas, avg_gas) = parse_deployment_row(line, line_number)
|
||||||
|
|
||||||
|
if contract in deployment_costs:
|
||||||
|
raise ReportParsingError(f"Duplicate contract deployment row for '{contract}'.", line, line_number)
|
||||||
|
|
||||||
|
deployment_costs[contract] = (min_gas, max_gas, avg_gas)
|
||||||
|
else:
|
||||||
|
assert expected_row_type is None
|
||||||
|
raise ReportParsingError("Found data row without a section header.", line, line_number)
|
||||||
|
|
||||||
|
except ValueError as error:
|
||||||
|
raise ReportParsingError(error.args[0], line, line_number) from error
|
||||||
|
|
||||||
|
if report_params is None:
|
||||||
|
raise ReportValidationError("Report header not found.")
|
||||||
|
|
||||||
|
report_params['contracts'] = {
|
||||||
|
contract: ContractGasReport(
|
||||||
|
min_deployment_gas=deployment_costs.get(contract, (None, None, None))[0],
|
||||||
|
max_deployment_gas=deployment_costs.get(contract, (None, None, None))[1],
|
||||||
|
avg_deployment_gas=deployment_costs.get(contract, (None, None, None))[2],
|
||||||
|
methods=methods_by_contract.get(contract),
|
||||||
|
)
|
||||||
|
for contract in methods_by_contract.keys() | deployment_costs.keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
return GasReport(**report_params)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
report = parse_report(sys.stdin.read())
|
||||||
|
print(report.to_json())
|
||||||
|
except ReportError as exception:
|
||||||
|
print(f"{exception}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
53
scripts/externalTests/summarize_benchmarks.sh
Executable file
53
scripts/externalTests/summarize_benchmarks.sh
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Reads a combined benchmark report from standard input and outputs an abbreviated
|
||||||
|
# report containing only totals. Can handle individual reports coming directly
|
||||||
|
# from scripts in test/externalTests/ as well as combined report from merge_benchmarks.sh.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# <script name>.sh < <CONCATENATED_REPORTS>
|
||||||
|
#
|
||||||
|
# CONCATENATED_REPORTS: JSON report files concatenated into a single stream (e.g. using cat).
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# cat reports/externalTests/benchmark-*.json | <script name>.sh
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# This file is part of solidity.
|
||||||
|
#
|
||||||
|
# solidity is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# solidity is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with solidity. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
#
|
||||||
|
# (c) 2021 solidity contributors.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
|
# Iterates over presets in a dict of the form {"<project>": {"<preset>": {...}}} and for each
|
||||||
|
# one preserves only the few keys with totals that we want to see in the summary.
|
||||||
|
exec "${REPO_ROOT}/scripts/externalTests/merge_benchmarks.sh" | jq --indent 4 --sort-keys '
|
||||||
|
with_entries({
|
||||||
|
key: .key,
|
||||||
|
value: .value | with_entries({
|
||||||
|
key: .key,
|
||||||
|
value: {
|
||||||
|
bytecode_size: .value.total_bytecode_size,
|
||||||
|
method_gas: .value.gas.total_method_gas,
|
||||||
|
deployment_gas: .value.gas.total_deployment_gas,
|
||||||
|
version: .value.project.version
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
'
|
@ -270,15 +270,29 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract)
|
|||||||
if (!m_options.compiler.outputs.signatureHashes)
|
if (!m_options.compiler.outputs.signatureHashes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Json::Value methodIdentifiers = m_compiler->methodIdentifiers(_contract);
|
Json::Value interfaceSymbols = m_compiler->interfaceSymbols(_contract);
|
||||||
string out;
|
string out = "Function signatures:\n";
|
||||||
for (auto const& name: methodIdentifiers.getMemberNames())
|
for (auto const& name: interfaceSymbols["methods"].getMemberNames())
|
||||||
out += methodIdentifiers[name].asString() + ": " + name + "\n";
|
out += interfaceSymbols["methods"][name].asString() + ": " + name + "\n";
|
||||||
|
|
||||||
|
if (interfaceSymbols.isMember("errors"))
|
||||||
|
{
|
||||||
|
out += "\nError signatures:\n";
|
||||||
|
for (auto const& name: interfaceSymbols["errors"].getMemberNames())
|
||||||
|
out += interfaceSymbols["errors"][name].asString() + ": " + name + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interfaceSymbols.isMember("events"))
|
||||||
|
{
|
||||||
|
out += "\nEvent signatures:\n";
|
||||||
|
for (auto const& name: interfaceSymbols["events"].getMemberNames())
|
||||||
|
out += interfaceSymbols["events"][name].asString() + ": " + name + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_options.output.dir.empty())
|
if (!m_options.output.dir.empty())
|
||||||
createFile(m_compiler->filesystemFriendlyName(_contract) + ".signatures", out);
|
createFile(m_compiler->filesystemFriendlyName(_contract) + ".signatures", out);
|
||||||
else
|
else
|
||||||
sout() << "Function signatures:" << endl << out;
|
sout() << out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineInterface::handleMetadata(string const& _contract)
|
void CommandLineInterface::handleMetadata(string const& _contract)
|
||||||
@ -822,7 +836,7 @@ void CommandLineInterface::handleCombinedJSON()
|
|||||||
m_compiler->runtimeObject(contractName).functionDebugData
|
m_compiler->runtimeObject(contractName).functionDebugData
|
||||||
);
|
);
|
||||||
if (m_options.compiler.combinedJsonRequests->signatureHashes)
|
if (m_options.compiler.combinedJsonRequests->signatureHashes)
|
||||||
contractData[g_strSignatureHashes] = m_compiler->methodIdentifiers(contractName);
|
contractData[g_strSignatureHashes] = m_compiler->interfaceSymbols(contractName)["methods"];
|
||||||
if (m_options.compiler.combinedJsonRequests->natspecDev)
|
if (m_options.compiler.combinedJsonRequests->natspecDev)
|
||||||
contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName);
|
contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName);
|
||||||
if (m_options.compiler.combinedJsonRequests->natspecUser)
|
if (m_options.compiler.combinedJsonRequests->natspecUser)
|
||||||
|
@ -147,6 +147,7 @@ set(libyul_sources
|
|||||||
libyul/Parser.cpp
|
libyul/Parser.cpp
|
||||||
libyul/StackLayoutGeneratorTest.cpp
|
libyul/StackLayoutGeneratorTest.cpp
|
||||||
libyul/StackLayoutGeneratorTest.h
|
libyul/StackLayoutGeneratorTest.h
|
||||||
|
libyul/StackShufflingTest.cpp
|
||||||
libyul/SyntaxTest.h
|
libyul/SyntaxTest.h
|
||||||
libyul/SyntaxTest.cpp
|
libyul/SyntaxTest.cpp
|
||||||
libyul/YulInterpreterTest.cpp
|
libyul/YulInterpreterTest.cpp
|
||||||
|
@ -81,5 +81,6 @@ bool solidity::test::createSymlinkIfSupportedByFilesystem(
|
|||||||
BOOST_THROW_EXCEPTION(runtime_error(
|
BOOST_THROW_EXCEPTION(runtime_error(
|
||||||
"Failed to create a symbolic link: \"" + _linkName.string() + "\""
|
"Failed to create a symbolic link: \"" + _linkName.string() + "\""
|
||||||
" -> " + _targetPath.string() + "\"."
|
" -> " + _targetPath.string() + "\"."
|
||||||
|
" " + symlinkCreationError.message() + "."
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ void removeTestSuite(std::string const& _name)
|
|||||||
{
|
{
|
||||||
master_test_suite_t& master = framework::master_test_suite();
|
master_test_suite_t& master = framework::master_test_suite();
|
||||||
auto id = master.get(_name);
|
auto id = master.get(_name);
|
||||||
assert(id != INV_TEST_UNIT_ID);
|
soltestAssert(id != INV_TEST_UNIT_ID, "Removing non-existent test suite!");
|
||||||
master.remove(id);
|
master.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +279,6 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
|
|||||||
"ABIDecoderTest",
|
"ABIDecoderTest",
|
||||||
"ABIEncoderTest",
|
"ABIEncoderTest",
|
||||||
"SolidityAuctionRegistrar",
|
"SolidityAuctionRegistrar",
|
||||||
"SolidityFixedFeeRegistrar",
|
|
||||||
"SolidityWallet",
|
"SolidityWallet",
|
||||||
"GasMeterTests",
|
"GasMeterTests",
|
||||||
"GasCostTests",
|
"GasCostTests",
|
||||||
|
1
test/cmdlineTests/hashes/args
Normal file
1
test/cmdlineTests/hashes/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--hashes
|
28
test/cmdlineTests/hashes/input.sol
Normal file
28
test/cmdlineTests/hashes/input.sol
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
24
test/cmdlineTests/hashes/output
Normal file
24
test/cmdlineTests/hashes/output
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
======= hashes/input.sol:C =======
|
||||||
|
Function signatures:
|
||||||
|
3fc03eeb: f((uint256))
|
||||||
|
|
||||||
|
Error signatures:
|
||||||
|
619a0bb7: err(uint256,uint256)
|
||||||
|
82b5f64f: fileLevelError(uint256)
|
||||||
|
8c41f45c: libraryError(uint256)
|
||||||
|
|
||||||
|
Event signatures:
|
||||||
|
2d4dd5fe18ada5a020a9f5591539a8dc3010a5c074ba6a70e1c956659f02786a: ev(uint256)
|
||||||
|
81f3fb02f88d32d3bb08c80c9a622ca3b3223292f131c6ad049811f9a8a606dc: libraryEvent(uint256)
|
||||||
|
|
||||||
|
======= hashes/input.sol:L =======
|
||||||
|
Function signatures:
|
||||||
|
|
||||||
|
Error signatures:
|
||||||
|
8c41f45c: libraryError(uint256)
|
||||||
|
c61c03f5: libraryErrorUnused(uint256)
|
||||||
|
|
||||||
|
Event signatures:
|
||||||
|
81f3fb02f88d32d3bb08c80c9a622ca3b3223292f131c6ad049811f9a8a606dc: libraryEvent(uint256)
|
||||||
|
0a994ad3600197f16ffe1ea1101caea3174efe5ebd9ba9a75d6d5524c5de28cd: libraryEventUnused(uint256)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources":
|
||||||
|
{
|
||||||
|
"A":
|
||||||
|
{
|
||||||
|
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings":
|
||||||
|
{
|
||||||
|
"outputSelection":
|
||||||
|
{
|
||||||
|
"*": { "*": ["evm.methodIdentifiers"] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
{"contracts":{"A":{"C":{"evm":{"methodIdentifiers":{}}}}},"sources":{"A":{"id":0}}}
|
@ -3,8 +3,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"component": "general",
|
"component": "general",
|
||||||
"formattedMessage": "Cannot import url (\"in.yul\"): File not found.",
|
"formattedMessage": "Cannot import url (\"in.yul\"): File not found. Searched the following locations: \"\".",
|
||||||
"message": "Cannot import url (\"in.yul\"): File not found.",
|
"message": "Cannot import url (\"in.yul\"): File not found. Searched the following locations: \"\".",
|
||||||
"severity": "error",
|
"severity": "error",
|
||||||
"type": "IOError"
|
"type": "IOError"
|
||||||
},
|
},
|
||||||
|
@ -28,26 +28,26 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
REPO_ROOT="$(dirname "$0")"
|
|
||||||
|
|
||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
|
|
||||||
printTask "Running external tests..."
|
printTask "Running external tests..."
|
||||||
|
|
||||||
"$REPO_ROOT/externalTests/zeppelin.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/zeppelin.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/gnosis.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/gnosis.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/gnosis-v2.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/gnosis-v2.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/colony.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/colony.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/ens.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/ens.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/trident.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/trident.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/euler.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/euler.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/yield-liquidator.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/yield-liquidator.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/bleeps.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/bleeps.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/pool-together.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/pool-together.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/perpetual-pools.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/perpetual-pools.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/uniswap.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/uniswap.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/prb-math.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/prb-math.sh" "$@"
|
||||||
"$REPO_ROOT/externalTests/elementfi.sh" "$@"
|
"{$REPO_ROOT}/test/externalTests/elementfi.sh" "$@"
|
||||||
|
@ -24,13 +24,16 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
SELECTED_PRESETS="$3"
|
SELECTED_PRESETS="$3"
|
||||||
|
|
||||||
function compile_fn { npm run compile; }
|
function compile_fn { npm run compile; }
|
||||||
function test_fn { npm run test; }
|
# NOTE: `npm run test` runs `mocha` which seems to disable the gas reporter.
|
||||||
|
function test_fn { HARDHAT_DEPLOY_FIXTURE=true npx --no hardhat --no-compile test; }
|
||||||
|
|
||||||
function bleeps_test
|
function bleeps_test
|
||||||
{
|
{
|
||||||
@ -87,6 +90,7 @@ function bleeps_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
||||||
|
store_benchmark_report hardhat bleeps "$repo" "$preset"
|
||||||
done
|
done
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -73,6 +75,7 @@ function colony_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
||||||
|
store_benchmark_report truffle colony "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Requires "${REPO_ROOT}/scripts/common.sh" to be included before.
|
# Requires $REPO_ROOT to be defined and "${REPO_ROOT}/scripts/common.sh" to be included before.
|
||||||
|
|
||||||
CURRENT_EVM_VERSION=london
|
CURRENT_EVM_VERSION=london
|
||||||
|
|
||||||
@ -71,15 +71,23 @@ function setup_solc
|
|||||||
local binary_path="$3"
|
local binary_path="$3"
|
||||||
local solcjs_branch="${4:-master}"
|
local solcjs_branch="${4:-master}"
|
||||||
local install_dir="${5:-solc/}"
|
local install_dir="${5:-solc/}"
|
||||||
|
local solcjs_dir="$6"
|
||||||
|
|
||||||
[[ $binary_type == native || $binary_type == solcjs ]] || assertFail
|
[[ $binary_type == native || $binary_type == solcjs ]] || assertFail
|
||||||
|
[[ $binary_type == solcjs || $solcjs_dir == "" ]] || assertFail
|
||||||
|
|
||||||
cd "$test_dir"
|
cd "$test_dir"
|
||||||
|
|
||||||
if [[ $binary_type == solcjs ]]
|
if [[ $binary_type == solcjs ]]
|
||||||
then
|
then
|
||||||
printLog "Setting up solc-js..."
|
printLog "Setting up solc-js..."
|
||||||
git clone --depth 1 -b "$solcjs_branch" https://github.com/ethereum/solc-js.git "$install_dir"
|
if [[ $solcjs_dir == "" ]]; then
|
||||||
|
printLog "Cloning branch ${solcjs_branch}..."
|
||||||
|
git clone --depth 1 -b "$solcjs_branch" https://github.com/ethereum/solc-js.git "$install_dir"
|
||||||
|
else
|
||||||
|
printLog "Using local solc-js from ${solcjs_dir}..."
|
||||||
|
cp -ra "$solcjs_dir" solc
|
||||||
|
fi
|
||||||
|
|
||||||
pushd "$install_dir"
|
pushd "$install_dir"
|
||||||
npm install
|
npm install
|
||||||
@ -207,9 +215,19 @@ function force_truffle_compiler_settings
|
|||||||
echo "Compiler version (full): ${SOLCVERSION}"
|
echo "Compiler version (full): ${SOLCVERSION}"
|
||||||
echo "-------------------------------------"
|
echo "-------------------------------------"
|
||||||
|
|
||||||
# Forcing the settings should always work by just overwriting the solc object. Forcing them by using a
|
local compiler_settings gas_reporter_settings
|
||||||
# dedicated settings objects should only be the fallback.
|
compiler_settings=$(truffle_compiler_settings "$solc_path" "$preset" "$evm_version")
|
||||||
echo "module.exports['compilers'] = $(truffle_compiler_settings "$solc_path" "$preset" "$evm_version");" >> "$config_file"
|
gas_reporter_settings=$(eth_gas_reporter_settings "$preset")
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "require('eth-gas-reporter');"
|
||||||
|
echo "module.exports['mocha'] = {"
|
||||||
|
echo " reporter: 'eth-gas-reporter',"
|
||||||
|
echo " reporterOptions: ${gas_reporter_settings}"
|
||||||
|
echo "};"
|
||||||
|
|
||||||
|
echo "module.exports['compilers'] = ${compiler_settings};"
|
||||||
|
} >> "$config_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
function name_hardhat_default_export
|
function name_hardhat_default_export
|
||||||
@ -278,16 +296,21 @@ function force_hardhat_compiler_settings
|
|||||||
echo "Compiler version (full): ${SOLCVERSION}"
|
echo "Compiler version (full): ${SOLCVERSION}"
|
||||||
echo "-------------------------------------"
|
echo "-------------------------------------"
|
||||||
|
|
||||||
local settings
|
local compiler_settings gas_reporter_settings
|
||||||
settings=$(hardhat_compiler_settings "$SOLCVERSION_SHORT" "$preset" "$evm_version")
|
compiler_settings=$(hardhat_compiler_settings "$SOLCVERSION_SHORT" "$preset" "$evm_version")
|
||||||
|
gas_reporter_settings=$(eth_gas_reporter_settings "$preset")
|
||||||
if [[ $config_file == *\.js ]]; then
|
if [[ $config_file == *\.js ]]; then
|
||||||
[[ $config_var_name == "" ]] || assertFail
|
[[ $config_var_name == "" ]] || assertFail
|
||||||
echo "module.exports['solidity'] = ${settings}" >> "$config_file"
|
echo "require('hardhat-gas-reporter');"
|
||||||
|
echo "module.exports.gasReporter = ${gas_reporter_settings};"
|
||||||
|
echo "module.exports.solidity = ${compiler_settings};"
|
||||||
else
|
else
|
||||||
[[ $config_file == *\.ts ]] || assertFail
|
[[ $config_file == *\.ts ]] || assertFail
|
||||||
[[ $config_var_name != "" ]] || assertFail
|
[[ $config_var_name != "" ]] || assertFail
|
||||||
echo "${config_var_name}.solidity = {compilers: [${settings}]}" >> "$config_file"
|
echo 'import "hardhat-gas-reporter";'
|
||||||
fi
|
echo "${config_var_name}.gasReporter = ${gas_reporter_settings};"
|
||||||
|
echo "${config_var_name}.solidity = {compilers: [${compiler_settings}]};"
|
||||||
|
fi >> "$config_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
function truffle_verify_compiler_version
|
function truffle_verify_compiler_version
|
||||||
@ -320,21 +343,7 @@ function truffle_clean
|
|||||||
|
|
||||||
function hardhat_clean
|
function hardhat_clean
|
||||||
{
|
{
|
||||||
rm -rf artifacts/ cache/
|
rm -rf build/ artifacts/ cache/
|
||||||
}
|
|
||||||
|
|
||||||
function run_test
|
|
||||||
{
|
|
||||||
local compile_fn="$1"
|
|
||||||
local test_fn="$2"
|
|
||||||
|
|
||||||
replace_version_pragmas
|
|
||||||
|
|
||||||
printLog "Running compile function..."
|
|
||||||
time $compile_fn
|
|
||||||
|
|
||||||
printLog "Running test function..."
|
|
||||||
$test_fn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function settings_from_preset
|
function settings_from_preset
|
||||||
@ -368,6 +377,21 @@ function replace_global_solc
|
|||||||
export PATH="$PWD:$PATH"
|
export PATH="$PWD:$PATH"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function eth_gas_reporter_settings
|
||||||
|
{
|
||||||
|
local preset="$1"
|
||||||
|
|
||||||
|
echo "{"
|
||||||
|
echo " enabled: true,"
|
||||||
|
echo " gasPrice: 1," # Gas price does not matter to us at all. Set to whatever to avoid API call.
|
||||||
|
echo " noColors: true,"
|
||||||
|
echo " showTimeSpent: false," # We're not interested in test timing
|
||||||
|
echo " onlyCalledMethods: true," # Exclude entries with no gas for shorter report
|
||||||
|
echo " showMethodSig: true," # Should make diffs more stable if there are overloaded functions
|
||||||
|
echo " outputFile: \"$(gas_report_path "$preset")\""
|
||||||
|
echo "}"
|
||||||
|
}
|
||||||
|
|
||||||
function truffle_compiler_settings
|
function truffle_compiler_settings
|
||||||
{
|
{
|
||||||
local solc_path="$1"
|
local solc_path="$1"
|
||||||
@ -495,3 +519,121 @@ function external_test
|
|||||||
rm -rf "$DIR"
|
rm -rf "$DIR"
|
||||||
echo "Done."
|
echo "Done."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gas_report_path
|
||||||
|
{
|
||||||
|
local preset="$1"
|
||||||
|
|
||||||
|
echo "${DIR}/gas-report-${preset}.rst"
|
||||||
|
}
|
||||||
|
|
||||||
|
function gas_report_to_json
|
||||||
|
{
|
||||||
|
cat - | "${REPO_ROOT}/scripts/externalTests/parse_eth_gas_report.py" | jq '{gas: .}'
|
||||||
|
}
|
||||||
|
|
||||||
|
function detect_hardhat_artifact_dir
|
||||||
|
{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
function bytecode_size_json_from_truffle_artifacts
|
||||||
|
{
|
||||||
|
# NOTE: The output of this function is a series of concatenated JSON dicts rather than a list.
|
||||||
|
|
||||||
|
for artifact in build/contracts/*.json; do
|
||||||
|
if [[ $(jq '. | has("unlinked_binary")' "$artifact") == false ]]; then
|
||||||
|
# Each artifact represents compilation output for a single contract. Some top-level keys contain
|
||||||
|
# bits of Standard JSON output while others are generated by Truffle. Process it into a dict
|
||||||
|
# of the form `{"<file>": {"<contract>": <size>}}`.
|
||||||
|
# NOTE: The `bytecode` field starts with 0x, which is why we subtract 1 from size.
|
||||||
|
jq '{
|
||||||
|
(.ast.absolutePath): {
|
||||||
|
(.contractName): (.bytecode | length / 2 - 1)
|
||||||
|
}
|
||||||
|
}' "$artifact"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
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 `{"<file>": {"<contract>": <size>}}`,
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
|
||||||
|
function combine_artifact_json
|
||||||
|
{
|
||||||
|
# Combine all dicts into a list with `jq --slurp` and then use `reduce` to merge them into one
|
||||||
|
# big dict with keys of the form `"<file>:<contract>"`. Then run jq again to filter out items
|
||||||
|
# with zero size and put the rest under under a top-level `bytecode_size` key. Also add another
|
||||||
|
# key with total bytecode size.
|
||||||
|
# NOTE: The extra inner `bytecode_size` key is there only to make diffs more readable.
|
||||||
|
cat - |
|
||||||
|
jq --slurp 'reduce (.[] | to_entries[]) as {$key, $value} ({}; . + {
|
||||||
|
($key + ":" + ($value | to_entries[].key)): {
|
||||||
|
bytecode_size: $value | to_entries[].value
|
||||||
|
}
|
||||||
|
})' |
|
||||||
|
jq --indent 4 --sort-keys '{
|
||||||
|
bytecode_size: [. | to_entries[] | select(.value.bytecode_size > 0)] | from_entries,
|
||||||
|
total_bytecode_size: (reduce (. | to_entries[]) as {$key, $value} (0; . + $value.bytecode_size))
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
function project_info_json
|
||||||
|
{
|
||||||
|
local project_url="$1"
|
||||||
|
|
||||||
|
echo "{"
|
||||||
|
echo " \"project\": {"
|
||||||
|
# NOTE: Given that we clone with `--depth 1`, we'll only get useful output out of `git describe`
|
||||||
|
# if we directly check out a tag. Still better than nothing.
|
||||||
|
echo " \"version\": \"$(git describe --always)\","
|
||||||
|
echo " \"commit\": \"$(git rev-parse HEAD)\","
|
||||||
|
echo " \"url\": \"${project_url}\""
|
||||||
|
echo " }"
|
||||||
|
echo "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function store_benchmark_report
|
||||||
|
{
|
||||||
|
local framework="$1"
|
||||||
|
local project_name="$2"
|
||||||
|
local project_url="$3"
|
||||||
|
local preset="$4"
|
||||||
|
|
||||||
|
[[ $framework == truffle || $framework == hardhat ]] || assertFail
|
||||||
|
[[ " ${AVAILABLE_PRESETS[*]} " == *" $preset "* ]] || assertFail
|
||||||
|
|
||||||
|
local report_dir="${REPO_ROOT}/reports/externalTests"
|
||||||
|
local output_file="${report_dir}/benchmark-${project_name}-${preset}.json"
|
||||||
|
mkdir -p "$report_dir"
|
||||||
|
|
||||||
|
{
|
||||||
|
if [[ -e $(gas_report_path "$preset") ]]; then
|
||||||
|
gas_report_to_json < "$(gas_report_path "$preset")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"bytecode_size_json_from_${framework}_artifacts" | combine_artifact_json
|
||||||
|
project_info_json "$project_url"
|
||||||
|
} | jq --slurp "{\"${project_name}\": {\"${preset}\": add}}" --indent 4 --sort-keys > "$output_file"
|
||||||
|
}
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -84,6 +86,10 @@ function elementfi_test
|
|||||||
sed -i 's|delete _twoTokenPoolTokens\[poolId\];|delete _twoTokenPoolTokens[poolId].tokenA;delete _twoTokenPoolTokens[poolId].tokenB;|g' vault/balances/TwoTokenPoolsBalance.sol
|
sed -i 's|delete _twoTokenPoolTokens\[poolId\];|delete _twoTokenPoolTokens[poolId].tokenA;delete _twoTokenPoolTokens[poolId].tokenB;|g' vault/balances/TwoTokenPoolsBalance.sol
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
# The test suite uses forked mainnet and an expiration period that's too short.
|
||||||
|
# TODO: Remove when https://github.com/element-fi/elf-contracts/issues/243 is fixed.
|
||||||
|
sed -i 's|^\s*require(_expiration - block\.timestamp < _unitSeconds);\s*$||g' contracts/ConvergentCurvePool.sol
|
||||||
|
|
||||||
# Several tests fail unless we use the exact versions hard-coded in package-lock.json
|
# Several tests fail unless we use the exact versions hard-coded in package-lock.json
|
||||||
#neutralize_package_lock
|
#neutralize_package_lock
|
||||||
|
|
||||||
@ -97,6 +103,7 @@ function elementfi_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
||||||
|
store_benchmark_report hardhat elementfi "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -68,6 +70,7 @@ function ens_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
||||||
|
store_benchmark_report hardhat ens "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -68,6 +70,7 @@ function euler_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
||||||
|
store_benchmark_report hardhat euler "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -40,12 +42,12 @@ function gnosis_safe_test
|
|||||||
local config_file="truffle-config.js"
|
local config_file="truffle-config.js"
|
||||||
|
|
||||||
local compile_only_presets=(
|
local compile_only_presets=(
|
||||||
legacy-no-optimize # "Error: while migrating GnosisSafe: Returned error: base fee exceeds gas limit"
|
legacy-no-optimize # Compiles but migrations run out of gas: "Error: while migrating GnosisSafe: Returned error: base fee exceeds gas limit"
|
||||||
)
|
)
|
||||||
local settings_presets=(
|
local settings_presets=(
|
||||||
"${compile_only_presets[@]}"
|
"${compile_only_presets[@]}"
|
||||||
#ir-no-optimize # "YulException: Variable var_call_430_mpos is 1 slot(s) too deep inside the stack."
|
#ir-no-optimize # Compilation fails with "YulException: Variable var_call_430_mpos is 1 slot(s) too deep inside the stack."
|
||||||
#ir-optimize-evm-only # "YulException: Variable var_call_430_mpos is 1 slot(s) too deep inside the stack."
|
#ir-optimize-evm-only # Compilation fails with "YulException: Variable var_call_430_mpos is 1 slot(s) too deep inside the stack."
|
||||||
ir-optimize-evm+yul
|
ir-optimize-evm+yul
|
||||||
legacy-optimize-evm-only
|
legacy-optimize-evm-only
|
||||||
legacy-optimize-evm+yul
|
legacy-optimize-evm+yul
|
||||||
@ -65,12 +67,14 @@ function gnosis_safe_test
|
|||||||
neutralize_package_json_hooks
|
neutralize_package_json_hooks
|
||||||
force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")"
|
force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")"
|
||||||
npm install --package-lock
|
npm install --package-lock
|
||||||
|
npm install eth-gas-reporter
|
||||||
|
|
||||||
replace_version_pragmas
|
replace_version_pragmas
|
||||||
[[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist"
|
[[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist"
|
||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
||||||
|
store_benchmark_report truffle gnosis2 "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -42,11 +44,11 @@ function gnosis_safe_test
|
|||||||
local compile_only_presets=()
|
local compile_only_presets=()
|
||||||
local settings_presets=(
|
local settings_presets=(
|
||||||
"${compile_only_presets[@]}"
|
"${compile_only_presets[@]}"
|
||||||
#ir-no-optimize # "YulException: Variable var_call_430_mpos is 1 slot(s) too deep inside the stack."
|
#ir-no-optimize # Compilation fails with "YulException: Variable var_call_430_mpos is 1 slot(s) too deep inside the stack."
|
||||||
#ir-optimize-evm-only # "YulException: Variable var_call_430_mpos is 1 slot(s) too deep inside the stack."
|
#ir-optimize-evm-only # Compilation fails with "YulException: Variable var_call_430_mpos is 1 slot(s) too deep inside the stack."
|
||||||
ir-optimize-evm+yul
|
ir-optimize-evm+yul
|
||||||
#legacy-no-optimize # "Stack too deep" error
|
#legacy-no-optimize # Compilation fails with "Stack too deep" error
|
||||||
#legacy-optimize-evm-only # "Stack too deep" error
|
#legacy-optimize-evm-only # Compilation fails with "Stack too deep" error
|
||||||
legacy-optimize-evm+yul
|
legacy-optimize-evm+yul
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -63,12 +65,14 @@ function gnosis_safe_test
|
|||||||
neutralize_package_json_hooks
|
neutralize_package_json_hooks
|
||||||
force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")"
|
force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")"
|
||||||
npm install --package-lock
|
npm install --package-lock
|
||||||
|
npm install eth-gas-reporter
|
||||||
|
|
||||||
replace_version_pragmas
|
replace_version_pragmas
|
||||||
[[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist"
|
[[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist"
|
||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
||||||
|
store_benchmark_report truffle gnosis "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -68,6 +70,7 @@ function perpetual_pools_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
||||||
|
store_benchmark_report hardhat perpetual-pools "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -72,6 +74,7 @@ function pool_together_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
||||||
|
store_benchmark_report hardhat pool-together "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,13 +24,16 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
SELECTED_PRESETS="$3"
|
SELECTED_PRESETS="$3"
|
||||||
|
|
||||||
function compile_fn { yarn compile; }
|
function compile_fn { yarn compile; }
|
||||||
function test_fn { yarn test; }
|
# NOTE: `yarn test` runs `mocha` which seems to disable the gas reporter.
|
||||||
|
function test_fn { npx --no hardhat --no-compile test; }
|
||||||
|
|
||||||
function prb_math_test
|
function prb_math_test
|
||||||
{
|
{
|
||||||
@ -70,11 +73,13 @@ function prb_math_test
|
|||||||
force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH"
|
force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH"
|
||||||
force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var"
|
force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var"
|
||||||
yarn install --no-lock-file
|
yarn install --no-lock-file
|
||||||
|
yarn add hardhat-gas-reporter
|
||||||
|
|
||||||
replace_version_pragmas
|
replace_version_pragmas
|
||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
||||||
|
store_benchmark_report hardhat prb-math "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,11 +26,9 @@ source test/externalTests/common.sh
|
|||||||
|
|
||||||
SOLJSON="$1"
|
SOLJSON="$1"
|
||||||
VERSION="$2"
|
VERSION="$2"
|
||||||
|
SOLCJS_CHECKOUT="$3" # optional
|
||||||
|
|
||||||
[[ $SOLJSON != "" && -f "$SOLJSON" && $VERSION != "" ]] || fail "Usage: $0 <path to soljson.js> <version>"
|
[[ $SOLJSON != "" && -f "$SOLJSON" && $VERSION != "" ]] || fail "Usage: $0 <path to soljson.js> <version> [<path to solc-js>]"
|
||||||
|
|
||||||
function compile_fn { echo "Nothing to compile."; }
|
|
||||||
function test_fn { npm test; }
|
|
||||||
|
|
||||||
function solcjs_test
|
function solcjs_test
|
||||||
{
|
{
|
||||||
@ -38,7 +36,7 @@ function solcjs_test
|
|||||||
SOLCJS_INPUT_DIR="$TEST_DIR"/test/externalTests/solc-js
|
SOLCJS_INPUT_DIR="$TEST_DIR"/test/externalTests/solc-js
|
||||||
|
|
||||||
# set up solc-js on the branch specified
|
# set up solc-js on the branch specified
|
||||||
setup_solc "$DIR" solcjs "$SOLJSON" master solc/
|
setup_solc "$DIR" solcjs "$SOLJSON" master solc/ "$SOLCJS_CHECKOUT"
|
||||||
cd solc/
|
cd solc/
|
||||||
|
|
||||||
printLog "Updating index.js file..."
|
printLog "Updating index.js file..."
|
||||||
@ -60,7 +58,10 @@ function solcjs_test
|
|||||||
echo "Updating package.json to version $VERSION"
|
echo "Updating package.json to version $VERSION"
|
||||||
npm version --allow-same-version --no-git-tag-version "$VERSION"
|
npm version --allow-same-version --no-git-tag-version "$VERSION"
|
||||||
|
|
||||||
run_test compile_fn test_fn
|
replace_version_pragmas
|
||||||
|
|
||||||
|
printLog "Running test function..."
|
||||||
|
npm test
|
||||||
}
|
}
|
||||||
|
|
||||||
external_test solc-js solcjs_test
|
external_test solc-js solcjs_test
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -92,6 +94,7 @@ function trident_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
||||||
|
store_benchmark_report hardhat trident "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -73,11 +75,13 @@ function uniswap_test
|
|||||||
yarn add @ethereumjs/tx@3.1.3
|
yarn add @ethereumjs/tx@3.1.3
|
||||||
|
|
||||||
yarn install
|
yarn install
|
||||||
|
yarn add hardhat-gas-reporter
|
||||||
|
|
||||||
replace_version_pragmas
|
replace_version_pragmas
|
||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
||||||
|
store_benchmark_report hardhat uniswap "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -65,9 +67,11 @@ function yield_liquidator_test
|
|||||||
npm install
|
npm install
|
||||||
|
|
||||||
replace_version_pragmas
|
replace_version_pragmas
|
||||||
|
neutralize_packaged_contracts
|
||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var"
|
||||||
|
store_benchmark_report hardhat yield_liquidator "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ set -e
|
|||||||
source scripts/common.sh
|
source scripts/common.sh
|
||||||
source test/externalTests/common.sh
|
source test/externalTests/common.sh
|
||||||
|
|
||||||
|
REPO_ROOT=$(realpath "$(dirname "$0")/../..")
|
||||||
|
|
||||||
verify_input "$@"
|
verify_input "$@"
|
||||||
BINARY_TYPE="$1"
|
BINARY_TYPE="$1"
|
||||||
BINARY_PATH="$2"
|
BINARY_PATH="$2"
|
||||||
@ -44,8 +46,8 @@ function zeppelin_test
|
|||||||
)
|
)
|
||||||
local settings_presets=(
|
local settings_presets=(
|
||||||
"${compile_only_presets[@]}"
|
"${compile_only_presets[@]}"
|
||||||
#ir-no-optimize # "YulException: Variable var_account_852 is 4 slot(s) too deep inside the stack."
|
#ir-no-optimize # Compilation fails with "YulException: Variable var_account_852 is 4 slot(s) too deep inside the stack."
|
||||||
#ir-optimize-evm-only # "YulException: Variable var_account_852 is 4 slot(s) too deep inside the stack."
|
#ir-optimize-evm-only # Compilation fails with "YulException: Variable var_account_852 is 4 slot(s) too deep inside the stack."
|
||||||
legacy-no-optimize
|
legacy-no-optimize
|
||||||
legacy-optimize-evm-only
|
legacy-optimize-evm-only
|
||||||
legacy-optimize-evm+yul
|
legacy-optimize-evm+yul
|
||||||
@ -66,6 +68,7 @@ function zeppelin_test
|
|||||||
|
|
||||||
for preset in $SELECTED_PRESETS; do
|
for preset in $SELECTED_PRESETS; do
|
||||||
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn
|
||||||
|
store_benchmark_report hardhat zeppelin "$repo" "$preset"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +435,7 @@ TestCase::TestResult SemanticTest::runTest(
|
|||||||
{
|
{
|
||||||
soltestAssert(
|
soltestAssert(
|
||||||
m_allowNonExistingFunctions ||
|
m_allowNonExistingFunctions ||
|
||||||
m_compiler.methodIdentifiers(m_compiler.lastContractName(m_sources.mainSourceFile)).isMember(test.call().signature),
|
m_compiler.interfaceSymbols(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].isMember(test.call().signature),
|
||||||
"The function " + test.call().signature + " is not known to the compiler"
|
"The function " + test.call().signature + " is not known to the compiler"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2582,6 +2582,55 @@ BOOST_AUTO_TEST_CASE(dev_struct_getter_override)
|
|||||||
checkNatspec(sourceCode, "Thing", natspec2, false);
|
checkNatspec(sourceCode, "Thing", natspec2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(dev_struct_getter_override_no_return_name)
|
||||||
|
{
|
||||||
|
char const *sourceCode = R"(
|
||||||
|
interface IThing {
|
||||||
|
///@return
|
||||||
|
function value(uint) external returns (uint128,uint128);
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Thing is IThing {
|
||||||
|
struct Value {
|
||||||
|
uint128 x;
|
||||||
|
uint128 A;
|
||||||
|
}
|
||||||
|
mapping(uint=>Value) public override value;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
char const *natspec = R"ABCDEF({
|
||||||
|
"methods":
|
||||||
|
{
|
||||||
|
"value(uint256)":
|
||||||
|
{
|
||||||
|
"returns":
|
||||||
|
{
|
||||||
|
"_0": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})ABCDEF";
|
||||||
|
|
||||||
|
char const *natspec2 = R"ABCDEF({
|
||||||
|
"methods": {},
|
||||||
|
"stateVariables":
|
||||||
|
{
|
||||||
|
"value":
|
||||||
|
{
|
||||||
|
"return": "x ",
|
||||||
|
"returns":
|
||||||
|
{
|
||||||
|
"x": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})ABCDEF";
|
||||||
|
|
||||||
|
checkNatspec(sourceCode, "IThing", natspec, false);
|
||||||
|
checkNatspec(sourceCode, "Thing", natspec2, false);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(dev_struct_getter_override_different_return_parameter_names)
|
BOOST_AUTO_TEST_CASE(dev_struct_getter_override_different_return_parameter_names)
|
||||||
{
|
{
|
||||||
char const *sourceCode = R"(
|
char const *sourceCode = R"(
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <test/TemporaryDirectory.h>
|
#include <test/TemporaryDirectory.h>
|
||||||
#include <test/libsolidity/util/SoltestErrors.h>
|
#include <test/libsolidity/util/SoltestErrors.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
@ -192,8 +193,8 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_root_name_only)
|
|||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
boost::filesystem::path driveLetter = boost::filesystem::current_path().root_name();
|
boost::filesystem::path driveLetter = boost::filesystem::current_path().root_name();
|
||||||
solAssert(!driveLetter.empty(), "");
|
soltestAssert(!driveLetter.empty(), "");
|
||||||
solAssert(driveLetter.is_relative(), "");
|
soltestAssert(driveLetter.is_relative(), "");
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(driveLetter, resolveSymlinks), expectedWorkDir);
|
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(driveLetter, resolveSymlinks), expectedWorkDir);
|
||||||
#endif
|
#endif
|
||||||
@ -212,13 +213,32 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_stripping_root_name)
|
|||||||
|
|
||||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||||
{
|
{
|
||||||
|
boost::filesystem::path workDir = boost::filesystem::current_path();
|
||||||
|
|
||||||
boost::filesystem::path normalizedPath = FileReader::normalizeCLIPathForVFS(
|
boost::filesystem::path normalizedPath = FileReader::normalizeCLIPathForVFS(
|
||||||
boost::filesystem::current_path(),
|
workDir,
|
||||||
resolveSymlinks
|
resolveSymlinks
|
||||||
);
|
);
|
||||||
BOOST_CHECK_EQUAL(normalizedPath, "/" / boost::filesystem::current_path().relative_path());
|
BOOST_CHECK_EQUAL(normalizedPath, "/" / workDir.relative_path());
|
||||||
BOOST_TEST(normalizedPath.root_name().empty());
|
BOOST_TEST(normalizedPath.root_name().empty());
|
||||||
BOOST_CHECK_EQUAL(normalizedPath.root_directory(), "/");
|
BOOST_CHECK_EQUAL(normalizedPath.root_directory(), "/");
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
string root = workDir.root_path().string();
|
||||||
|
soltestAssert(root.length() == 3 && root[1] == ':' && root[2] == '\\', "");
|
||||||
|
|
||||||
|
for (auto convert: {boost::to_lower_copy<string>, boost::to_upper_copy<string>})
|
||||||
|
{
|
||||||
|
boost::filesystem::path workDirWin = convert(root, locale()) / workDir.relative_path();
|
||||||
|
normalizedPath = FileReader::normalizeCLIPathForVFS(
|
||||||
|
workDirWin,
|
||||||
|
resolveSymlinks
|
||||||
|
);
|
||||||
|
BOOST_CHECK_EQUAL(normalizedPath, "/" / workDir.relative_path());
|
||||||
|
BOOST_TEST(normalizedPath.root_name().empty());
|
||||||
|
BOOST_CHECK_EQUAL(normalizedPath.root_directory(), "/");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
contract A {
|
contract A {
|
||||||
uint public x;
|
uint public x = 2;
|
||||||
constructor(uint) {}
|
constructor(uint) {}
|
||||||
function f() public { x = 4; }
|
function f() public returns(uint) { x = 4; }
|
||||||
}
|
}
|
||||||
contract B is A {
|
contract B is A {
|
||||||
constructor() A(f()) {}
|
constructor() A(f()) {}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// compileViaYul: also
|
// compileViaYul: false
|
||||||
// ----
|
// ----
|
||||||
// x() -> 4
|
// x() -> 4
|
@ -0,0 +1,12 @@
|
|||||||
|
contract A {
|
||||||
|
uint public x = 2;
|
||||||
|
constructor(uint) {}
|
||||||
|
function f() public returns(uint) { x = 4; }
|
||||||
|
}
|
||||||
|
contract B is A {
|
||||||
|
constructor() A(f()) {}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: true
|
||||||
|
// ----
|
||||||
|
// x() -> 2
|
@ -0,0 +1,14 @@
|
|||||||
|
contract C {
|
||||||
|
function f(string memory a, string memory b) public returns (string memory) {
|
||||||
|
return string.concat(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f(string,string): 0x40, 0x80, 32, "abcdabcdabcdabcdabcdabcdabcdabcd", 5, "bcdef" -> 0x20, 0x25, 0x6162636461626364616263646162636461626364616263646162636461626364, 44502269928904312298000709931354278973409164155382318144318241583783949107200
|
||||||
|
// f(string,string): 0x40, 0xa0, 64, "abcdabcdabcdabcdabcdabcdabcdabcd", "abcdabcdabcdabcdabcdabcdabcdabcd", 5, "bcdef" -> 0x20, 0x45, 0x6162636461626364616263646162636461626364616263646162636461626364, 0x6162636461626364616263646162636461626364616263646162636461626364, 44502269928904312298000709931354278973409164155382318144318241583783949107200
|
||||||
|
// f(string,string): 0x40, 0x80, 3, "abc", 3, "def" -> 0x20, 6, "abcdef"
|
||||||
|
// f(string,string): 0x40, 0xa0, 34, "abcdabcdabcdabcdabcdabcdabcdabcd", "ab", 30, "cdabcdabcdabcdabcdabcdabcdabcd" -> 0x20, 0x40, 0x6162636461626364616263646162636461626364616263646162636461626364, 0x6162636461626364616263646162636461626364616263646162636461626364
|
||||||
|
// f(string,string): 0x40, 0xa0, 34, "abcdabcdabcdabcdabcdabcdabcdabcd", "ab", 34, "cdabcdabcdabcdabcdabcdabcdabcdab", "cd" -> 0x20, 0x44, 0x6162636461626364616263646162636461626364616263646162636461626364, 0x6162636461626364616263646162636461626364616263646162636461626364, 44048183293808120317390542201052832727062033572611867748297851798484192067584
|
||||||
|
// f(string,string): 0x40, 0x80, 3, "abc", 30, "dabcdabcdabcdabcdabcdabcdabcda" -> 0x20, 0x21, 0x6162636461626364616263646162636461626364616263646162636461626364, 43874346312576839672212443538448152585028080127215369968075725190498334277632
|
@ -0,0 +1,37 @@
|
|||||||
|
contract C{
|
||||||
|
string s = "bcdef";
|
||||||
|
|
||||||
|
function f(string memory a) public returns (string memory) {
|
||||||
|
return string.concat(a, "bcdef");
|
||||||
|
}
|
||||||
|
function g(string calldata a) public returns (string memory) {
|
||||||
|
return string.concat(a, "abcdefghabcdefghabcdefghabcdefghab");
|
||||||
|
}
|
||||||
|
function h(string calldata a) public returns (string memory) {
|
||||||
|
return string.concat(a, s);
|
||||||
|
}
|
||||||
|
function j(string calldata a) public returns (string memory) {
|
||||||
|
string storage ref = s;
|
||||||
|
return string.concat(a, ref, s);
|
||||||
|
}
|
||||||
|
function k(string calldata a, bytes memory b) public returns (string memory) {
|
||||||
|
return string.concat(a, string(b));
|
||||||
|
}
|
||||||
|
function slice(string calldata a) public returns (string memory) {
|
||||||
|
require(bytes(a).length > 2, "");
|
||||||
|
return string.concat(a[:2], a[2:]);
|
||||||
|
}
|
||||||
|
function strParam(bytes calldata a) public returns (string memory) {
|
||||||
|
return string.concat(string(a), "bcdef");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f(string): 0x20, 32, "abcdabcdabcdabcdabcdabcdabcdabcd" -> 0x20, 0x25, 0x6162636461626364616263646162636461626364616263646162636461626364, 44502269928904312298000709931354278973409164155382318144318241583783949107200
|
||||||
|
// g(string): 0x20, 32, "abcdabcdabcdabcdabcdabcdabcdabcd" -> 0x20, 0x42, 0x6162636461626364616263646162636461626364616263646162636461626364, 0x6162636465666768616263646566676861626364656667686162636465666768, 44047497324925121336511606693520958599579173549109180625971642598225011015680
|
||||||
|
// h(string): 0x20, 32, "abcdabcdabcdabcdabcdabcdabcdabcd" -> 0x20, 0x25, 0x6162636461626364616263646162636461626364616263646162636461626364, 44502269928904312298000709931354278973409164155382318144318241583783949107200
|
||||||
|
// j(string): 0x20, 32, "abcdabcdabcdabcdabcdabcdabcdabcd" -> 0x20, 0x2a, 0x6162636461626364616263646162636461626364616263646162636461626364, 44502269928944786876717917111204727192787026596791669343131645116682757734400
|
||||||
|
// k(string,bytes): 0x40, 0x80, 32, "abcdabcdabcdabcdabcdabcdabcdabcd", 5, "bcdef" -> 0x20, 0x25, 0x6162636461626364616263646162636461626364616263646162636461626364, 44502269928904312298000709931354278973409164155382318144318241583783949107200
|
||||||
|
// slice(string): 0x20, 4, "abcd" -> 0x20, 4, "abcd"
|
||||||
|
// strParam(bytes): 0x20, 32, "abcdabcdabcdabcdabcdabcdabcdabcd" -> 0x20, 0x25, 0x6162636461626364616263646162636461626364616263646162636461626364, 44502269928904312298000709931354278973409164155382318144318241583783949107200
|
@ -0,0 +1,10 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (string memory) {
|
||||||
|
return string.concat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileToEwasm: also
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x20, 0
|
@ -0,0 +1,27 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (string memory) {
|
||||||
|
string memory b = "";
|
||||||
|
return string.concat(
|
||||||
|
string.concat(b),
|
||||||
|
string.concat(b, b),
|
||||||
|
string.concat("", b),
|
||||||
|
string.concat(b, "")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function g() public returns (string memory) {
|
||||||
|
return string.concat("", "abc", hex"", "abc", unicode"");
|
||||||
|
}
|
||||||
|
|
||||||
|
function h() public returns (string memory) {
|
||||||
|
string memory b = "";
|
||||||
|
return string.concat(b, "abc", b, "abc", b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileToEwasm: also
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x20, 0
|
||||||
|
// g() -> 0x20, 6, "abcabc"
|
||||||
|
// h() -> 0x20, 6, "abcabc"
|
@ -0,0 +1,9 @@
|
|||||||
|
contract C {
|
||||||
|
function f(string memory a, string memory b, string memory c) public returns (string memory) {
|
||||||
|
return string.concat(string.concat(a, b), c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f(string,string,string): 0x60, 0x60, 0x60, 2, "ab" -> 0x20, 6, "ababab"
|
@ -0,0 +1,17 @@
|
|||||||
|
interface IBase {
|
||||||
|
function foo() external view;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Base is IBase {
|
||||||
|
function foo() public virtual view {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IExt is IBase {}
|
||||||
|
|
||||||
|
contract Ext is IExt, Base {}
|
||||||
|
|
||||||
|
contract T { function foo() public virtual view {} }
|
||||||
|
|
||||||
|
contract Impl is Ext, T {
|
||||||
|
function foo() public view override(IBase, Base, T) {}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
abstract contract IBase {
|
||||||
|
function foo() external view virtual;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Base is IBase {
|
||||||
|
function foo() public virtual override view {}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract contract IExt is IBase {}
|
||||||
|
|
||||||
|
contract Ext is IExt, Base {}
|
||||||
|
|
||||||
|
contract T { function foo() public virtual view {} }
|
||||||
|
|
||||||
|
contract Impl is Ext, T {
|
||||||
|
function foo() public view override(IBase, Base, T) {}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
interface IBase {
|
||||||
|
function foo() external view;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Base is IBase {
|
||||||
|
function foo() public virtual view {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IExt is IBase {}
|
||||||
|
|
||||||
|
contract Ext is IExt, Base {}
|
||||||
|
|
||||||
|
contract Impl is Ext {
|
||||||
|
function foo() public view {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9456: (211-240): Overriding function is missing "override" specifier.
|
||||||
|
// TypeError 4327: (211-240): Function needs to specify overridden contracts "Base" and "IBase".
|
@ -0,0 +1,16 @@
|
|||||||
|
interface IBase {
|
||||||
|
function foo() external view;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Base is IBase {
|
||||||
|
function foo() public virtual view {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IExt is IBase {}
|
||||||
|
|
||||||
|
contract Ext is IExt, Base {}
|
||||||
|
|
||||||
|
contract Impl is Ext {
|
||||||
|
function foo() public view override (IBase, Base) {}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,22 @@
|
|||||||
|
interface IBase {
|
||||||
|
function foo() external view;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Base1 is IBase { function foo() public virtual view {} }
|
||||||
|
contract Base2 is IBase { function foo() public virtual view {} }
|
||||||
|
|
||||||
|
interface IExt1a is IBase {}
|
||||||
|
interface IExt1b is IBase {}
|
||||||
|
interface IExt2a is IBase {}
|
||||||
|
interface IExt2b is IBase {}
|
||||||
|
|
||||||
|
contract Ext1 is IExt1a, IExt1b, Base1 {}
|
||||||
|
contract Ext2 is IExt2a, IExt2b, Base2 {}
|
||||||
|
|
||||||
|
contract Impl is Ext1, Ext2 {
|
||||||
|
function foo() public view {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9456: (424-453): Overriding function is missing "override" specifier.
|
||||||
|
// TypeError 9456: (424-453): Overriding function is missing "override" specifier.
|
||||||
|
// TypeError 4327: (424-453): Function needs to specify overridden contracts "Base1", "Base2" and "IBase".
|
@ -0,0 +1,18 @@
|
|||||||
|
interface IBase {
|
||||||
|
function foo() external view;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Base1 is IBase { function foo() public virtual view {} }
|
||||||
|
contract Base2 is IBase { function foo() public virtual view {} }
|
||||||
|
|
||||||
|
interface IExt1a is IBase {}
|
||||||
|
interface IExt1b is IBase {}
|
||||||
|
interface IExt2a is IBase {}
|
||||||
|
interface IExt2b is IBase {}
|
||||||
|
|
||||||
|
contract Ext1 is IExt1a, IExt1b, Base1 {}
|
||||||
|
contract Ext2 is IExt2a, IExt2b, Base2 {}
|
||||||
|
|
||||||
|
contract Impl is Ext1, Ext2 {
|
||||||
|
function foo() public view override (IBase, Base1, Base2) {}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
interface IBase {
|
||||||
|
function foo() external view;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Base1 is IBase { function foo() public virtual view {} }
|
||||||
|
contract Base2 is IBase { function foo() public virtual view {} }
|
||||||
|
|
||||||
|
interface IExt1a is IBase {}
|
||||||
|
abstract contract IExt1b is IBase {}
|
||||||
|
abstract contract IExt2a is IBase {}
|
||||||
|
interface IExt2b is IBase {}
|
||||||
|
|
||||||
|
contract Ext1 is IExt1a, IExt1b, Base1 {}
|
||||||
|
contract Ext2 is IExt2a, IExt2b, Base2 {}
|
||||||
|
|
||||||
|
contract Impl is Ext1, Ext2 {
|
||||||
|
function foo() public view override (IBase, Base1, Base2) {}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
contract C {
|
||||||
|
function g() public pure returns (string memory) {
|
||||||
|
return string.concat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 6359: (83-96): Return argument type function () pure returns (string memory) is not implicitly convertible to expected type (type of first return variable) string memory.
|
@ -0,0 +1,13 @@
|
|||||||
|
contract C {
|
||||||
|
function j() external {
|
||||||
|
string memory a = "hello";
|
||||||
|
string memory b = " world";
|
||||||
|
|
||||||
|
string memory d = string.concat(bytes(a), bytes(b));
|
||||||
|
string memory e = string.concat(a, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9977: (153-161): Invalid type for argument in the string.concat function call. string type is required, but t_bytes_memory_ptr provided.
|
||||||
|
// TypeError 9977: (163-171): Invalid type for argument in the string.concat function call. string type is required, but t_bytes_memory_ptr provided.
|
||||||
|
// TypeError 9977: (217-218): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
@ -0,0 +1,15 @@
|
|||||||
|
contract C {
|
||||||
|
string s;
|
||||||
|
function f(string calldata c, string calldata c1) public {
|
||||||
|
string memory a;
|
||||||
|
bytes16 b;
|
||||||
|
uint8[] memory num;
|
||||||
|
bytes1[] memory m;
|
||||||
|
string memory d = string.concat(a, b, c, num, s, "abc", m, c1, bytes(c1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9977: (232-233): Invalid type for argument in the string.concat function call. string type is required, but t_bytes16 provided.
|
||||||
|
// TypeError 9977: (238-241): Invalid type for argument in the string.concat function call. string type is required, but t_array$_t_uint8_$dyn_memory_ptr provided.
|
||||||
|
// TypeError 9977: (253-254): Invalid type for argument in the string.concat function call. string type is required, but t_array$_t_bytes1_$dyn_memory_ptr provided.
|
||||||
|
// TypeError 9977: (260-269): Invalid type for argument in the string.concat function call. string type is required, but t_bytes_calldata_ptr provided.
|
@ -0,0 +1,7 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public {
|
||||||
|
string.concat([], [], []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 6378: (61-63): Unable to deduce common type for array elements.
|
@ -0,0 +1,40 @@
|
|||||||
|
contract C {
|
||||||
|
struct S {
|
||||||
|
uint x;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum E {A, B, C}
|
||||||
|
|
||||||
|
mapping(uint => E) m;
|
||||||
|
|
||||||
|
function f() public {
|
||||||
|
bool b;
|
||||||
|
uint u;
|
||||||
|
uint8 u8;
|
||||||
|
address a;
|
||||||
|
address payable ap;
|
||||||
|
function () external fext;
|
||||||
|
function () internal fint;
|
||||||
|
uint[] memory uDynamic;
|
||||||
|
uint[2] memory uStatic;
|
||||||
|
C c;
|
||||||
|
S memory s;
|
||||||
|
E e;
|
||||||
|
|
||||||
|
string.concat(b, u, u8, a, ap, fext, fint, uDynamic, uStatic, c, s, e, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9977: (426-427): Invalid type for argument in the string.concat function call. string type is required, but t_bool provided.
|
||||||
|
// TypeError 9977: (429-430): Invalid type for argument in the string.concat function call. string type is required, but t_uint256 provided.
|
||||||
|
// TypeError 9977: (432-434): Invalid type for argument in the string.concat function call. string type is required, but t_uint8 provided.
|
||||||
|
// TypeError 9977: (436-437): Invalid type for argument in the string.concat function call. string type is required, but t_address provided.
|
||||||
|
// TypeError 9977: (439-441): Invalid type for argument in the string.concat function call. string type is required, but t_address_payable provided.
|
||||||
|
// TypeError 9977: (443-447): Invalid type for argument in the string.concat function call. string type is required, but t_function_external_nonpayable$__$returns$__$ provided.
|
||||||
|
// TypeError 9977: (449-453): Invalid type for argument in the string.concat function call. string type is required, but t_function_internal_nonpayable$__$returns$__$ provided.
|
||||||
|
// TypeError 9977: (455-463): Invalid type for argument in the string.concat function call. string type is required, but t_array$_t_uint256_$dyn_memory_ptr provided.
|
||||||
|
// TypeError 9977: (465-472): Invalid type for argument in the string.concat function call. string type is required, but t_array$_t_uint256_$2_memory_ptr provided.
|
||||||
|
// TypeError 9977: (474-475): Invalid type for argument in the string.concat function call. string type is required, but t_contract$_C_$86 provided.
|
||||||
|
// TypeError 9977: (477-478): Invalid type for argument in the string.concat function call. string type is required, but t_struct$_S_$4_memory_ptr provided.
|
||||||
|
// TypeError 9977: (480-481): Invalid type for argument in the string.concat function call. string type is required, but t_enum$_E_$8 provided.
|
||||||
|
// TypeError 9977: (483-484): Invalid type for argument in the string.concat function call. string type is required, but t_mapping$_t_uint256_$_t_enum$_E_$8_$ provided.
|
@ -0,0 +1,58 @@
|
|||||||
|
contract C {
|
||||||
|
struct S {
|
||||||
|
uint x;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum E {A, B, C}
|
||||||
|
|
||||||
|
function f() public {
|
||||||
|
string.concat(
|
||||||
|
false,
|
||||||
|
1,
|
||||||
|
1e10,
|
||||||
|
1e-10,
|
||||||
|
0.1,
|
||||||
|
0x1234567,
|
||||||
|
0x11112222333344445555666677778888999900, // One byte less than an address
|
||||||
|
0x1111222233334444555566667777888899990000, // Address
|
||||||
|
0x111122223333444455556666777788889999000011, // One byte more than an address
|
||||||
|
0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff, // exactly 32 bytes
|
||||||
|
-0x0000000000000000000000000000000000000000000000000000000000000001, // exactly 32 bytes
|
||||||
|
bytes(bytes32(0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff))[:],
|
||||||
|
f,
|
||||||
|
(),
|
||||||
|
(0, 0),
|
||||||
|
[0],
|
||||||
|
[0][:],
|
||||||
|
[0][0],
|
||||||
|
new C(),
|
||||||
|
S(0),
|
||||||
|
E.A
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9640: (698-780): Explicit type conversion not allowed from "bytes32" to "bytes memory".
|
||||||
|
// TypeError 1227: (698-783): Index range access is only supported for dynamic calldata arrays.
|
||||||
|
// TypeError 1227: (865-871): Index range access is only supported for dynamic calldata arrays.
|
||||||
|
// TypeError 9977: (134-139): Invalid type for argument in the string.concat function call. string type is required, but t_bool provided.
|
||||||
|
// TypeError 9977: (153-154): Invalid type for argument in the string.concat function call. string type is required, but t_rational_1_by_1 provided.
|
||||||
|
// TypeError 9977: (168-172): Invalid type for argument in the string.concat function call. string type is required, but t_rational_10000000000_by_1 provided.
|
||||||
|
// TypeError 9977: (186-191): Invalid type for argument in the string.concat function call. string type is required, but t_rational_1_by_10000000000 provided.
|
||||||
|
// TypeError 9977: (205-208): Invalid type for argument in the string.concat function call. string type is required, but t_rational_1_by_10 provided.
|
||||||
|
// TypeError 9977: (222-231): Invalid type for argument in the string.concat function call. string type is required, but t_rational_19088743_by_1 provided.
|
||||||
|
// TypeError 9977: (245-285): Invalid type for argument in the string.concat function call. string type is required, but t_rational_380605192295934637532253317235440047844071680_by_1 provided.
|
||||||
|
// TypeError 9977: (336-378): Invalid type for argument in the string.concat function call. string type is required, but t_address provided.
|
||||||
|
// TypeError 9977: (405-449): Invalid type for argument in the string.concat function call. string type is required, but t_rational_24943341882306372405313753398341798975509081620497_by_1 provided.
|
||||||
|
// TypeError 9977: (496-562): Invalid type for argument in the string.concat function call. string type is required, but t_rational_30272441630670900764332283662402067049651745785153368133042924362431065855_by_1 provided.
|
||||||
|
// TypeError 9977: (597-664): Invalid type for argument in the string.concat function call. string type is required, but t_rational_minus_1_by_1 provided.
|
||||||
|
// TypeError 9977: (698-783): Invalid type for argument in the string.concat function call. string type is required, but t_bytes_memory_ptr_slice provided.
|
||||||
|
// TypeError 9977: (797-798): Invalid type for argument in the string.concat function call. string type is required, but t_function_internal_nonpayable$__$returns$__$ provided.
|
||||||
|
// TypeError 9977: (812-814): Invalid type for argument in the string.concat function call. string type is required, but t_tuple$__$ provided.
|
||||||
|
// TypeError 9977: (828-834): Invalid type for argument in the string.concat function call. string type is required, but t_tuple$_t_rational_0_by_1_$_t_rational_0_by_1_$ provided.
|
||||||
|
// TypeError 9977: (848-851): Invalid type for argument in the string.concat function call. string type is required, but t_array$_t_uint8_$1_memory_ptr provided.
|
||||||
|
// TypeError 9977: (865-871): Invalid type for argument in the string.concat function call. string type is required, but t_array$_t_uint8_$1_memory_ptr_slice provided.
|
||||||
|
// TypeError 9977: (885-891): Invalid type for argument in the string.concat function call. string type is required, but t_uint8 provided.
|
||||||
|
// TypeError 9977: (905-912): Invalid type for argument in the string.concat function call. string type is required, but t_contract$_C_$61 provided.
|
||||||
|
// TypeError 9977: (926-930): Invalid type for argument in the string.concat function call. string type is required, but t_struct$_S_$4_memory_ptr provided.
|
||||||
|
// TypeError 9977: (944-947): Invalid type for argument in the string.concat function call. string type is required, but t_enum$_E_$8 provided.
|
@ -0,0 +1,33 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
string.concat(
|
||||||
|
0,
|
||||||
|
-0,
|
||||||
|
0.0,
|
||||||
|
-0.0,
|
||||||
|
0e10,
|
||||||
|
-0e10,
|
||||||
|
0e-10,
|
||||||
|
-0e-10,
|
||||||
|
(0),
|
||||||
|
0x00,
|
||||||
|
-0x00,
|
||||||
|
0x0000000000000000000000000000000000000000000000000000000000000000, // exactly 32 bytes
|
||||||
|
-0x0000000000000000000000000000000000000000000000000000000000000000 // exactly 32 bytes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9977: (79-80): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (94-96): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (110-113): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (127-131): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (145-149): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (163-168): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (182-187): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (201-207): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (221-224): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (238-242): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (256-261): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (275-341): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
||||||
|
// TypeError 9977: (375-442): Invalid type for argument in the string.concat function call. string type is required, but t_rational_0_by_1 provided.
|
54
test/libyul/StackShufflingTest.cpp
Normal file
54
test/libyul/StackShufflingTest.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Unit tests for stack shuffling.
|
||||||
|
*/
|
||||||
|
#include <libyul/backends/evm/StackHelpers.h>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace solidity::langutil;
|
||||||
|
|
||||||
|
namespace solidity::yul::test
|
||||||
|
{
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(YulStackShuffling)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(swap_cycle)
|
||||||
|
{
|
||||||
|
std::vector<Scope::Variable> scopeVariables;
|
||||||
|
Scope::Function function;
|
||||||
|
std::vector<VariableSlot> v;
|
||||||
|
for (size_t i = 0; i < 17; ++i)
|
||||||
|
scopeVariables.emplace_back(Scope::Variable{""_yulstring, YulString{"v" + to_string(i)}});
|
||||||
|
for (size_t i = 0; i < 17; ++i)
|
||||||
|
v.emplace_back(VariableSlot{scopeVariables[i]});
|
||||||
|
|
||||||
|
Stack sourceStack{
|
||||||
|
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[9], v[10], v[11], v[12], v[13], v[14], v[15], v[16],
|
||||||
|
FunctionReturnLabelSlot{function}, FunctionReturnLabelSlot{function}, v[5]};
|
||||||
|
Stack targetStack{
|
||||||
|
v[1], v[0], v[2], v[3], v[4], v[5], v[6], v[7], v[9], v[10], v[11], v[12], v[13], v[14], v[15], v[16],
|
||||||
|
FunctionReturnLabelSlot{function}, JunkSlot{}, JunkSlot{}
|
||||||
|
};
|
||||||
|
// Used to hit a swapping cycle.
|
||||||
|
createStackLayout(sourceStack, targetStack, [](auto){}, [](auto){}, [](){});
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
}
|
381
test/scripts/fixtures/eth_gas_report_gnosis.rst
Normal file
381
test/scripts/fixtures/eth_gas_report_gnosis.rst
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
·----------------------------------------------------------------------------------------------------------------------------------------|---------------------------|-------------|------------------------------·
|
||||||
|
| Solc version: 0.8.10 · Optimizer enabled: true · Runs: 200 · Block limit: 100000000 gas │
|
||||||
|
·········································································································································|···························|·············|·······························
|
||||||
|
| Methods │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| Contract · Method · Min · Max · Avg · # calls · eur (avg) │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · getMessageHash(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · getMessageHashForSafe(address,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · getModules() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · isValidSignature(bytes,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · isValidSignature(bytes32,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · NAME() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · onERC1155BatchReceived(address,address,uint256[],uint256[],bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · onERC1155Received(address,address,uint256,uint256,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · onERC721Received(address,address,uint256,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · simulate(address,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · supportsInterface(bytes4) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · tokensReceived(address,address,address,uint256,bytes,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CompatibilityFallbackHandler · VERSION() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CreateCall · performCreate(uint256,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| CreateCall · performCreate2(uint256,bytes,bytes32) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DebugTransactionGuard · checkAfterExecution(bytes32,bool) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DebugTransactionGuard · checkTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DebugTransactionGuard · supportsInterface(bytes4) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DebugTransactionGuard · txNonces(bytes32) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DefaultCallbackHandler · NAME() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DefaultCallbackHandler · onERC1155BatchReceived(address,address,uint256[],uint256[],bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DefaultCallbackHandler · onERC1155Received(address,address,uint256,uint256,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DefaultCallbackHandler · onERC721Received(address,address,uint256,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DefaultCallbackHandler · supportsInterface(bytes4) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DefaultCallbackHandler · tokensReceived(address,address,address,uint256,bytes,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DefaultCallbackHandler · VERSION() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DelegateCallTransactionGuard · allowedTarget() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DelegateCallTransactionGuard · checkAfterExecution(bytes32,bool) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DelegateCallTransactionGuard · checkTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| DelegateCallTransactionGuard · supportsInterface(bytes4) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC1155Token · balanceOf(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC1155Token · mint(address,uint256,uint256,bytes) · 47934 · 59804 · 57826 · 6 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC1155Token · safeTransferFrom(address,address,uint256,uint256,bytes) · - · - · 53900 · 2 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · allowance(address,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · approve(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · balanceOf(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · decimals() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · decreaseAllowance(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · increaseAllowance(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · name() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · symbol() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · totalSupply() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · transfer(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20 · transferFrom(address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · allowance(address,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · approve(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · balanceOf(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · decimals() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · decreaseAllowance(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · increaseAllowance(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · name() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · symbol() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · totalSupply() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · transfer(address,uint256) · - · - · 51567 · 8 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · transferFrom(address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| FallbackManager · setFallbackHandler(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · addOwnerWithThreshold(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · approvedHashes(address,bytes32) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · approveHash(bytes32) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · changeThreshold(uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · checkNSignatures(bytes32,bytes,bytes,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · checkSignatures(bytes32,bytes,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · disableModule(address,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · domainSeparator() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · enableModule(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · encodeTransactionData(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes) · 59563 · 151736 · 94816 · 85 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · execTransactionFromModule(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · execTransactionFromModuleReturnData(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · getChainId() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · getModulesPaginated(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · getOwners() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · getStorageAt(uint256,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · getThreshold() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · getTransactionHash(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · isModuleEnabled(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · isOwner(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · nonce() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · removeOwner(address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · requiredTxGas(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · setFallbackHandler(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · setGuard(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · setup(address[],uint256,address,bytes,address,address,uint256,address) · 167642 · 263690 · 201944 · 49 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · signedMessages(bytes32) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · simulateAndRevert(address,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · swapOwner(address,address,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafe · VERSION() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · addOwnerWithThreshold(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · approvedHashes(address,bytes32) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · approveHash(bytes32) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · changeThreshold(uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · checkNSignatures(bytes32,bytes,bytes,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · checkSignatures(bytes32,bytes,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · disableModule(address,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · domainSeparator() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · enableModule(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · encodeTransactionData(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · execTransactionFromModule(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · execTransactionFromModuleReturnData(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · getChainId() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · getModulesPaginated(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · getOwners() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · getStorageAt(uint256,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · getThreshold() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · getTransactionHash(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · isModuleEnabled(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · isOwner(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · nonce() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · removeOwner(address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · requiredTxGas(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · setFallbackHandler(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · setGuard(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · setup(address[],uint256,address,bytes,address,address,uint256,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · signedMessages(bytes32) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · simulateAndRevert(address,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · swapOwner(address,address,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeL2 · VERSION() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeProxyFactory · calculateCreateProxyWithNonceAddress(address,bytes,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeProxyFactory · createProxy(address,bytes) · 105568 · 105580 · 105568 · 52 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeProxyFactory · createProxyWithCallback(address,bytes,uint256,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeProxyFactory · createProxyWithNonce(address,bytes,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeProxyFactory · proxyCreationCode() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GnosisSafeProxyFactory · proxyRuntimeCode() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| GuardManager · setGuard(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| Migration · migrate() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| Migration · migrationSingleton() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| Migration · safe120Singleton() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · DEFAULT_FALLBACK_VALUE() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenAnyReturn(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenAnyReturnAddress(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenAnyReturnBool(bool) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenAnyReturnUint(uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenAnyRevert() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenAnyRevertWithMessage(string) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenAnyRunOutOfGas() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenCalldataReturn(bytes,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenCalldataReturnAddress(bytes,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenCalldataReturnBool(bytes,bool) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenCalldataReturnUint(bytes,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenCalldataRevert(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenCalldataRevertWithMessage(bytes,string) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenCalldataRunOutOfGas(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenMethodReturn(bytes,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenMethodReturnAddress(bytes,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenMethodReturnBool(bytes,bool) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenMethodReturnUint(bytes,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenMethodRevert(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenMethodRevertWithMessage(bytes,string) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · givenMethodRunOutOfGas(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · invocationCount() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · invocationCountForCalldata(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · invocationCountForMethod(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · MOCKS_LIST_END_HASH() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · MOCKS_LIST_END() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · MOCKS_LIST_START() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · reset() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · SENTINEL_ANY_MOCKS() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MockContract · updateInvocationCount(bytes4,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ModuleManager · disableModule(address,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ModuleManager · enableModule(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ModuleManager · execTransactionFromModule(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ModuleManager · execTransactionFromModuleReturnData(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ModuleManager · getModulesPaginated(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ModuleManager · isModuleEnabled(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MultiSend · multiSend(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| MultiSendCallOnly · multiSend(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| OwnerManager · addOwnerWithThreshold(address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| OwnerManager · changeThreshold(uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| OwnerManager · getOwners() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| OwnerManager · getThreshold() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| OwnerManager · isOwner(address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| OwnerManager · removeOwner(address,address,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| OwnerManager · swapOwner(address,address,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ReentrancyTransactionGuard · checkAfterExecution(bytes32,bool) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ReentrancyTransactionGuard · checkTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes,address) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| ReentrancyTransactionGuard · supportsInterface(bytes4) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| SignMessageLib · getMessageHash(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| SignMessageLib · signMessage(bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| SimulateTxAccessor · simulate(address,uint256,bytes,uint8) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| StorageAccessible · getStorageAt(uint256,uint256) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| StorageAccessible · simulateAndRevert(address,bytes) · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| TestHandler · dudududu() · - · - · - · 0 · - │
|
||||||
|
·································|·······································································································|·············|·············|·············|···············|···············
|
||||||
|
| Deployments · · % of limit · │
|
||||||
|
·········································································································································|·············|·············|·············|···············|···············
|
||||||
|
| DelegateCallTransactionGuard · 283510 · 283522 · 283516 · 0.3 % · - │
|
||||||
|
·········································································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC1155Token · - · - · 525869 · 0.5 % · - │
|
||||||
|
·········································································································································|·············|·············|·············|···············|···············
|
||||||
|
| ERC20Token · - · - · 733462 · 0.7 % · - │
|
||||||
|
·----------------------------------------------------------------------------------------------------------------------------------------|-------------|-------------|-------------|---------------|--------------·
|
219
test/scripts/test_externalTests_parse_eth_gas_report.py
Normal file
219
test/scripts/test_externalTests_parse_eth_gas_report.py
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from dataclasses import asdict
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
from unittest_helpers import FIXTURE_DIR, load_fixture
|
||||||
|
|
||||||
|
# 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 externalTests.parse_eth_gas_report import parse_report, ReportParsingError, ReportValidationError
|
||||||
|
# pragma pylint: enable=import-error
|
||||||
|
|
||||||
|
ETH_GAS_REPORT_GNOSIS_RST_PATH = FIXTURE_DIR / 'eth_gas_report_gnosis.rst'
|
||||||
|
ETH_GAS_REPORT_GNOSIS_RST_CONTENT = load_fixture(ETH_GAS_REPORT_GNOSIS_RST_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
class TestEthGasReport(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.maxDiff = 10000
|
||||||
|
|
||||||
|
def test_parse_report(self):
|
||||||
|
parsed_report = parse_report(ETH_GAS_REPORT_GNOSIS_RST_CONTENT)
|
||||||
|
|
||||||
|
expected_report = {
|
||||||
|
'solc_version': '0.8.10',
|
||||||
|
'optimize': True,
|
||||||
|
'runs': 200,
|
||||||
|
'block_limit': 100000000,
|
||||||
|
'total_method_gas': 57826 * 6 + 53900 * 2 + 51567 * 8 + 94816 * 85 + 201944 * 49 + 105568 * 52,
|
||||||
|
'total_deployment_gas': 283516 + 525869 + 733462,
|
||||||
|
'contracts': {
|
||||||
|
'DelegateCallTransactionGuard': {
|
||||||
|
'total_method_gas': 0,
|
||||||
|
'min_deployment_gas': 283510,
|
||||||
|
'max_deployment_gas': 283522,
|
||||||
|
'avg_deployment_gas': 283516,
|
||||||
|
'methods': None,
|
||||||
|
},
|
||||||
|
'ERC1155Token': {
|
||||||
|
'total_method_gas': 57826 * 6 + 53900 * 2,
|
||||||
|
'min_deployment_gas': None,
|
||||||
|
'max_deployment_gas': None,
|
||||||
|
'avg_deployment_gas': 525869,
|
||||||
|
'methods': {
|
||||||
|
'mint(address,uint256,uint256,bytes)': {
|
||||||
|
'total_gas': 57826 * 6,
|
||||||
|
'min_gas': 47934,
|
||||||
|
'max_gas': 59804,
|
||||||
|
'avg_gas': 57826,
|
||||||
|
'call_count': 6
|
||||||
|
},
|
||||||
|
'safeTransferFrom(address,address,uint256,uint256,bytes)': {
|
||||||
|
'total_gas': 53900 * 2,
|
||||||
|
'min_gas': 53900,
|
||||||
|
'max_gas': 53900,
|
||||||
|
'avg_gas': 53900,
|
||||||
|
'call_count': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'ERC20Token': {
|
||||||
|
'total_method_gas': 51567 * 8,
|
||||||
|
'min_deployment_gas': None,
|
||||||
|
'max_deployment_gas': None,
|
||||||
|
'avg_deployment_gas': 733462,
|
||||||
|
'methods': {
|
||||||
|
'transfer(address,uint256)': {
|
||||||
|
'total_gas': 51567 * 8,
|
||||||
|
'min_gas': 51567,
|
||||||
|
'max_gas': 51567,
|
||||||
|
'avg_gas': 51567,
|
||||||
|
'call_count': 8,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'GnosisSafe': {
|
||||||
|
'total_method_gas': 94816 * 85 + 201944 * 49,
|
||||||
|
'min_deployment_gas': None,
|
||||||
|
'max_deployment_gas': None,
|
||||||
|
'avg_deployment_gas': None,
|
||||||
|
'methods': {
|
||||||
|
'execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)': {
|
||||||
|
'total_gas': 94816 * 85,
|
||||||
|
'min_gas': 59563,
|
||||||
|
'max_gas': 151736,
|
||||||
|
'avg_gas': 94816,
|
||||||
|
'call_count': 85,
|
||||||
|
},
|
||||||
|
'setup(address[],uint256,address,bytes,address,address,uint256,address)': {
|
||||||
|
'total_gas': 201944 * 49,
|
||||||
|
'min_gas': 167642,
|
||||||
|
'max_gas': 263690,
|
||||||
|
'avg_gas': 201944,
|
||||||
|
'call_count': 49,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'GnosisSafeProxyFactory': {
|
||||||
|
'total_method_gas': 105568 * 52,
|
||||||
|
'min_deployment_gas': None,
|
||||||
|
'max_deployment_gas': None,
|
||||||
|
'avg_deployment_gas': None,
|
||||||
|
'methods': {
|
||||||
|
'createProxy(address,bytes)': {
|
||||||
|
'total_gas': 105568 * 52,
|
||||||
|
'min_gas': 105568,
|
||||||
|
'max_gas': 105580,
|
||||||
|
'avg_gas': 105568,
|
||||||
|
'call_count': 52,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.assertEqual(asdict(parsed_report), expected_report)
|
||||||
|
|
||||||
|
def test_parse_report_should_fail_if_report_is_empty(self):
|
||||||
|
text_report = ""
|
||||||
|
with self.assertRaises(ReportValidationError) as manager:
|
||||||
|
parse_report(text_report)
|
||||||
|
self.assertEqual(str(manager.exception), "Report header not found.")
|
||||||
|
|
||||||
|
def test_parse_report_should_fail_if_report_has_no_header(self):
|
||||||
|
text_report = dedent("""
|
||||||
|
| Methods |
|
||||||
|
| ERC1155Token · mint() · 1 · 3 · 2 · 6 · - |
|
||||||
|
| Deployments · · % of limit · │
|
||||||
|
| ERC1155Token · - · - · 5 · 1 % · - |
|
||||||
|
""").strip('\n')
|
||||||
|
with self.assertRaises(ReportValidationError) as manager:
|
||||||
|
parse_report(text_report)
|
||||||
|
self.assertEqual(str(manager.exception), "Report header not found.")
|
||||||
|
|
||||||
|
def test_parse_report_should_fail_if_data_rows_have_no_headers(self):
|
||||||
|
text_report = dedent("""
|
||||||
|
| ERC1155Token · mint() · 1 · 3 · 2 · 6 · - |
|
||||||
|
""").strip('\n')
|
||||||
|
expected_message = dedent("""
|
||||||
|
Parsing error on line 1: Found data row without a section header.
|
||||||
|
| ERC1155Token | mint() | 1 | 3 | 2 | 6 | - |
|
||||||
|
""").strip('\n')
|
||||||
|
|
||||||
|
with self.assertRaises(ReportParsingError) as manager:
|
||||||
|
parse_report(text_report)
|
||||||
|
self.assertEqual(str(manager.exception), expected_message)
|
||||||
|
|
||||||
|
def test_parse_report_should_fail_if_report_has_more_than_one_header(self):
|
||||||
|
text_report = dedent("""
|
||||||
|
| Solc version: 0.8.10 · Optimizer enabled: true · Runs: 200 · Block limit: 100000000 gas |
|
||||||
|
| Solc version: 0.8.9 · Optimizer enabled: false · Runs: 111 · Block limit: 999999999 gas |
|
||||||
|
""").strip('\n')
|
||||||
|
expected_message = dedent("""
|
||||||
|
Parsing error on line 2: Duplicate report header.
|
||||||
|
| Solc version: 0.8.9 | Optimizer enabled: false | Runs: 111 | Block limit: 999999999 gas |
|
||||||
|
""").strip('\n')
|
||||||
|
|
||||||
|
with self.assertRaises(ReportParsingError) as manager:
|
||||||
|
parse_report(text_report)
|
||||||
|
self.assertEqual(str(manager.exception), expected_message)
|
||||||
|
|
||||||
|
def test_parse_report_should_fail_if_row_matching_same_method_call_appears_twice(self):
|
||||||
|
text_report = dedent("""
|
||||||
|
| Methods |
|
||||||
|
| ERC1155Token · mint() · 47934 · 59804 · 57826 · 6 · - |
|
||||||
|
| ERC1155Token · mint() · 11111 · 22222 · 33333 · 4 · - |
|
||||||
|
""").strip('\n')
|
||||||
|
expected_message = dedent("""
|
||||||
|
Parsing error on line 3: Duplicate method row for 'ERC1155Token.mint()'.
|
||||||
|
| ERC1155Token | mint() | 11111 | 22222 | 33333 | 4 | - |
|
||||||
|
""").strip('\n')
|
||||||
|
|
||||||
|
with self.assertRaises(ReportParsingError) as manager:
|
||||||
|
parse_report(text_report)
|
||||||
|
self.assertEqual(str(manager.exception), expected_message)
|
||||||
|
|
||||||
|
def test_parse_report_should_fail_if_row_matching_same_contract_deployment_appears_twice(self):
|
||||||
|
text_report = dedent("""
|
||||||
|
| Deployments · · % of limit · │
|
||||||
|
| ERC1155Token · - · - · 525869 · 0.5 % · - |
|
||||||
|
| ERC1155Token · - · - · 111111 · 0.6 % · - |
|
||||||
|
""").strip('\n')
|
||||||
|
expected_message = dedent("""
|
||||||
|
Parsing error on line 3: Duplicate contract deployment row for 'ERC1155Token'.
|
||||||
|
| ERC1155Token | - | - | 111111 | 0.6 % | - |
|
||||||
|
""").strip('\n')
|
||||||
|
|
||||||
|
with self.assertRaises(ReportParsingError) as manager:
|
||||||
|
parse_report(text_report)
|
||||||
|
self.assertEqual(str(manager.exception), expected_message)
|
||||||
|
|
||||||
|
def test_parse_report_should_fail_if_method_row_appears_under_deployments_header(self):
|
||||||
|
text_report = dedent("""
|
||||||
|
| Deployments · · % of limit · │
|
||||||
|
| ERC1155Token · mint() · 47934 · 59804 · 57826 · 6 · - |
|
||||||
|
""").strip('\n')
|
||||||
|
expected_message = dedent("""
|
||||||
|
Parsing error on line 2: Expected a table row with deployment details.
|
||||||
|
| ERC1155Token | mint() | 47934 | 59804 | 57826 | 6 | - |
|
||||||
|
""").strip('\n')
|
||||||
|
|
||||||
|
with self.assertRaises(ReportParsingError) as manager:
|
||||||
|
parse_report(text_report)
|
||||||
|
self.assertEqual(str(manager.exception), expected_message)
|
||||||
|
|
||||||
|
def test_parse_report_should_fail_if_deployment_row_appears_under_methods_header(self):
|
||||||
|
text_report = dedent("""
|
||||||
|
| Methods |
|
||||||
|
| ERC1155Token · - · - · 525869 · 5 · - |
|
||||||
|
""").strip('\n')
|
||||||
|
expected_message = dedent("""
|
||||||
|
Parsing error on line 2: Expected a table row with method details.
|
||||||
|
| ERC1155Token | - | - | 525869 | 5 | - |
|
||||||
|
""").strip('\n')
|
||||||
|
|
||||||
|
with self.assertRaises(ReportParsingError) as manager:
|
||||||
|
parse_report(text_report)
|
||||||
|
self.assertEqual(str(manager.exception), expected_message)
|
@ -100,7 +100,7 @@ ImportCheck checkImport(
|
|||||||
return ImportCheck::OK();
|
return ImportCheck::OK();
|
||||||
|
|
||||||
static regex const sourceNotFoundErrorRegex{
|
static regex const sourceNotFoundErrorRegex{
|
||||||
R"(^Error \(6275\): Source ".+" not found: (.*)\.\n)"
|
R"(^Error \(6275\): Source "[^"]+" not found: (.*)\.\n)"
|
||||||
R"(\s*--> .*<stdin>:\d+:\d+:\n)"
|
R"(\s*--> .*<stdin>:\d+:\d+:\n)"
|
||||||
R"(\s*\|\n)"
|
R"(\s*\|\n)"
|
||||||
R"(\d+\s*\| import '.+';\n)"
|
R"(\d+\s*\| import '.+';\n)"
|
||||||
@ -110,12 +110,12 @@ ImportCheck checkImport(
|
|||||||
smatch submatches;
|
smatch submatches;
|
||||||
if (!regex_match(cliResult.stderrContent, submatches, sourceNotFoundErrorRegex))
|
if (!regex_match(cliResult.stderrContent, submatches, sourceNotFoundErrorRegex))
|
||||||
return ImportCheck::Unknown("Unexpected stderr content: '" + cliResult.stderrContent + "'");
|
return ImportCheck::Unknown("Unexpected stderr content: '" + cliResult.stderrContent + "'");
|
||||||
if (submatches[1] != "File not found" && submatches[1] != "File outside of allowed directories")
|
if (submatches[1] != "File not found" && !boost::starts_with(string(submatches[1]), "File outside of allowed directories"))
|
||||||
return ImportCheck::Unknown("Unexpected error message: '" + cliResult.stderrContent + "'");
|
return ImportCheck::Unknown("Unexpected error message: '" + cliResult.stderrContent + "'");
|
||||||
|
|
||||||
if (submatches[1] == "File not found")
|
if (submatches[1] == "File not found")
|
||||||
return ImportCheck::FileNotFound();
|
return ImportCheck::FileNotFound();
|
||||||
else if (submatches[1] == "File outside of allowed directories")
|
else if (boost::starts_with(string(submatches[1]), "File outside of allowed directories"))
|
||||||
return ImportCheck::PathDisallowed();
|
return ImportCheck::PathDisallowed();
|
||||||
else
|
else
|
||||||
return ImportCheck::Unknown("Unexpected error message '" + submatches[1].str() + "'");
|
return ImportCheck::Unknown("Unexpected error message '" + submatches[1].str() + "'");
|
||||||
|
@ -58,7 +58,7 @@ optional<CompilerOutput> SolidityCompilationFramework::compileContract()
|
|||||||
else
|
else
|
||||||
contractName = m_compilerInput.contractName;
|
contractName = m_compilerInput.contractName;
|
||||||
evmasm::LinkerObject obj = m_compiler.object(contractName);
|
evmasm::LinkerObject obj = m_compiler.object(contractName);
|
||||||
Json::Value methodIdentifiers = m_compiler.methodIdentifiers(contractName);
|
Json::Value methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"];
|
||||||
return CompilerOutput{obj.bytecode, methodIdentifiers};
|
return CompilerOutput{obj.bytecode, methodIdentifiers};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ public:
|
|||||||
/// @returns method identifiers in contract called @param _contractName.
|
/// @returns method identifiers in contract called @param _contractName.
|
||||||
Json::Value methodIdentifiers(std::string const& _contractName)
|
Json::Value methodIdentifiers(std::string const& _contractName)
|
||||||
{
|
{
|
||||||
return m_compiler.methodIdentifiers(_contractName);
|
return m_compiler.interfaceSymbols(_contractName)["methods"];
|
||||||
}
|
}
|
||||||
/// @returns Compilation output comprising EVM bytecode and list of
|
/// @returns Compilation output comprising EVM bytecode and list of
|
||||||
/// method identifiers in contract if compilation is successful,
|
/// method identifiers in contract if compilation is successful,
|
||||||
|
Loading…
Reference in New Issue
Block a user