From 9fb77b139cdca101b6582e63f466771e679ecc7b Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 9 Nov 2021 13:25:00 +0100 Subject: [PATCH 0001/1704] Keep canonical form of Yul code at all times. --- libyul/optimiser/BlockFlattener.cpp | 12 ++++++++++++ libyul/optimiser/BlockFlattener.h | 2 +- libyul/optimiser/CircularReferencesPruner.cpp | 2 ++ libyul/optimiser/ExpressionJoiner.cpp | 4 +++- libyul/optimiser/FunctionGrouper.h | 2 +- libyul/optimiser/OptimizerUtilities.h | 2 ++ libyul/optimiser/Suite.cpp | 2 +- libyul/optimiser/UnusedPruner.cpp | 7 +++++++ libyul/optimiser/UnusedPruner.h | 4 +--- 9 files changed, 30 insertions(+), 7 deletions(-) diff --git a/libyul/optimiser/BlockFlattener.cpp b/libyul/optimiser/BlockFlattener.cpp index bcbe19c18d..0bb828ee5a 100644 --- a/libyul/optimiser/BlockFlattener.cpp +++ b/libyul/optimiser/BlockFlattener.cpp @@ -43,3 +43,15 @@ void BlockFlattener::operator()(Block& _block) } ); } + +void BlockFlattener::run(OptimiserStepContext&, Block& _ast) +{ + BlockFlattener flattener; + for (auto& statement: _ast.statements) + if (auto* block = get_if(&statement)) + flattener(*block); + else if (auto* function = get_if(&statement)) + flattener(function->body); + else + yulAssert(false, "BlockFlattener requires the FunctionGrouper."); +} diff --git a/libyul/optimiser/BlockFlattener.h b/libyul/optimiser/BlockFlattener.h index 87a1af7cf1..3825647de3 100644 --- a/libyul/optimiser/BlockFlattener.h +++ b/libyul/optimiser/BlockFlattener.h @@ -27,7 +27,7 @@ class BlockFlattener: public ASTModifier { public: static constexpr char const* name{"BlockFlattener"}; - static void run(OptimiserStepContext&, Block& _ast) { BlockFlattener{}(_ast); } + static void run(OptimiserStepContext&, Block& _ast); using ASTModifier::operator(); void operator()(Block& _block) override; diff --git a/libyul/optimiser/CircularReferencesPruner.cpp b/libyul/optimiser/CircularReferencesPruner.cpp index 1078779c5b..ba1fbf11da 100644 --- a/libyul/optimiser/CircularReferencesPruner.cpp +++ b/libyul/optimiser/CircularReferencesPruner.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -29,6 +30,7 @@ using namespace solidity::yul; void CircularReferencesPruner::run(OptimiserStepContext& _context, Block& _ast) { CircularReferencesPruner{_context.reservedIdentifiers}(_ast); + FunctionGrouper::run(_context, _ast); } void CircularReferencesPruner::operator()(Block& _block) diff --git a/libyul/optimiser/ExpressionJoiner.cpp b/libyul/optimiser/ExpressionJoiner.cpp index 9d1df86947..dbb684007c 100644 --- a/libyul/optimiser/ExpressionJoiner.cpp +++ b/libyul/optimiser/ExpressionJoiner.cpp @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -37,9 +38,10 @@ using namespace std; using namespace solidity; using namespace solidity::yul; -void ExpressionJoiner::run(OptimiserStepContext&, Block& _ast) +void ExpressionJoiner::run(OptimiserStepContext& _context, Block& _ast) { ExpressionJoiner{_ast}(_ast); + FunctionGrouper::run(_context, _ast); } diff --git a/libyul/optimiser/FunctionGrouper.h b/libyul/optimiser/FunctionGrouper.h index fa54099369..57ea80cac9 100644 --- a/libyul/optimiser/FunctionGrouper.h +++ b/libyul/optimiser/FunctionGrouper.h @@ -34,7 +34,7 @@ struct OptimiserStepContext; * all function definitions. * * After this step, a block is of the form - * { { I...} F... } + * { { I... } F... } * Where I are (non-function-definition) instructions and F are function definitions. */ class FunctionGrouper diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index 09ea9ed5a3..d80b16316a 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -37,6 +37,8 @@ namespace solidity::yul { /// Removes statements that are just empty blocks (non-recursive). +/// If this is run on the outermost block, the FunctionGrouper should be run afterwards to keep +/// the canonical form. void removeEmptyBlocks(Block& _block); /// Returns true if a given literal can not be used as an identifier. diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 32ea08dbe1..766cc93b90 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -118,7 +118,7 @@ void OptimiserSuite::run( // Some steps depend on properties ensured by FunctionHoister, BlockFlattener, FunctionGrouper and // ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely. - suite.runSequence("hfgo", ast); + suite.runSequence("hgfo", ast); NameSimplifier::run(suite.m_context, ast); // Now the user-supplied part diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index dae4d4c6ff..cb60f9da89 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,12 @@ using namespace std; using namespace solidity; using namespace solidity::yul; +void UnusedPruner::run(OptimiserStepContext& _context, Block& _ast) +{ + UnusedPruner::runUntilStabilisedOnFullAST(_context.dialect, _ast, _context.reservedIdentifiers); + FunctionGrouper::run(_context, _ast); +} + UnusedPruner::UnusedPruner( Dialect const& _dialect, Block& _ast, diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index af77d911af..e4587d5d72 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -50,9 +50,7 @@ class UnusedPruner: public ASTModifier { public: static constexpr char const* name{"UnusedPruner"}; - static void run(OptimiserStepContext& _context, Block& _ast) { - UnusedPruner::runUntilStabilisedOnFullAST(_context.dialect, _ast, _context.reservedIdentifiers); - } + static void run(OptimiserStepContext& _context, Block& _ast); using ASTModifier::operator(); From f2d9a806e0a2a2fb8560cc24d391013dcdf32553 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 9 Nov 2021 13:25:13 +0100 Subject: [PATCH 0002/1704] Document change to BlockFlattener. --- docs/internals/optimizer.rst | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index 28c342902d..d75eca4198 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -972,15 +972,19 @@ BlockFlattener ^^^^^^^^^^^^^^ This stage eliminates nested blocks by inserting the statement in the -inner block at the appropriate place in the outer block: +inner block at the appropriate place in the outer block. It depends on the +FunctionGrouper and does not flatten the outermost block to keep the form +produced by the FunctionGrouper. .. code-block:: yul { - let x := 2 { - let y := 3 - mstore(x, y) + let x := 2 + { + let y := 3 + mstore(x, y) + } } } @@ -989,9 +993,11 @@ is transformed to .. code-block:: yul { - let x := 2 - let y := 3 - mstore(x, y) + { + let x := 2 + let y := 3 + mstore(x, y) + } } As long as the code is disambiguated, this does not cause a problem because From 10618188dd4af178486402ca240881d633b3dbd8 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 9 Nov 2021 13:25:25 +0100 Subject: [PATCH 0003/1704] Update tests. --- .../blockFlattener/basic.yul | 28 +++++++----- .../blockFlattener/for_stmt.yul | 12 +++-- .../blockFlattener/if_stmt.yul | 24 +++++----- .../blockFlattener/many_nested_blocks.yul | 38 +++++++++------- .../blockFlattener/switch_stmt.yul | 24 +++++----- .../called_from_non_function.yul | 6 ++- .../nested_different_names.yul | 2 +- .../nested_same_name.yul | 2 +- .../circularReferencesPruner/trivial.yul | 2 +- .../expressionJoiner/if_condition.yul | 6 ++- .../expressionJoiner/muli_wrong_order3.yul | 8 ++-- .../expressionJoiner/multi.yul | 4 +- .../expressionJoiner/multi_reference.yul | 6 ++- .../expressionJoiner/multi_wrong_order.yul | 6 ++- .../expressionJoiner/multi_wrong_order2.yul | 6 ++- .../no_replacement_across_blocks.yul | 6 ++- .../no_replacement_in_loop_condition1.yul | 6 ++- .../no_replacement_in_loop_condition2.yul | 8 ++-- .../expressionJoiner/only_assignment.yul | 1 + .../expressionJoiner/reassignment.yul | 8 ++-- .../expressionJoiner/simple.yul | 4 +- .../expressionJoiner/single_wrong_order.yul | 6 ++- .../expressionJoiner/smoke.yul | 2 +- .../expressionJoiner/switch_expression.yul | 10 +++-- .../expressionJoiner/triple.yul | 4 +- .../assigned_vars_multi.yul | 6 ++- .../byte_after_shr_non_mul_of_8.yul | 2 +- .../combine_shift_and_and.yul | 8 ++-- .../combine_shift_and_and_2.yul | 44 ++++++++++--------- .../combine_shift_and_and_3.yul | 28 ++++++------ .../constant_propagation.yul | 2 +- .../expressionSimplifier/constants.yul | 2 +- .../expressionSimplifier/create2_and_mask.yul | 12 ++--- .../expressionSimplifier/create_and_mask.yul | 14 +++--- .../exp_simplifications.yul | 18 ++++---- .../expressionSimplifier/idempotency.yul | 10 +++-- .../identity_rules_complex.yul | 2 +- .../identity_rules_negative.yul | 6 ++- .../identity_rules_simple.yul | 2 +- .../including_function_calls.yul | 2 +- .../expressionSimplifier/inside_for.yul | 8 ++-- .../expressionSimplifier/invariant.yul | 2 +- .../expressionSimplifier/iszero_sub_to_eq.yul | 8 ++-- .../large_byte_access.yul | 22 +++++----- .../expressionSimplifier/mod_and_1.yul | 6 ++- .../expressionSimplifier/mod_and_2.yul | 6 ++- ...lied_function_call_different_arguments.yul | 8 ++-- ..._applied_function_call_different_names.yul | 2 +- ...ied_function_call_equality_not_movable.yul | 2 +- ...d_removes_non_constant_and_not_movable.yul | 12 ++--- .../pop_byte_shr_call.yul | 8 ++-- .../pop_byte_shr_func.yul | 6 ++- .../pop_byte_shr_func_trivial.yul | 2 +- .../expressionSimplifier/reassign.yul | 10 +++-- .../remove_redundant_shift_masking.yul | 18 ++++---- .../replace_too_large_shift.yul | 18 ++++---- .../expressionSimplifier/return_vars_zero.yul | 2 +- .../expressionSimplifier/reversed.yul | 6 ++- .../selfbalance_not_supported.yul | 4 +- .../selfbalance_split.yul | 6 ++- .../selfbalance_supported.yul | 2 +- .../side_effects_in_for_condition.yul | 6 ++- .../expressionSimplifier/smoke.yul | 2 +- .../unassigend_vars_multi.yul | 6 ++- .../expressionSimplifier/unassigned_vars.yul | 2 +- .../no_inline_into_big_function.yul | 1 + .../fullSimplify/constant_propagation.yul | 6 ++- .../fullSimplify/constants.yul | 2 +- .../fullSimplify/identity_rules_complex.yul | 2 +- .../fullSimplify/identity_rules_negative.yul | 6 ++- .../fullSimplify/identity_rules_simple.yul | 2 +- .../fullSimplify/including_function_calls.yul | 2 +- .../fullSimplify/inside_for.yul | 8 ++-- .../fullSimplify/invariant.yul | 10 +++-- .../fullSimplify/mod_and_1.yul | 6 ++- .../fullSimplify/mod_and_2.yul | 6 ++- ...lied_function_call_different_arguments.yul | 8 ++-- ..._applied_function_call_different_names.yul | 2 +- ...ied_function_call_equality_not_movable.yul | 2 +- ...d_removes_non_constant_and_not_movable.yul | 8 ++-- .../fullSimplify/operations.yul | 38 ++++++++-------- .../fullSimplify/reversed.yul | 6 ++- .../fullSimplify/signextend.yul | 6 ++- .../yulOptimizerTests/fullSimplify/smoke.yul | 2 +- .../loadResolver/double_mload.yul | 6 ++- .../double_mload_with_other_reassignment.yul | 10 +++-- .../double_mload_with_reassignment.yul | 10 +++-- .../yulOptimizerTests/loadResolver/keccak.yul | 10 +++-- .../loadResolver/keccak_crash.yul | 10 +++-- .../loadResolver/keccak_fail1.yul | 12 ++--- .../loadResolver/keccak_fail2.yul | 10 +++-- .../loadResolver/keccak_short.yul | 20 +++++---- .../loadResolver/keccak_string_literal.yul | 16 ++++--- .../loadResolver/keccak_symbolic_memory.yul | 10 +++-- .../loadResolver/keccak_with_msize.yul | 12 ++--- .../yulOptimizerTests/loadResolver/loop.yul | 16 ++++--- ...y_with_different_kinds_of_invalidation.yul | 30 +++++++------ .../loadResolver/memory_with_msize.yul | 12 ++--- .../loadResolver/merge_known_write.yul | 18 ++++---- .../merge_known_write_with_distance.yul | 14 +++--- .../merge_mload_with_known_distance.yul | 12 ++--- .../loadResolver/merge_mload_with_rewrite.yul | 14 +++--- .../merge_mload_without_rewrite.yul | 14 +++--- .../loadResolver/merge_unknown_write.yul | 18 ++++---- .../loadResolver/merge_with_rewrite.yul | 14 +++--- .../loadResolver/mload_in_function.yul | 12 ++--- .../loadResolver/mload_self.yul | 10 +++-- .../mstore_in_function_loop_body.yul | 12 ++--- .../mstore_in_function_loop_init.yul | 12 ++--- .../loadResolver/multi_sload_loop.yul | 24 +++++----- .../loadResolver/re_store_memory.yul | 16 ++++--- .../loadResolver/re_store_storage.yul | 16 ++++--- .../loadResolver/reassign.yul | 12 ++--- .../reassign_value_expression.yul | 24 +++++----- .../loadResolver/second_mstore_with_delta.yul | 18 ++++---- .../loadResolver/second_store.yul | 14 +++--- .../loadResolver/second_store_same_value.yul | 14 +++--- .../loadResolver/second_store_with_delta.yul | 18 ++++---- .../side_effects_of_user_functions.yul | 20 +++++---- .../yulOptimizerTests/loadResolver/simple.yul | 8 ++-- .../loadResolver/simple_memory.yul | 8 ++-- .../loadResolver/staticcall.yul | 22 +++++----- .../loadResolver/verbatim_mload.yul | 12 ++--- .../loadResolver/verbatim_sload.yul | 18 ++++---- .../splitJoin/control_flow.yul | 10 +++-- .../yulOptimizerTests/splitJoin/functions.yul | 14 +++--- .../yulOptimizerTests/splitJoin/smoke.yul | 2 +- .../yulOptimizerTests/ssaAndBack/for_loop.yul | 14 +++--- .../ssaAndBack/multi_assign.yul | 6 ++- .../ssaAndBack/multi_assign_if.yul | 8 ++-- .../ssaAndBack/multi_assign_multi_var_if.yul | 18 ++++---- .../multi_assign_multi_var_switch.yul | 32 +++++++------- .../ssaAndBack/multi_assign_switch.yul | 12 ++--- .../yulOptimizerTests/ssaAndBack/simple.yul | 6 ++- .../ssaAndBack/single_assign_if.yul | 8 ++-- .../ssaAndBack/single_assign_switch.yul | 12 ++--- .../ssaAndBack/ssaReverse.yul | 6 ++- .../yulOptimizerTests/ssaAndBack/two_vars.yul | 16 ++++--- .../stackCompressor/inlineInBlock.yul | 4 +- .../stackCompressor/inlineInFunction.yul | 2 +- .../stackCompressor/noInline.yul | 2 +- .../stackCompressor/unusedPrunerWithMSize.yul | 20 +++++---- .../unusedPruner/functions.yul | 2 +- .../unusedPruner/intermediate_assignment.yul | 6 ++- .../intermediate_multi_assignment.yul | 8 ++-- .../yulOptimizerTests/unusedPruner/keccak.yul | 6 ++- .../movable_user_defined_function.yul | 2 +- .../yulOptimizerTests/unusedPruner/msize.yul | 6 ++- .../unusedPruner/multi_assign.yul | 8 ++-- .../unusedPruner/multi_assignments.yul | 8 ++-- .../unusedPruner/multi_declarations.yul | 2 +- .../unusedPruner/multi_declare.yul | 2 +- .../multi_partial_assignments.yul | 6 ++- .../unusedPruner/no_msize.yul | 2 +- .../yulOptimizerTests/unusedPruner/pop.yul | 2 +- .../yulOptimizerTests/unusedPruner/smoke.yul | 2 +- .../unusedPruner/trivial.yul | 2 +- .../unusedPruner/verbatim.yul | 8 ++-- test/yulPhaser/Program.cpp | 5 ++- 159 files changed, 893 insertions(+), 638 deletions(-) diff --git a/test/libyul/yulOptimizerTests/blockFlattener/basic.yul b/test/libyul/yulOptimizerTests/blockFlattener/basic.yul index e576174367..5b49552fb9 100644 --- a/test/libyul/yulOptimizerTests/blockFlattener/basic.yul +++ b/test/libyul/yulOptimizerTests/blockFlattener/basic.yul @@ -1,21 +1,25 @@ { - let _1 := mload(0) - let f_a := mload(1) - let f_r { - f_a := mload(f_a) - f_r := add(f_a, calldatasize()) + let _1 := mload(0) + let f_a := mload(1) + let f_r + { + f_a := mload(f_a) + f_r := add(f_a, calldatasize()) + } + let z := mload(2) } - let z := mload(2) } // ---- // step: blockFlattener // // { -// let _1 := mload(0) -// let f_a := mload(1) -// let f_r -// f_a := mload(f_a) -// f_r := add(f_a, calldatasize()) -// let z := mload(2) +// { +// let _1 := mload(0) +// let f_a := mload(1) +// let f_r +// f_a := mload(f_a) +// f_r := add(f_a, calldatasize()) +// let z := mload(2) +// } // } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul index a5be68a7ce..c587c47a3a 100644 --- a/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul +++ b/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul @@ -1,12 +1,16 @@ { - for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - a := add(a, 1) + { + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + a := add(a, 1) + } } } // ---- // step: blockFlattener // // { -// for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } -// { a := add(a, 1) } +// { +// for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } +// { a := add(a, 1) } +// } // } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul index f31c5f979c..00740fb133 100644 --- a/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul +++ b/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul @@ -1,21 +1,25 @@ { - if add(mload(7), sload(mload(3))) { - let y := add(mload(3), 3) - { - y := add(y, 7) - } + if add(mload(7), sload(mload(3))) + { + let y := add(mload(3), 3) + { + y := add(y, 7) + } + } + let t := add(3, 9) } - let t := add(3, 9) } // ---- // step: blockFlattener // // { -// if add(mload(7), sload(mload(3))) // { -// let y := add(mload(3), 3) -// y := add(y, 7) +// if add(mload(7), sload(mload(3))) +// { +// let y := add(mload(3), 3) +// y := add(y, 7) +// } +// let t := add(3, 9) // } -// let t := add(3, 9) // } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul b/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul index d7fd4b45a4..d1051a115b 100644 --- a/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul +++ b/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul @@ -1,29 +1,33 @@ { - let a := 3 - let b := 4 { - a := add(b, 3) - let c := 5 + let a := 3 + let b := 4 { - b := add(b, 4) + a := add(b, 3) + let c := 5 { - c := add(a, 5) - } - b := add(a, b) + b := add(b, 4) + { + c := add(a, 5) + } + b := add(a, b) + } + a := add(a, c) } - a := add(a, c) } } // ---- // step: blockFlattener // // { -// let a := 3 -// let b := 4 -// a := add(b, 3) -// let c := 5 -// b := add(b, 4) -// c := add(a, 5) -// b := add(a, b) -// a := add(a, c) +// { +// let a := 3 +// let b := 4 +// a := add(b, 3) +// let c := 5 +// b := add(b, 4) +// c := add(a, 5) +// b := add(a, b) +// a := add(a, c) +// } // } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul index 0b2a8245de..27b9d96dfd 100644 --- a/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul +++ b/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul @@ -1,23 +1,27 @@ { + { let a := 1 switch calldataload(0) case 0 { { { mstore(0, 1) } } a := 8 } default { a := 3 { a := 4 } } a := 5 + } } // ---- // step: blockFlattener // // { -// let a := 1 -// switch calldataload(0) -// case 0 { -// mstore(0, 1) -// a := 8 +// { +// let a := 1 +// switch calldataload(0) +// case 0 { +// mstore(0, 1) +// a := 8 +// } +// default { +// a := 3 +// a := 4 +// } +// a := 5 // } -// default { -// a := 3 -// a := 4 -// } -// a := 5 // } diff --git a/test/libyul/yulOptimizerTests/circularReferencesPruner/called_from_non_function.yul b/test/libyul/yulOptimizerTests/circularReferencesPruner/called_from_non_function.yul index 739ba78bff..909d12533c 100644 --- a/test/libyul/yulOptimizerTests/circularReferencesPruner/called_from_non_function.yul +++ b/test/libyul/yulOptimizerTests/circularReferencesPruner/called_from_non_function.yul @@ -9,8 +9,10 @@ // step: circularReferencesPruner // // { -// let a -// a := h() +// { +// let a +// a := h() +// } // function f() -> x // { x := g() } // function g() -> y diff --git a/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_different_names.yul b/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_different_names.yul index ac04f96a81..f78b9fb992 100644 --- a/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_different_names.yul +++ b/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_different_names.yul @@ -11,4 +11,4 @@ // ---- // step: circularReferencesPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_same_name.yul b/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_same_name.yul index 02ac2317de..858a48d85b 100644 --- a/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_same_name.yul +++ b/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_same_name.yul @@ -11,4 +11,4 @@ // ---- // step: circularReferencesPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/circularReferencesPruner/trivial.yul b/test/libyul/yulOptimizerTests/circularReferencesPruner/trivial.yul index 4398bc29f4..ebb8a329c8 100644 --- a/test/libyul/yulOptimizerTests/circularReferencesPruner/trivial.yul +++ b/test/libyul/yulOptimizerTests/circularReferencesPruner/trivial.yul @@ -5,4 +5,4 @@ // ---- // step: circularReferencesPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul b/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul index 045168cf13..f7e0e2ea16 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul @@ -14,6 +14,8 @@ // step: expressionJoiner // // { -// if add(mload(7), sload(mload(3))) { let y := add(mload(3), 3) } -// let t := add(3, 9) +// { +// if add(mload(7), sload(mload(3))) { let y := add(mload(3), 3) } +// let t := add(3, 9) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul b/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul index 461285ae24..b2f75828e8 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul @@ -8,7 +8,9 @@ // step: expressionJoiner // // { -// let a := mload(3) -// let b := mload(6) -// sstore(mul(add(b, a), mload(2)), 3) +// { +// let a := mload(3) +// let b := mload(6) +// sstore(mul(add(b, a), mload(2)), 3) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul index 5fcd2c5bf2..6a9e1a336e 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul @@ -8,5 +8,7 @@ // step: expressionJoiner // // { -// sstore(mul(add(mload(6), mload(2)), 2), 3) +// { +// sstore(mul(add(mload(6), mload(2)), 2), 3) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul index ed209e597d..cf90aa836f 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul @@ -7,6 +7,8 @@ // step: expressionJoiner // // { -// let a := mload(2) -// let b := add(a, a) +// { +// let a := mload(2) +// let b := add(a, a) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul index 2837f70330..16bd1adedd 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul @@ -11,6 +11,8 @@ // step: expressionJoiner // // { -// let a := mload(2) -// sstore(mul(a, add(2, mload(6))), 3) +// { +// let a := mload(2) +// sstore(mul(a, add(2, mload(6))), 3) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul index d69f9d8a5d..25cf9676cb 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul @@ -8,6 +8,8 @@ // step: expressionJoiner // // { -// let a := mload(2) -// sstore(mul(add(a, mload(6)), 2), 3) +// { +// let a := mload(2) +// sstore(mul(add(a, mload(6)), 2), 3) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul index 0e4f1916a2..f31be09c96 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul @@ -15,6 +15,8 @@ // step: expressionJoiner // // { -// let x := calldataload(mload(2)) -// sstore(x, 3) +// { +// let x := calldataload(mload(2)) +// sstore(x, 3) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul index b453446ad2..7e81adc7de 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul @@ -5,6 +5,8 @@ // step: expressionJoiner // // { -// for { let b := mload(1) } b { } -// { } +// { +// for { let b := mload(1) } b { } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul index ab41999d50..bc5c5106df 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul @@ -6,7 +6,9 @@ // step: expressionJoiner // // { -// let a := mload(0) -// for { } a { } -// { } +// { +// let a := mload(0) +// for { } a { } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul b/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul index 30bf466348..ac3d8e6221 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul @@ -9,6 +9,7 @@ // step: expressionJoiner // // { +// { } // function f(a) -> x // { // a := mload(2) diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul b/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul index e327d0b33f..2b5cce251f 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul @@ -8,7 +8,9 @@ // step: expressionJoiner // // { -// let a := mload(2) -// let b := mload(a) -// a := 4 +// { +// let a := mload(2) +// let b := mload(a) +// a := 4 +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul b/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul index 5ec8a900ad..ed8a282622 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul @@ -7,5 +7,7 @@ // step: expressionJoiner // // { -// sstore(calldataload(mload(2)), 3) +// { +// sstore(calldataload(mload(2)), 3) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul b/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul index 812cb7e7c6..beb3b8ab59 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul @@ -9,6 +9,8 @@ // step: expressionJoiner // // { -// let b := sload(mload(3)) -// sstore(add(b, mload(7)), 0) +// { +// let b := sload(mload(3)) +// sstore(add(b, mload(7)), 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul b/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul index 77f73f1126..69c4afdda6 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul @@ -2,4 +2,4 @@ // ---- // step: expressionJoiner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul b/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul index 08f7bb9fb0..c17e8d3dc1 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul @@ -18,8 +18,10 @@ // step: expressionJoiner // // { -// switch add(mload(7), sload(mload(3))) -// case 3 { let y := add(mload(3), 3) } -// default { sstore(1, 0) } -// let t := add(3, 9) +// { +// switch add(mload(7), sload(mload(3))) +// case 3 { let y := add(mload(3), 3) } +// default { sstore(1, 0) } +// let t := add(3, 9) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul b/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul index d6c652e2c0..e0a5dca4d2 100644 --- a/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul +++ b/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul @@ -9,5 +9,7 @@ // step: expressionJoiner // // { -// sstore(mul(add(mload(7), mload(6)), mload(2)), 3) +// { +// sstore(mul(add(mload(7), mload(6)), mload(2)), 3) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul index b73742ced1..1fce6767ed 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul @@ -8,8 +8,10 @@ // step: expressionSimplifier // // { -// let c, d := f() -// sstore(add(add(d, c), 7), 20) +// { +// let c, d := f() +// sstore(add(add(d, c), 7), 20) +// } // function f() -> x, z // { } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/byte_after_shr_non_mul_of_8.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/byte_after_shr_non_mul_of_8.yul index e7c7bbf881..f9405e1013 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/byte_after_shr_non_mul_of_8.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/byte_after_shr_non_mul_of_8.yul @@ -6,4 +6,4 @@ // ---- // step: expressionSimplifier // -// { sstore(0, 0) } +// { { sstore(0, 0) } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and.yul index 7288ef56f9..9bb106c89e 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and.yul @@ -13,7 +13,9 @@ // step: expressionSimplifier // // { -// let x := calldataload(0) -// let a := and(0xff, and(shr(248, x), 255)) -// sstore(a, shr(12, and(shl(8, x), 15790080))) +// { +// let x := calldataload(0) +// let a := and(0xff, and(shr(248, x), 255)) +// sstore(a, shr(12, and(shl(8, x), 15790080))) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_2.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_2.yul index f57a5108b8..6e39f2a1dc 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_2.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_2.yul @@ -24,25 +24,27 @@ // step: expressionSimplifier // // { -// let x := calldataload(0) -// let _2 := 0xf -// let _5 := and(shr(248, x), 0) -// let _10 := 0xff -// let a := and(_5, 255) -// let _14 := and(shr(4, x), 3855) -// let _15 := 12 -// let b := shl(_15, _14) -// let _19 := and(shr(4, x), 3855) -// let c := shl(_15, _19) -// let d := shl(_15, and(shr(255, x), 0)) -// let e := shl(_10, _19) -// let f := 0 -// let g := 0 -// sstore(10, a) -// sstore(11, b) -// sstore(_15, c) -// sstore(13, d) -// sstore(14, e) -// sstore(_2, f) -// sstore(16, g) +// { +// let x := calldataload(0) +// let _2 := 0xf +// let _5 := and(shr(248, x), 0) +// let _10 := 0xff +// let a := and(_5, 255) +// let _14 := and(shr(4, x), 3855) +// let _15 := 12 +// let b := shl(_15, _14) +// let _19 := and(shr(4, x), 3855) +// let c := shl(_15, _19) +// let d := shl(_15, and(shr(255, x), 0)) +// let e := shl(_10, _19) +// let f := 0 +// let g := 0 +// sstore(10, a) +// sstore(11, b) +// sstore(_15, c) +// sstore(13, d) +// sstore(14, e) +// sstore(_2, f) +// sstore(16, g) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_3.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_3.yul index 14ff1b375d..9df15b4e9c 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_3.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_3.yul @@ -21,17 +21,19 @@ // step: expressionSimplifier // // { -// let x := calldataload(0) -// let a := and(shl(8, x), 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000) -// let b := and(shr(8, x), 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0) -// let c := and(shr(8, x), 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) -// let d := and(shl(8, x), 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) -// let _14 := 150 -// let e := shl(_14, and(shl(148, x), 0x3ffffffffffffffffffffffffff0000000000000000000000000000000000000)) -// sstore(15, x) -// sstore(16, a) -// sstore(17, b) -// sstore(18, c) -// sstore(19, d) -// sstore(20, e) +// { +// let x := calldataload(0) +// let a := and(shl(8, x), 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000) +// let b := and(shr(8, x), 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0) +// let c := and(shr(8, x), 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// let d := and(shl(8, x), 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) +// let _14 := 150 +// let e := shl(_14, and(shl(148, x), 0x3ffffffffffffffffffffffffff0000000000000000000000000000000000000)) +// sstore(15, x) +// sstore(16, a) +// sstore(17, b) +// sstore(18, c) +// sstore(19, d) +// sstore(20, e) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul index 56d18fb7b3..557142fa54 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul @@ -5,4 +5,4 @@ // ---- // step: expressionSimplifier // -// { mstore(20, mload(0)) } +// { { mstore(20, mload(0)) } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul index ce29499931..bbd8f2d122 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul @@ -5,4 +5,4 @@ // ---- // step: expressionSimplifier // -// { sstore(7, 13) } +// { { sstore(7, 13) } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul index 8a52659922..a431c57a6c 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul @@ -12,9 +12,11 @@ // step: expressionSimplifier // // { -// let _1 := 0xffffffffffffffffffffffffffffffffffffffff -// let _2 := 0 -// let _3 := 0x20 -// let a := and(create2(_2, _2, _3, _2), _1) -// sstore(a, and(_1, create2(_2, _2, _3, _2))) +// { +// let _1 := 0xffffffffffffffffffffffffffffffffffffffff +// let _2 := 0 +// let _3 := 0x20 +// let a := and(create2(_2, _2, _3, _2), _1) +// sstore(a, and(_1, create2(_2, _2, _3, _2))) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul index 8e77b8726b..3710cbebdf 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul @@ -11,10 +11,12 @@ // step: expressionSimplifier // // { -// let _1 := 0x20 -// let _2 := 0 -// let c := create(_2, _2, _1) -// let _4 := 0xffffffffffffffffffffffffffffffffffffffff -// let a := and(c, _4) -// sstore(a, and(_4, create(_2, _2, _1))) +// { +// let _1 := 0x20 +// let _2 := 0 +// let c := create(_2, _2, _1) +// let _4 := 0xffffffffffffffffffffffffffffffffffffffff +// let a := and(c, _4) +// sstore(a, and(_4, create(_2, _2, _1))) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/exp_simplifications.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/exp_simplifications.yul index bfc1cbb2b0..4a5d218053 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/exp_simplifications.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/exp_simplifications.yul @@ -13,12 +13,14 @@ // step: expressionSimplifier // // { -// let _1 := 0 -// let t := calldataload(_1) -// sstore(_1, iszero(t)) -// sstore(1, 1) -// let _8 := 2 -// sstore(_8, shl(t, 1)) -// sstore(3, exp(8, t)) -// sstore(4, sub(iszero(and(t, 1)), and(t, 1))) +// { +// let _1 := 0 +// let t := calldataload(_1) +// sstore(_1, iszero(t)) +// sstore(1, 1) +// let _8 := 2 +// sstore(_8, shl(t, 1)) +// sstore(3, exp(8, t)) +// sstore(4, sub(iszero(and(t, 1)), and(t, 1))) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/idempotency.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/idempotency.yul index 9698dfdff4..5b11fa7c8e 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/idempotency.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/idempotency.yul @@ -9,8 +9,10 @@ // step: expressionSimplifier // // { -// let x := calldataload(0) -// let z := calldataload(1) -// let t := and(x, z) -// sstore(t, or(x, z)) +// { +// let x := calldataload(0) +// let z := calldataload(1) +// let t := and(x, z) +// sstore(t, or(x, z)) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul index 6bb6a751b8..af88cbac6d 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul @@ -5,4 +5,4 @@ // ---- // step: expressionSimplifier // -// { sstore(0, 0) } +// { { sstore(0, 0) } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul index 686ae2b635..80f19a1b53 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul @@ -6,6 +6,8 @@ // step: expressionSimplifier // // { -// let _1 := 0 -// sstore(_1, sub(calldataload(1), calldataload(_1))) +// { +// let _1 := 0 +// sstore(_1, sub(calldataload(1), calldataload(_1))) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul index 57d84ae153..87677dfea2 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul @@ -6,4 +6,4 @@ // ---- // step: expressionSimplifier // -// { sstore(0, 0) } +// { { sstore(0, 0) } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul index 8ebb9e51dd..42cd772e9f 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul @@ -7,7 +7,7 @@ // step: expressionSimplifier // // { -// sstore(0, f()) +// { sstore(0, f()) } // function f() -> a // { } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul index b8b3ee35d8..5a7c8939a6 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul @@ -6,7 +6,9 @@ // step: expressionSimplifier // // { -// let a := 10 -// for { } iszero(iszero(a)) { a := add(a, 1) } -// { } +// { +// let a := 10 +// for { } iszero(iszero(a)) { a := add(a, 1) } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul index d7da5e41fe..78565bbe5b 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul @@ -6,4 +6,4 @@ // ---- // step: expressionSimplifier // -// { sstore(0, mload(0)) } +// { { sstore(0, mload(0)) } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/iszero_sub_to_eq.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/iszero_sub_to_eq.yul index 7efa54b021..3e0f785e95 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/iszero_sub_to_eq.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/iszero_sub_to_eq.yul @@ -10,7 +10,9 @@ // step: expressionSimplifier // // { -// let _1 := 0 -// let a := calldataload(_1) -// if eq(a, calldataload(0x20)) { sstore(_1, 1) } +// { +// let _1 := 0 +// let a := calldataload(_1) +// if eq(a, calldataload(0x20)) { sstore(_1, 1) } +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul index 22bfaf91fd..19d65dca41 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul @@ -13,14 +13,16 @@ // step: expressionSimplifier // // { -// let _1 := 0 -// let a := calldataload(_1) -// let b := 0 -// let c := byte(20, a) -// pop(create(_1, _1, 0x20)) -// let d := 0 -// sstore(7, a) -// sstore(8, b) -// sstore(9, c) -// sstore(10, d) +// { +// let _1 := 0 +// let a := calldataload(_1) +// let b := 0 +// let c := byte(20, a) +// pop(create(_1, _1, 0x20)) +// let d := 0 +// sstore(7, a) +// sstore(8, b) +// sstore(9, c) +// sstore(10, d) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul index 696d0b1117..88ed926b18 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul @@ -5,6 +5,8 @@ // step: expressionSimplifier // // { -// let _4 := 0 -// mstore(_4, and(calldataload(_4), 255)) +// { +// let _4 := 0 +// mstore(_4, and(calldataload(_4), 255)) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul index 81fe7e117e..a62c5904cf 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul @@ -5,6 +5,8 @@ // step: expressionSimplifier // // { -// let _4 := 0 -// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// { +// let _4 := 0 +// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul index eca9021ea6..c426935219 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul @@ -7,9 +7,11 @@ // step: expressionSimplifier // // { -// let _2 := f(1) -// let _3 := 0 -// sstore(_3, sub(f(_3), _2)) +// { +// let _2 := f(1) +// let _3 := 0 +// sstore(_3, sub(f(_3), _2)) +// } // function f(a) -> b // { } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul index ed439b62fd..5245677053 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul @@ -8,7 +8,7 @@ // step: expressionSimplifier // // { -// sstore(0, sub(f1(), f2())) +// { sstore(0, sub(f1(), f2())) } // function f1() -> a // { } // function f2() -> b diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul index bba7cf26e5..b0215685de 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul @@ -8,7 +8,7 @@ // step: expressionSimplifier // // { -// sstore(sub(f(), f()), 8) +// { sstore(sub(f(), f()), 8) } // function f() -> a // { mstore(0, 1) } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul index 37065cd4dc..a7be174e35 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul @@ -9,9 +9,11 @@ // step: expressionSimplifier // // { -// let _1 := msize() -// let _2 := 0 -// sstore(_2, _1) -// pop(keccak256(_2, _2)) -// sstore(20, 0) +// { +// let _1 := msize() +// let _2 := 0 +// sstore(_2, _1) +// pop(keccak256(_2, _2)) +// sstore(20, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul index af34e76bde..abd1b1743d 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul @@ -7,7 +7,9 @@ // step: expressionSimplifier // // { -// let _1 := 0 -// pop(call(_1, _1, _1, _1, _1, _1, _1)) -// sstore(_1, 0) +// { +// let _1 := 0 +// pop(call(_1, _1, _1, _1, _1, _1, _1)) +// sstore(_1, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func.yul index e1ec04ad1e..6465aa7974 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func.yul @@ -8,8 +8,10 @@ // step: expressionSimplifier // // { -// pop(f()) -// mstore(0, 0) +// { +// pop(f()) +// mstore(0, 0) +// } // function f() -> x // { mstore(0, 1337) } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func_trivial.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func_trivial.yul index 448e071d8f..b822b402b3 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func_trivial.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func_trivial.yul @@ -7,4 +7,4 @@ // ---- // step: expressionSimplifier // -// { sstore(0, 0) } +// { { sstore(0, 0) } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/reassign.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/reassign.yul index d87b84f595..d0cf0a6eed 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/reassign.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/reassign.yul @@ -7,8 +7,10 @@ // step: expressionSimplifier // // { -// let _1 := 0 -// let x := mload(_1) -// x := _1 -// mstore(_1, 7) +// { +// let _1 := 0 +// let x := mload(_1) +// x := _1 +// mstore(_1, 7) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/remove_redundant_shift_masking.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/remove_redundant_shift_masking.yul index 060a4e13ff..a4d3012c33 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/remove_redundant_shift_masking.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/remove_redundant_shift_masking.yul @@ -12,12 +12,14 @@ // step: expressionSimplifier // // { -// let _2 := calldataload(0) -// let _5 := 0xff -// let a := shr(248, _2) -// let b := shr(248, _2) -// let c := and(shr(249, _2), 0xfa) -// let d := and(shr(247, _2), _5) -// sstore(a, b) -// sstore(c, d) +// { +// let _2 := calldataload(0) +// let _5 := 0xff +// let a := shr(248, _2) +// let b := shr(248, _2) +// let c := and(shr(249, _2), 0xfa) +// let d := and(shr(247, _2), _5) +// sstore(a, b) +// sstore(c, d) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/replace_too_large_shift.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/replace_too_large_shift.yul index 88263e98e7..85c86f0e4b 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/replace_too_large_shift.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/replace_too_large_shift.yul @@ -12,12 +12,14 @@ // step: expressionSimplifier // // { -// let a := 0 -// let b := 0 -// let _8 := calldataload(2) -// let _9 := 255 -// let c := shl(_9, _8) -// let d := shr(_9, calldataload(3)) -// sstore(a, b) -// sstore(c, d) +// { +// let a := 0 +// let b := 0 +// let _8 := calldataload(2) +// let _9 := 255 +// let c := shl(_9, _8) +// let d := shr(_9, calldataload(3)) +// sstore(a, b) +// sstore(c, d) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul index ca31e7613b..73a79410df 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul @@ -10,7 +10,7 @@ // step: expressionSimplifier // // { -// let t, v := f() +// { let t, v := f() } // function f() -> c, d // { sstore(0, 7) } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul index 32c8775721..b83b77c216 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul @@ -6,6 +6,8 @@ // step: expressionSimplifier // // { -// let _1 := 0 -// sstore(_1, mload(_1)) +// { +// let _1 := 0 +// sstore(_1, mload(_1)) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_not_supported.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_not_supported.yul index 8a9bb7c199..3f30eefd65 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_not_supported.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_not_supported.yul @@ -6,4 +6,6 @@ // ---- // step: expressionSimplifier // -// { sstore(0, balance(address())) } +// { +// { sstore(0, balance(address())) } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_split.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_split.yul index b14098ffef..72562a2fde 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_split.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_split.yul @@ -9,6 +9,8 @@ // step: expressionSimplifier // // { -// let a := address() -// sstore(a, selfbalance()) +// { +// let a := address() +// sstore(a, selfbalance()) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_supported.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_supported.yul index bc3c6c4d70..7ed42b360e 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_supported.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/selfbalance_supported.yul @@ -6,4 +6,4 @@ // ---- // step: expressionSimplifier // -// { sstore(0, selfbalance()) } +// { { sstore(0, selfbalance()) } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul index 14d65c4e92..bd567a69a6 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul @@ -9,6 +9,8 @@ // step: expressionSimplifier // // { -// for { } div(create(0, 1, 0), shl(msize(), 1)) { } -// { } +// { +// for { } div(create(0, 1, 0), shl(msize(), 1)) { } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul index 30a2f5e901..0fae4792fd 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul @@ -2,4 +2,4 @@ // ---- // step: expressionSimplifier // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul index b052fe4033..a15cca231d 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul @@ -8,6 +8,8 @@ // step: expressionSimplifier // // { -// let c, d -// sstore(d, 7) +// { +// let c, d +// sstore(d, 7) +// } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul index 9dd4e3365d..b6828cf8c4 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul @@ -8,4 +8,4 @@ // ---- // step: expressionSimplifier // -// { sstore(8, 7) } +// { { sstore(8, 7) } } diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul index c1ce89bcfe..fbc0ca8561 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul @@ -13,6 +13,7 @@ // step: fullInliner // // { +// { } // function f(a) -> b // { b := sload(mload(a)) } // function g() -> x_1 diff --git a/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul b/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul index 968ec47673..a13ad93953 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul @@ -6,6 +6,8 @@ // step: fullSimplify // // { -// let _2 := 0 -// mstore(mload(_2), _2) +// { +// let _2 := 0 +// mstore(mload(_2), _2) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/constants.yul b/test/libyul/yulOptimizerTests/fullSimplify/constants.yul index 0b31d361f9..2d2fb70444 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/constants.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/constants.yul @@ -5,4 +5,4 @@ // ---- // step: fullSimplify // -// { mstore(0, 13) } +// { { mstore(0, 13) } } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul index 452ceaae6f..eb104f6337 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul @@ -5,4 +5,4 @@ // ---- // step: fullSimplify // -// { mstore(0, 0) } +// { { mstore(0, 0) } } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul index 8c5e4e5dfc..daf34eed5e 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul @@ -6,6 +6,8 @@ // step: fullSimplify // // { -// let _1 := 0 -// mstore(_1, sub(calldataload(1), calldataload(_1))) +// { +// let _1 := 0 +// mstore(_1, sub(calldataload(1), calldataload(_1))) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul index e8efb735c0..6f90c583ef 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul @@ -5,4 +5,4 @@ // ---- // step: fullSimplify // -// { mstore(0, 0) } +// { { mstore(0, 0) } } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul b/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul index 090b3cde65..08dd01646d 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul @@ -7,7 +7,7 @@ // step: fullSimplify // // { -// mstore(f(), 0) +// { mstore(f(), 0) } // function f() -> a // { } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul b/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul index 9d4e52dc1b..911c668172 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul @@ -7,7 +7,9 @@ // step: fullSimplify // // { -// let a := 10 -// for { } iszero(iszero(a)) { a := add(a, 1) } -// { } +// { +// let a := 10 +// for { } iszero(iszero(a)) { a := add(a, 1) } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul b/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul index 6874918186..0ab5cc6ed8 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul @@ -11,8 +11,10 @@ // step: fullSimplify // // { -// let a := calldataload(0) -// let _4 := 0 -// let b := a -// mstore(b, eq(calldataload(_4), a)) +// { +// let a := calldataload(0) +// let _4 := 0 +// let b := a +// mstore(b, eq(calldataload(_4), a)) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul index 1e448c9a4f..c10345e4ee 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul @@ -5,6 +5,8 @@ // step: fullSimplify // // { -// let _4 := 0 -// mstore(_4, and(calldataload(_4), 255)) +// { +// let _4 := 0 +// mstore(_4, and(calldataload(_4), 255)) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul index 0756c1841d..fc171337f9 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul @@ -5,6 +5,8 @@ // step: fullSimplify // // { -// let _4 := 0 -// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// { +// let _4 := 0 +// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul index 517bbe442b..e42b6c0986 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul @@ -6,9 +6,11 @@ // step: fullSimplify // // { -// let _2 := f(1) -// let _3 := 0 -// mstore(_3, sub(f(_3), _2)) +// { +// let _2 := f(1) +// let _3 := 0 +// mstore(_3, sub(f(_3), _2)) +// } // function f(a) -> b // { } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul index 7f8fddf2e5..31490cbc06 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul @@ -8,7 +8,7 @@ // step: fullSimplify // // { -// mstore(0, sub(f1(), f2())) +// { mstore(0, sub(f1(), f2())) } // function f1() -> a // { } // function f2() -> b diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul index 52030fe88f..8162119e8f 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul @@ -8,7 +8,7 @@ // step: fullSimplify // // { -// mstore(0, sub(f(), f())) +// { mstore(0, sub(f(), f())) } // function f() -> a // { mstore(1, 2) } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul index 05fc9447d6..0e366e6d40 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul @@ -7,7 +7,9 @@ // step: fullSimplify // // { -// let _1 := 0 -// pop(create(_1, _1, _1)) -// mstore(_1, 0) +// { +// let _1 := 0 +// pop(create(_1, _1, _1)) +// mstore(_1, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/operations.yul b/test/libyul/yulOptimizerTests/fullSimplify/operations.yul index 93b4242330..a0fb676014 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/operations.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/operations.yul @@ -23,22 +23,24 @@ // step: fullSimplify // // { -// mstore(1, 0) -// mstore(2, 0) -// mstore(3, 0) -// mstore(4, 0) -// mstore(5, 0) -// mstore(6, 0) -// mstore(7, 0) -// mstore(8, 0) -// mstore(9, 0) -// mstore(10, 0) -// mstore(11, 0) -// mstore(12, 0) -// mstore(13, 0) -// mstore(14, 0) -// mstore(15, 0) -// mstore(16, 0) -// mstore(17, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) -// mstore(18, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// { +// mstore(1, 0) +// mstore(2, 0) +// mstore(3, 0) +// mstore(4, 0) +// mstore(5, 0) +// mstore(6, 0) +// mstore(7, 0) +// mstore(8, 0) +// mstore(9, 0) +// mstore(10, 0) +// mstore(11, 0) +// mstore(12, 0) +// mstore(13, 0) +// mstore(14, 0) +// mstore(15, 0) +// mstore(16, 0) +// mstore(17, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// mstore(18, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul b/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul index 5fe6324959..b3b98d061a 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul @@ -6,6 +6,8 @@ // step: fullSimplify // // { -// let _1 := 0 -// mstore(_1, mload(_1)) +// { +// let _1 := 0 +// mstore(_1, mload(_1)) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul b/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul index 9ebdf01289..2dd64525f9 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul @@ -8,6 +8,8 @@ // step: fullSimplify // // { -// mstore(0, 7) -// mstore(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// { +// mstore(0, 7) +// mstore(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul b/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul index 15ff14a845..a5b71eea8d 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul @@ -2,4 +2,4 @@ // ---- // step: fullSimplify // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/loadResolver/double_mload.yul b/test/libyul/yulOptimizerTests/loadResolver/double_mload.yul index b75f9c07b9..1448354763 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/double_mload.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/double_mload.yul @@ -8,6 +8,8 @@ // step: loadResolver // // { -// let a := mload(calldataload(0)) -// sstore(a, a) +// { +// let a := mload(calldataload(0)) +// sstore(a, a) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/double_mload_with_other_reassignment.yul b/test/libyul/yulOptimizerTests/loadResolver/double_mload_with_other_reassignment.yul index 19d2174231..7ffac34c0b 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/double_mload_with_other_reassignment.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/double_mload_with_other_reassignment.yul @@ -9,8 +9,10 @@ // step: loadResolver // // { -// let x := calldataload(0) -// let a := mload(x) -// x := 7 -// sstore(a, mload(x)) +// { +// let x := calldataload(0) +// let a := mload(x) +// x := 7 +// sstore(a, mload(x)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/double_mload_with_reassignment.yul b/test/libyul/yulOptimizerTests/loadResolver/double_mload_with_reassignment.yul index b5c2f11265..7f8514875d 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/double_mload_with_reassignment.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/double_mload_with_reassignment.yul @@ -9,8 +9,10 @@ // step: loadResolver // // { -// let x := calldataload(0) -// let a := mload(x) -// a := 7 -// sstore(a, mload(x)) +// { +// let x := calldataload(0) +// let a := mload(x) +// a := 7 +// sstore(a, mload(x)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak.yul index 97b468e5fb..25b36f5fea 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak.yul @@ -9,8 +9,10 @@ // step: loadResolver // // { -// let _1 := 10 -// let _2 := 0 -// mstore(_2, _1) -// sstore(_2, 89717814153306320011181716697424560163256864414616650038987186496166826726056) +// { +// let _1 := 10 +// let _2 := 0 +// mstore(_2, _1) +// sstore(_2, 89717814153306320011181716697424560163256864414616650038987186496166826726056) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul index dd6a164eb4..18c818d15e 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul @@ -6,8 +6,10 @@ // step: loadResolver // // { -// for { } -// addmod(keccak256(0x0, create(0x0, 0x0, 0x0)), 0x0, 0x0) -// { } -// { } +// { +// for { } +// addmod(keccak256(0x0, create(0x0, 0x0, 0x0)), 0x0, 0x0) +// { } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_fail1.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_fail1.yul index e1157f21d4..e4fe6484ff 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_fail1.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_fail1.yul @@ -10,9 +10,11 @@ // step: loadResolver // // { -// let _1 := 30 -// let _2 := 0 -// mstore(_2, _1) -// if calldataload(_2) { mstore(_2, 20) } -// sstore(_2, keccak256(_2, 32)) +// { +// let _1 := 30 +// let _2 := 0 +// mstore(_2, _1) +// if calldataload(_2) { mstore(_2, 20) } +// sstore(_2, keccak256(_2, 32)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_fail2.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_fail2.yul index 61a2eefb25..5a7d571a47 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_fail2.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_fail2.yul @@ -9,8 +9,10 @@ // step: loadResolver // // { -// let _1 := 10 -// mstore(100, _1) -// mstore(132, 5) -// sstore(0, keccak256(_1, 33)) +// { +// let _1 := 10 +// mstore(100, _1) +// mstore(132, 5) +// sstore(0, keccak256(_1, 33)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul index d1761b7cea..58cb7c264c 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul @@ -19,13 +19,15 @@ // step: loadResolver // // { -// let _1 := 10 -// let _2 := 0 -// mstore(_2, _1) -// sstore(_2, 9948786400348073077032572701554570401043517428989726124163377057770909578447) -// sstore(1, 110945455955148346822663466543669633859020391897956790847617069135813044810108) -// let _13 := 85131057757245807317576516368191972321038229705283732634690444270750521936266 -// let _14 := 2 -// sstore(_14, _13) -// sstore(_14, 89477152217924674838424037953991966239322087453347756267410168184682657981552) +// { +// let _1 := 10 +// let _2 := 0 +// mstore(_2, _1) +// sstore(_2, 9948786400348073077032572701554570401043517428989726124163377057770909578447) +// sstore(1, 110945455955148346822663466543669633859020391897956790847617069135813044810108) +// let _13 := 85131057757245807317576516368191972321038229705283732634690444270750521936266 +// let _14 := 2 +// sstore(_14, _13) +// sstore(_14, 89477152217924674838424037953991966239322087453347756267410168184682657981552) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_string_literal.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_string_literal.yul index 279a23959f..261f38cd1f 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_string_literal.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_string_literal.yul @@ -12,11 +12,13 @@ // step: loadResolver // // { -// let _1 := 50 -// let _2 := "abcdefghijklmn" -// mstore(_1, _2) -// let _3 := 51246744213555520563123611275127692828770413530219146609532820042079541949502 -// let _4 := 0 -// sstore(_4, _3) -// sstore(_4, add(_2, 1)) +// { +// let _1 := 50 +// let _2 := "abcdefghijklmn" +// mstore(_1, _2) +// let _3 := 51246744213555520563123611275127692828770413530219146609532820042079541949502 +// let _4 := 0 +// sstore(_4, _3) +// sstore(_4, add(_2, 1)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_symbolic_memory.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_symbolic_memory.yul index c18af0c8df..46466a062f 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_symbolic_memory.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_symbolic_memory.yul @@ -15,8 +15,10 @@ // step: loadResolver // // { -// let _1 := 0 -// mstore(calldataload(_1), 500) -// sstore(_1, 92647596584187651892918913434663110448935397770592030057655219009846081465370) -// sstore(1, 110620294328144418057589324861608220015688365608948720310623173341503153578932) +// { +// let _1 := 0 +// mstore(calldataload(_1), 500) +// sstore(_1, 92647596584187651892918913434663110448935397770592030057655219009846081465370) +// sstore(1, 110620294328144418057589324861608220015688365608948720310623173341503153578932) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_with_msize.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_with_msize.yul index fdc1e88368..5e1c7d4190 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_with_msize.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_with_msize.yul @@ -11,9 +11,11 @@ // step: loadResolver // // { -// let _1 := msize() -// let _2 := 0 -// sstore(_2, _1) -// mstore(_2, 10) -// sstore(1, keccak256(_2, 32)) +// { +// let _1 := msize() +// let _2 := 0 +// sstore(_2, _1) +// mstore(_2, 10) +// sstore(1, keccak256(_2, 32)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/loop.yul b/test/libyul/yulOptimizerTests/loadResolver/loop.yul index 3606891ee1..4587671606 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/loop.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/loop.yul @@ -8,11 +8,13 @@ // step: loadResolver // // { -// let _1 := 123213 -// let _2 := 0 -// sstore(_2, _1) -// let x := _2 -// let y -// for { } lt(x, _1) { x := add(x, 1) } -// { y := add(x, y) } +// { +// let _1 := 123213 +// let _2 := 0 +// sstore(_2, _1) +// let x := _2 +// let y +// for { } lt(x, _1) { x := add(x, 1) } +// { y := add(x, y) } +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul index 77fc5aef01..840f19005b 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul @@ -18,18 +18,20 @@ // step: loadResolver // // { -// let _1 := 9 -// let _2 := 2 -// mstore(_2, _1) -// let _4 := _1 -// let _5 := 0 -// sstore(_5, _4) -// pop(call(_5, _5, _5, _5, _5, _5, _5)) -// sstore(_5, mload(_2)) -// let _17 := 10 -// mstore(_2, _17) -// mstore8(calldataload(_5), 4) -// sstore(_5, mload(_2)) -// mstore(_2, _17) -// sstore(_5, _17) +// { +// let _1 := 9 +// let _2 := 2 +// mstore(_2, _1) +// let _4 := _1 +// let _5 := 0 +// sstore(_5, _4) +// pop(call(_5, _5, _5, _5, _5, _5, _5)) +// sstore(_5, mload(_2)) +// let _17 := 10 +// mstore(_2, _17) +// mstore8(calldataload(_5), 4) +// sstore(_5, mload(_2)) +// mstore(_2, _17) +// sstore(_5, _17) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_msize.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_msize.yul index 199fb1f6c4..f54053bb10 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/memory_with_msize.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_msize.yul @@ -9,9 +9,11 @@ // step: loadResolver // // { -// let _1 := msize() -// let _3 := calldataload(0) -// mstore(_3, _1) -// let t := mload(calldataload(10)) -// sstore(t, mload(_3)) +// { +// let _1 := msize() +// let _3 := calldataload(0) +// mstore(_3, _1) +// let t := mload(calldataload(10)) +// sstore(t, mload(_3)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_known_write.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_known_write.yul index e9ced5f4c3..acb96c07b1 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_known_write.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_known_write.yul @@ -11,12 +11,14 @@ // step: loadResolver // // { -// let _2 := calldataload(10) -// let _3 := 0 -// let _4 := calldataload(_3) -// mstore(_4, _2) -// let _5 := 1 -// if calldataload(_5) { mstore(_4, _5) } -// let t := mload(_3) -// sstore(t, mload(_4)) +// { +// let _2 := calldataload(10) +// let _3 := 0 +// let _4 := calldataload(_3) +// mstore(_4, _2) +// let _5 := 1 +// if calldataload(_5) { mstore(_4, _5) } +// let t := mload(_3) +// sstore(t, mload(_4)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_known_write_with_distance.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_known_write_with_distance.yul index 8ce9fba00c..1659949a3c 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_known_write_with_distance.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_known_write_with_distance.yul @@ -11,10 +11,12 @@ // step: loadResolver // // { -// let _2 := calldataload(10) -// let _4 := calldataload(0) -// mstore(_4, _2) -// let _5 := 1 -// if calldataload(_5) { mstore(add(_4, 0x20), _5) } -// sstore(mload(add(_4, 0x20)), _2) +// { +// let _2 := calldataload(10) +// let _4 := calldataload(0) +// mstore(_4, _2) +// let _5 := 1 +// if calldataload(_5) { mstore(add(_4, 0x20), _5) } +// sstore(mload(add(_4, 0x20)), _2) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_known_distance.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_known_distance.yul index cde3ec0e6b..18740c0490 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_known_distance.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_known_distance.yul @@ -11,9 +11,11 @@ // step: loadResolver // // { -// let _2 := calldataload(0) -// let x := mload(_2) -// let _3 := 1 -// if calldataload(_3) { mstore(add(_2, 0x20), _3) } -// sstore(mload(add(_2, 0x20)), x) +// { +// let _2 := calldataload(0) +// let x := mload(_2) +// let _3 := 1 +// if calldataload(_3) { mstore(add(_2, 0x20), _3) } +// sstore(mload(add(_2, 0x20)), x) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_rewrite.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_rewrite.yul index 5c09b9b430..00bb85c4c8 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_rewrite.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_rewrite.yul @@ -11,12 +11,14 @@ // step: loadResolver // // { -// let _1 := 2 -// let b := mload(_1) -// if calldataload(1) // { -// mstore(_1, 7) -// mstore(_1, b) +// let _1 := 2 +// let b := mload(_1) +// if calldataload(1) +// { +// mstore(_1, 7) +// mstore(_1, b) +// } +// sstore(0, b) // } -// sstore(0, b) // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_mload_without_rewrite.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_mload_without_rewrite.yul index f6d0bdc7d1..7606416982 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_mload_without_rewrite.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_mload_without_rewrite.yul @@ -10,10 +10,12 @@ // step: loadResolver // // { -// let _1 := 2 -// let b := mload(_1) -// let _2 := 0 -// sstore(_2, b) -// if calldataload(1) { mstore(_1, 7) } -// sstore(_2, mload(_1)) +// { +// let _1 := 2 +// let b := mload(_1) +// let _2 := 0 +// sstore(_2, b) +// if calldataload(1) { mstore(_1, 7) } +// sstore(_2, mload(_1)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_unknown_write.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_unknown_write.yul index 225e0f6272..e8cc3cf4b0 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_unknown_write.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_unknown_write.yul @@ -11,12 +11,14 @@ // step: loadResolver // // { -// let _2 := calldataload(10) -// let _3 := 0 -// let _4 := calldataload(_3) -// mstore(_4, _2) -// let _5 := 1 -// if calldataload(_5) { mstore(_3, _5) } -// let t := mload(_3) -// sstore(t, mload(_4)) +// { +// let _2 := calldataload(10) +// let _3 := 0 +// let _4 := calldataload(_3) +// mstore(_4, _2) +// let _5 := 1 +// if calldataload(_5) { mstore(_3, _5) } +// let t := mload(_3) +// sstore(t, mload(_4)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_with_rewrite.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_with_rewrite.yul index b4b113e812..c6c76f425f 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_with_rewrite.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_with_rewrite.yul @@ -11,13 +11,15 @@ // step: loadResolver // // { -// let _1 := 3 -// let _2 := 2 -// mstore(_2, _1) -// if calldataload(1) // { -// mstore(_2, 7) +// let _1 := 3 +// let _2 := 2 // mstore(_2, _1) +// if calldataload(1) +// { +// mstore(_2, 7) +// mstore(_2, _1) +// } +// sstore(0, _1) // } -// sstore(0, _1) // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul b/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul index a8d9e2af06..b76d071ae8 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul @@ -10,11 +10,13 @@ // step: loadResolver // // { -// let _1 := 1337 -// let _2 := 0 -// mstore(_2, _1) -// foo(42) -// sstore(_2, mload(_2)) +// { +// let _1 := 1337 +// let _2 := 0 +// mstore(_2, _1) +// foo(42) +// sstore(_2, mload(_2)) +// } // function foo(x) // { // for { } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mload_self.yul b/test/libyul/yulOptimizerTests/loadResolver/mload_self.yul index e299bcbb9f..6ad9d36ac7 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mload_self.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mload_self.yul @@ -8,8 +8,10 @@ // step: loadResolver // // { -// let _1 := 0 -// let x := calldataload(_1) -// x := mload(x) -// sstore(_1, mload(x)) +// { +// let _1 := 0 +// let x := calldataload(_1) +// x := mload(x) +// sstore(_1, mload(x)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul index 6fcf7a6aa8..901ea12efc 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul @@ -15,11 +15,13 @@ // step: loadResolver // // { -// let _1 := 1337 -// let _2 := 0 -// mstore(_2, _1) -// funcWithLoop(42) -// sstore(_2, mload(_2)) +// { +// let _1 := 1337 +// let _2 := 0 +// mstore(_2, _1) +// funcWithLoop(42) +// sstore(_2, mload(_2)) +// } // function userNot(x) -> y // { y := iszero(x) } // function funcWithLoop(x_1) diff --git a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul index 4794237d67..6fb0fdcba9 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul @@ -15,11 +15,13 @@ // step: loadResolver // // { -// let _1 := 1337 -// let _2 := 0 -// mstore(_2, _1) -// funcWithLoop(42) -// sstore(_2, mload(_2)) +// { +// let _1 := 1337 +// let _2 := 0 +// mstore(_2, _1) +// funcWithLoop(42) +// sstore(_2, mload(_2)) +// } // function userNot(x) -> y // { y := iszero(x) } // function funcWithLoop(x_1) diff --git a/test/libyul/yulOptimizerTests/loadResolver/multi_sload_loop.yul b/test/libyul/yulOptimizerTests/loadResolver/multi_sload_loop.yul index 9aecad5290..c367059eb9 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/multi_sload_loop.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/multi_sload_loop.yul @@ -14,17 +14,19 @@ // step: loadResolver // // { -// let _1 := 0 -// let x := calldataload(_1) -// let len := sload(x) -// let sum -// let i := _1 -// for { } lt(i, len) { i := add(i, 1) } // { -// let p := add(add(x, i), 1) -// if gt(p, len) { revert(_1, _1) } -// sum := add(sum, sload(p)) +// let _1 := 0 +// let x := calldataload(_1) +// let len := sload(x) +// let sum +// let i := _1 +// for { } lt(i, len) { i := add(i, 1) } +// { +// let p := add(add(x, i), 1) +// if gt(p, len) { revert(_1, _1) } +// sum := add(sum, sload(p)) +// } +// mstore(_1, sum) +// return(_1, 0x20) // } -// mstore(_1, sum) -// return(_1, 0x20) // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/re_store_memory.yul b/test/libyul/yulOptimizerTests/loadResolver/re_store_memory.yul index 01e29b705e..031a5f22a5 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/re_store_memory.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/re_store_memory.yul @@ -11,11 +11,13 @@ // step: loadResolver // // { -// let a := 0 -// let b := 1 -// let c := 2 -// mstore(a, b) -// sstore(a, b) -// mstore(a, c) -// sstore(10, c) +// { +// let a := 0 +// let b := 1 +// let c := 2 +// mstore(a, b) +// sstore(a, b) +// mstore(a, c) +// sstore(10, c) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/re_store_storage.yul b/test/libyul/yulOptimizerTests/loadResolver/re_store_storage.yul index 8c33e4f5dc..fab562208b 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/re_store_storage.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/re_store_storage.yul @@ -11,11 +11,13 @@ // step: loadResolver // // { -// let a := 0 -// let b := 1 -// let c := 2 -// sstore(a, b) -// mstore(a, b) -// sstore(a, c) -// mstore(32, c) +// { +// let a := 0 +// let b := 1 +// let c := 2 +// sstore(a, b) +// mstore(a, b) +// sstore(a, c) +// mstore(32, c) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/reassign.yul b/test/libyul/yulOptimizerTests/loadResolver/reassign.yul index 4687422e92..694b59e262 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/reassign.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/reassign.yul @@ -8,9 +8,11 @@ // step: loadResolver // // { -// let _1 := 0 -// let a := calldataload(_1) -// sstore(a, 6) -// a := calldataload(2) -// mstore(_1, sload(a)) +// { +// let _1 := 0 +// let a := calldataload(_1) +// sstore(a, 6) +// a := calldataload(2) +// mstore(_1, sload(a)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/reassign_value_expression.yul b/test/libyul/yulOptimizerTests/loadResolver/reassign_value_expression.yul index 1b73cecb93..402987acb4 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/reassign_value_expression.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/reassign_value_expression.yul @@ -18,15 +18,17 @@ // step: loadResolver // // { -// let x := calldataload(1) -// let a := add(x, 10) -// let _3 := 7 -// sstore(a, _3) -// x := 9 -// let _4 := 11 -// mstore(_3, _4) -// a := 33 -// mstore(sload(a), _4) -// a := 39 -// mstore(sload(a), _4) +// { +// let x := calldataload(1) +// let a := add(x, 10) +// let _3 := 7 +// sstore(a, _3) +// x := 9 +// let _4 := 11 +// mstore(_3, _4) +// a := 33 +// mstore(sload(a), _4) +// a := 39 +// mstore(sload(a), _4) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/second_mstore_with_delta.yul b/test/libyul/yulOptimizerTests/loadResolver/second_mstore_with_delta.yul index 1aa05106c3..8f1cf338f6 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/second_mstore_with_delta.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/second_mstore_with_delta.yul @@ -13,12 +13,14 @@ // step: loadResolver // // { -// let x := calldataload(1) -// let a := add(x, 10) -// let b := add(x, 42) -// let _4 := 7 -// mstore(a, _4) -// let _5 := 8 -// mstore(b, _5) -// sstore(_4, _5) +// { +// let x := calldataload(1) +// let a := add(x, 10) +// let b := add(x, 42) +// let _4 := 7 +// mstore(a, _4) +// let _5 := 8 +// mstore(b, _5) +// sstore(_4, _5) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/second_store.yul b/test/libyul/yulOptimizerTests/loadResolver/second_store.yul index f6f8250ce0..eb960a9f6e 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/second_store.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/second_store.yul @@ -10,10 +10,12 @@ // step: loadResolver // // { -// let x := calldataload(1) -// sstore(x, 7) -// let _3 := 6 -// let _4 := 0 -// sstore(calldataload(_4), _3) -// mstore(_4, sload(x)) +// { +// let x := calldataload(1) +// sstore(x, 7) +// let _3 := 6 +// let _4 := 0 +// sstore(calldataload(_4), _3) +// mstore(_4, sload(x)) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/second_store_same_value.yul b/test/libyul/yulOptimizerTests/loadResolver/second_store_same_value.yul index a5cb459ad7..e13b8aa5f6 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/second_store_same_value.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/second_store_same_value.yul @@ -10,10 +10,12 @@ // step: loadResolver // // { -// let x := calldataload(1) -// let _2 := 7 -// sstore(x, _2) -// let _4 := 0 -// sstore(calldataload(_4), _2) -// mstore(_4, _2) +// { +// let x := calldataload(1) +// let _2 := 7 +// sstore(x, _2) +// let _4 := 0 +// sstore(calldataload(_4), _2) +// mstore(_4, _2) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/second_store_with_delta.yul b/test/libyul/yulOptimizerTests/loadResolver/second_store_with_delta.yul index c2e669b7f6..f301737eca 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/second_store_with_delta.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/second_store_with_delta.yul @@ -13,12 +13,14 @@ // step: loadResolver // // { -// let x := calldataload(1) -// let a := add(x, 10) -// let b := add(x, 20) -// let _4 := 7 -// sstore(a, _4) -// let _5 := 8 -// sstore(b, _5) -// mstore(_4, _5) +// { +// let x := calldataload(1) +// let a := add(x, 10) +// let b := add(x, 20) +// let _4 := 7 +// sstore(a, _4) +// let _5 := 8 +// sstore(b, _5) +// mstore(_4, _5) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul b/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul index 684e6b94f1..b1eefd0890 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul @@ -12,15 +12,17 @@ // step: loadResolver // // { -// let _1 := 9 -// let _2 := 2 -// mstore(_2, _1) -// reads() -// let _4 := _1 -// let _5 := 0 -// sstore(_5, _4) -// stores() -// sstore(_5, mload(_2)) +// { +// let _1 := 9 +// let _2 := 2 +// mstore(_2, _1) +// reads() +// let _4 := _1 +// let _5 := 0 +// sstore(_5, _4) +// stores() +// sstore(_5, mload(_2)) +// } // function stores() // { mstore(0, 1) } // function reads() diff --git a/test/libyul/yulOptimizerTests/loadResolver/simple.yul b/test/libyul/yulOptimizerTests/loadResolver/simple.yul index a645f1692f..a20025bcdf 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/simple.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/simple.yul @@ -8,7 +8,9 @@ // step: loadResolver // // { -// let _2 := calldataload(10) -// sstore(calldataload(0), _2) -// mstore(sload(_2), _2) +// { +// let _2 := calldataload(10) +// sstore(calldataload(0), _2) +// mstore(sload(_2), _2) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/simple_memory.yul b/test/libyul/yulOptimizerTests/loadResolver/simple_memory.yul index 667abe053c..3aa1d740f4 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/simple_memory.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/simple_memory.yul @@ -8,7 +8,9 @@ // step: loadResolver // // { -// let _2 := calldataload(10) -// mstore(calldataload(0), _2) -// sstore(mload(_2), _2) +// { +// let _2 := calldataload(10) +// mstore(calldataload(0), _2) +// sstore(mload(_2), _2) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul b/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul index b24ab0170c..2a72eee3e2 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul @@ -15,14 +15,16 @@ // step: loadResolver // // { -// let a := 0 -// let b := 1 -// sstore(a, b) -// let _1 := 7 -// let _2 := 900 -// mstore(_2, _1) -// let _3 := 200 -// pop(staticcall(10000, 10, a, _3, a, _3)) -// sstore(1, mload(_2)) -// mstore(a, b) +// { +// let a := 0 +// let b := 1 +// sstore(a, b) +// let _1 := 7 +// let _2 := 900 +// mstore(_2, _1) +// let _3 := 200 +// pop(staticcall(10000, 10, a, _3, a, _3)) +// sstore(1, mload(_2)) +// mstore(a, b) +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/verbatim_mload.yul b/test/libyul/yulOptimizerTests/loadResolver/verbatim_mload.yul index 150c0240b5..8d417a1776 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/verbatim_mload.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/verbatim_mload.yul @@ -8,9 +8,11 @@ // step: loadResolver // // { -// let _1 := 20 -// let _2 := 10 -// mstore(_2, _1) -// sstore(0, mload(_2)) -// verbatim_0i_0o("test") +// { +// let _1 := 20 +// let _2 := 10 +// mstore(_2, _1) +// sstore(0, mload(_2)) +// verbatim_0i_0o("test") +// } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/verbatim_sload.yul b/test/libyul/yulOptimizerTests/loadResolver/verbatim_sload.yul index ba9cb32d80..81479a5092 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/verbatim_sload.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/verbatim_sload.yul @@ -10,12 +10,14 @@ // step: loadResolver // // { -// let _1 := 20 -// let _2 := 10 -// sstore(_2, _1) -// let _4 := _1 -// let _5 := 30 -// sstore(_5, _4) -// verbatim_0i_0o("test") -// sstore(_5, sload(_2)) +// { +// let _1 := 20 +// let _2 := 10 +// sstore(_2, _1) +// let _4 := _1 +// let _5 := 30 +// sstore(_5, _4) +// verbatim_0i_0o("test") +// sstore(_5, sload(_2)) +// } // } diff --git a/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul b/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul index c8b22424cc..875bececd6 100644 --- a/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul +++ b/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul @@ -10,12 +10,14 @@ // step: splitJoin // // { -// if mul(add(calldataload(0), 2), 3) // { -// for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } +// if mul(add(calldataload(0), 2), 3) // { -// let b := mul(add(a, 2), 4) -// sstore(b, mul(b, 2)) +// for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } +// { +// let b := mul(add(a, 2), 4) +// sstore(b, mul(b, 2)) +// } // } // } // } diff --git a/test/libyul/yulOptimizerTests/splitJoin/functions.yul b/test/libyul/yulOptimizerTests/splitJoin/functions.yul index e2f554dd0e..08e741e8e9 100644 --- a/test/libyul/yulOptimizerTests/splitJoin/functions.yul +++ b/test/libyul/yulOptimizerTests/splitJoin/functions.yul @@ -12,14 +12,16 @@ // step: splitJoin // // { -// let x := f(0) -// function f(y) -> r // { -// r := mload(mul(6, add(y, 0x20))) +// let x := f(0) +// for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } +// { +// let b := mul(add(a, f(a)), 4) +// sstore(b, mul(b, 2)) +// } // } -// for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } +// function f(y) -> r // { -// let b := mul(add(a, f(a)), 4) -// sstore(b, mul(b, 2)) +// r := mload(mul(6, add(y, 0x20))) // } // } diff --git a/test/libyul/yulOptimizerTests/splitJoin/smoke.yul b/test/libyul/yulOptimizerTests/splitJoin/smoke.yul index 4aac31ddb6..86e53ab148 100644 --- a/test/libyul/yulOptimizerTests/splitJoin/smoke.yul +++ b/test/libyul/yulOptimizerTests/splitJoin/smoke.yul @@ -2,4 +2,4 @@ // ---- // step: splitJoin // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul index 43b9ade6a0..19b3ba44ea 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul @@ -19,12 +19,14 @@ // step: ssaAndBack // // { -// let a := mload(0) -// let b := mload(1) -// for { } lt(mload(a), mload(b)) { a := mload(b) } // { -// let b_4 := mload(a) -// a := mload(b_4) -// b := mload(a) +// let a := mload(0) +// let b := mload(1) +// for { } lt(mload(a), mload(b)) { a := mload(b) } +// { +// let b_4 := mload(a) +// a := mload(b_4) +// b := mload(a) +// } // } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul index 2e818561c6..1bfd89cd83 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul @@ -10,6 +10,8 @@ // step: ssaAndBack // // { -// let a_5 := mload(4) -// mstore(a_5, 0) +// { +// let a_5 := mload(4) +// mstore(a_5, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul index 4815349d7d..c0f3a4242a 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul @@ -12,7 +12,9 @@ // step: ssaAndBack // // { -// let a := mload(0) -// if mload(1) { a := mload(3) } -// mstore(a, 0) +// { +// let a := mload(0) +// if mload(1) { a := mload(3) } +// mstore(a, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul index a0821ab373..e3a6710282 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul @@ -13,14 +13,16 @@ // step: ssaAndBack // // { -// let a := mload(0) -// let b := mload(1) -// if mload(2) // { -// let a_3 := mload(b) -// let b_4 := mload(a_3) -// a := mload(b_4) -// b := mload(a) +// let a := mload(0) +// let b := mload(1) +// if mload(2) +// { +// let a_3 := mload(b) +// let b_4 := mload(a_3) +// a := mload(b_4) +// b := mload(a) +// } +// mstore(a, b) // } -// mstore(a, b) // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul index 92a0ba8259..89f3acaa63 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul @@ -20,20 +20,22 @@ // step: ssaAndBack // // { -// let a := mload(0) -// let b := mload(1) -// switch mload(2) -// case 0 { -// let a_3 := mload(b) -// let b_4 := mload(a_3) -// a := mload(b_4) -// b := mload(a) +// { +// let a := mload(0) +// let b := mload(1) +// switch mload(2) +// case 0 { +// let a_3 := mload(b) +// let b_4 := mload(a_3) +// a := mload(b_4) +// b := mload(a) +// } +// default { +// let b_7 := mload(a) +// let a_8 := mload(b_7) +// b := mload(a_8) +// a := mload(b) +// } +// mstore(a, b) // } -// default { -// let b_7 := mload(a) -// let a_8 := mload(b_7) -// b := mload(a_8) -// a := mload(b) -// } -// mstore(a, b) // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul index 63c4f8561e..b210c09c0e 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul @@ -17,9 +17,11 @@ // step: ssaAndBack // // { -// let a := mload(0) -// switch mload(1) -// case 0 { a := mload(3) } -// default { a := mload(6) } -// mstore(a, 0) +// { +// let a := mload(0) +// switch mload(1) +// case 0 { a := mload(3) } +// default { a := mload(6) } +// mstore(a, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul b/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul index e2f130507a..b2979e76d2 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul @@ -7,6 +7,8 @@ // step: ssaAndBack // // { -// let a_2 := mload(1) -// mstore(a_2, 0) +// { +// let a_2 := mload(1) +// mstore(a_2, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul index e2516b45b9..71823f105a 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul @@ -10,7 +10,9 @@ // step: ssaAndBack // // { -// let a := mload(0) -// if mload(1) { a := mload(1) } -// mstore(a, 0) +// { +// let a := mload(0) +// if mload(1) { a := mload(1) } +// mstore(a, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul index e6e0553c18..8c53bd28ab 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul @@ -13,9 +13,11 @@ // step: ssaAndBack // // { -// let a := mload(0) -// switch mload(1) -// case 0 { a := mload(1) } -// default { a := mload(2) } -// mstore(a, 0) +// { +// let a := mload(0) +// switch mload(1) +// case 0 { a := mload(1) } +// default { a := mload(2) } +// mstore(a, 0) +// } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul b/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul index 0ef0ffee39..21dfdf2cee 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul @@ -24,8 +24,10 @@ // step: ssaAndBack // // { -// let a, b := abi_decode_t_bytes_calldata_ptr(mload(0), mload(1)) -// mstore(a, b) +// { +// let a, b := abi_decode_t_bytes_calldata_ptr(mload(0), mload(1)) +// mstore(a, b) +// } // function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 // { // if iszero(slt(add(offset_12, 0x1f), end_13)) { revert(0, 0) } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul b/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul index 6053bd9ac9..1205993567 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul @@ -11,11 +11,13 @@ // step: ssaAndBack // // { -// let a_1 := mload(0) -// let b_2 := mload(a_1) -// let a_3 := mload(b_2) -// let b_4 := mload(a_3) -// let a_5 := mload(b_4) -// let b_6 := mload(a_5) -// mstore(a_5, b_6) +// { +// let a_1 := mload(0) +// let b_2 := mload(a_1) +// let a_3 := mload(b_2) +// let b_4 := mload(a_3) +// let a_5 := mload(b_4) +// let b_6 := mload(a_5) +// mstore(a_5, b_6) +// } // } diff --git a/test/libyul/yulOptimizerTests/stackCompressor/inlineInBlock.yul b/test/libyul/yulOptimizerTests/stackCompressor/inlineInBlock.yul index 382bd201d6..3633b3f36c 100644 --- a/test/libyul/yulOptimizerTests/stackCompressor/inlineInBlock.yul +++ b/test/libyul/yulOptimizerTests/stackCompressor/inlineInBlock.yul @@ -9,5 +9,7 @@ // step: stackCompressor // // { -// mstore(calldataload(calldataload(9)), add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(calldataload(calldataload(9)), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)) +// { +// mstore(calldataload(calldataload(9)), add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(calldataload(calldataload(9)), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)) +// } // } diff --git a/test/libyul/yulOptimizerTests/stackCompressor/inlineInFunction.yul b/test/libyul/yulOptimizerTests/stackCompressor/inlineInFunction.yul index ed85fe7b85..35dfa5343d 100644 --- a/test/libyul/yulOptimizerTests/stackCompressor/inlineInFunction.yul +++ b/test/libyul/yulOptimizerTests/stackCompressor/inlineInFunction.yul @@ -11,7 +11,7 @@ // step: stackCompressor // // { -// let x := 8 +// { let x := 8 } // function f() // { // mstore(calldataload(calldataload(9)), add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(add(calldataload(calldataload(9)), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)) diff --git a/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul b/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul index b5f3dd8725..1a178abf09 100644 --- a/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul +++ b/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul @@ -6,7 +6,7 @@ // step: stackCompressor // // { -// let x := 8 +// { let x := 8 } // function f() // { let y := 9 } // } diff --git a/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul b/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul index dc10737ad9..0556a22202 100644 --- a/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul +++ b/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul @@ -24,15 +24,17 @@ // step: stackCompressor // // { -// let _17_72 := msize() -// let _22_75 := msize() -// let _25_76 := msize() -// let _30_80 := msize() -// let _32_81 := msize() -// pop(keccak256(1, 2)) -// let _105 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -// mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(_105, _32_81), 1), _30_80), lt(or(1, add(_25_76, _105)), 1)), _22_75), 1), 1), gt(not(_17_72), 1)), 1)), 1), 1), 1) -// foo_singlereturn_1() +// { +// let _17_72 := msize() +// let _22_75 := msize() +// let _25_76 := msize() +// let _30_80 := msize() +// let _32_81 := msize() +// pop(keccak256(1, 2)) +// let _105 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(_105, _32_81), 1), _30_80), lt(or(1, add(_25_76, _105)), 1)), _22_75), 1), 1), gt(not(_17_72), 1)), 1)), 1), 1), 1) +// foo_singlereturn_1() +// } // function foo_singlereturn_1() // { extcodecopy(1, msize(), 1, 1) } // } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/functions.yul b/test/libyul/yulOptimizerTests/unusedPruner/functions.yul index cceace3bbb..cafb399f61 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/functions.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/functions.yul @@ -5,4 +5,4 @@ // ---- // step: unusedPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul index 32e96b9f3a..00bb145adb 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul @@ -7,6 +7,8 @@ // step: unusedPruner // // { -// let a := 1 -// a := 4 +// { +// let a := 1 +// a := 4 +// } // } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul index bc05f09f8a..4132a93f85 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul @@ -8,9 +8,11 @@ // step: unusedPruner // // { -// let a, b +// { +// let a, b +// a := f() +// b := 1 +// } // function f() -> x // { } -// a := f() -// b := 1 // } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/keccak.yul b/test/libyul/yulOptimizerTests/unusedPruner/keccak.yul index 6ad93184a6..357b3a33cf 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/keccak.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/keccak.yul @@ -7,6 +7,8 @@ // step: unusedPruner // // { -// pop(keccak256(1, 1)) -// sstore(0, msize()) +// { +// pop(keccak256(1, 1)) +// sstore(0, msize()) +// } // } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/movable_user_defined_function.yul b/test/libyul/yulOptimizerTests/unusedPruner/movable_user_defined_function.yul index 09d366fb29..43a4297cb5 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/movable_user_defined_function.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/movable_user_defined_function.yul @@ -10,4 +10,4 @@ // ---- // step: unusedPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/msize.yul b/test/libyul/yulOptimizerTests/unusedPruner/msize.yul index 05ad7b743e..633b447cd9 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/msize.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/msize.yul @@ -7,6 +7,8 @@ // step: unusedPruner // // { -// pop(mload(10)) -// sstore(0, msize()) +// { +// pop(mload(10)) +// sstore(0, msize()) +// } // } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul index 47e114373b..aac772dcb9 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul @@ -8,9 +8,11 @@ // step: unusedPruner // // { -// let a -// let b +// { +// let a +// let b +// a, b := f() +// } // function f() -> x, y // { } -// a, b := f() // } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul index 86f175d695..a987efe800 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul @@ -7,7 +7,9 @@ // step: unusedPruner // // { -// let x, y -// x := 1 -// y := 2 +// { +// let x, y +// x := 1 +// y := 2 +// } // } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul index f727b0e93c..3f70d6638a 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul @@ -4,4 +4,4 @@ // ---- // step: unusedPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul index aa8ae0ad4b..d65b4d5d7e 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul @@ -5,4 +5,4 @@ // ---- // step: unusedPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul index f54087a7d8..d66889a889 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul @@ -6,6 +6,8 @@ // step: unusedPruner // // { -// let x, y -// x := 1 +// { +// let x, y +// x := 1 +// } // } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/no_msize.yul b/test/libyul/yulOptimizerTests/unusedPruner/no_msize.yul index 7bfc4d7884..0591c0e2a6 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/no_msize.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/no_msize.yul @@ -6,4 +6,4 @@ // ---- // step: unusedPruner // -// { sstore(0, 5) } +// { { sstore(0, 5) } } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/pop.yul b/test/libyul/yulOptimizerTests/unusedPruner/pop.yul index 66d16db1ed..636552eee3 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/pop.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/pop.yul @@ -5,4 +5,4 @@ // ---- // step: unusedPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul b/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul index a2ac495a04..3315ce2c42 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul @@ -2,4 +2,4 @@ // ---- // step: unusedPruner // -// { } +// { { } } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul b/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul index 9de594351b..8a47d21083 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul @@ -6,4 +6,4 @@ // ---- // step: unusedPruner // -// { mstore(0, 1) } +// { { mstore(0, 1) } } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/verbatim.yul b/test/libyul/yulOptimizerTests/unusedPruner/verbatim.yul index 65b464f7f5..7fea85c52c 100644 --- a/test/libyul/yulOptimizerTests/unusedPruner/verbatim.yul +++ b/test/libyul/yulOptimizerTests/unusedPruner/verbatim.yul @@ -11,7 +11,9 @@ // step: unusedPruner // // { -// pop(mload(10)) -// pop(keccak256(10, 32)) -// verbatim_0i_0o("test") +// { +// pop(mload(10)) +// pop(keccak256(10, 32)) +// verbatim_0i_0o("test") +// } // } diff --git a/test/yulPhaser/Program.cpp b/test/yulPhaser/Program.cpp index 8aa2479a21..2e91926d05 100644 --- a/test/yulPhaser/Program.cpp +++ b/test/yulPhaser/Program.cpp @@ -337,7 +337,10 @@ BOOST_AUTO_TEST_CASE(optimise) Block const& parentBlockAfter = program.ast(); BOOST_TEST(parentBlockAfter.statements.size() == 1); - BOOST_TEST(holds_alternative(parentBlockAfter.statements[0])); + BOOST_TEST(holds_alternative(parentBlockAfter.statements[0])); + Block const& innerBlock = get(parentBlockAfter.statements[0]); + BOOST_TEST(innerBlock.statements.size() == 1); + BOOST_TEST(holds_alternative(innerBlock.statements[0])); } BOOST_AUTO_TEST_CASE(output_operator) From fbc48e30292db668de3874bf0fc9a9e74e9f471b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 28 Oct 2021 12:32:53 +0200 Subject: [PATCH 0004/1704] Extract helpers for managing steps in parallelized CircleCI jobs from soltest_all.sh --- .circleci/soltest_all.sh | 41 +++++++++++++++++++++++----------------- scripts/common.sh | 22 +++++++++++++++++++++ 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 353d81cd68..0c414593f3 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -28,27 +28,31 @@ set -e REPODIR="$(realpath "$(dirname "$0")"/..)" +# shellcheck source=scripts/common.sh +source "${REPODIR}/scripts/common.sh" + EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin london) DEFAULT_EVM=london [[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]] OPTIMIZE_VALUES=(0 1) STEPS=$(( 1 + ${#EVM_VALUES[@]} * ${#OPTIMIZE_VALUES[@]} )) -if (( CIRCLE_NODE_TOTAL )) && (( CIRCLE_NODE_TOTAL > 1 )) -then - RUN_STEPS=$(seq "$STEPS" | circleci tests split | xargs) -else - RUN_STEPS=$(seq "$STEPS" | xargs) -fi - -echo "Running steps $RUN_STEPS..." +RUN_STEPS=$(circleci_select_steps "$(seq "$STEPS")") +printTask "Running steps $RUN_STEPS..." STEP=1 # Run for ABI encoder v1, without SMTChecker tests. -[[ " $RUN_STEPS " == *" $STEP "* ]] && EVM="${DEFAULT_EVM}" OPTIMIZE=1 ABI_ENCODER_V1=1 BOOST_TEST_ARGS="-t !smtCheckerTests" "${REPODIR}/.circleci/soltest.sh" -STEP=$((STEP + 1)) +if circleci_step_selected "$RUN_STEPS" "$STEP" +then + EVM="${DEFAULT_EVM}" \ + OPTIMIZE=1 \ + ABI_ENCODER_V1=1 \ + BOOST_TEST_ARGS="-t !smtCheckerTests" \ + "${REPODIR}/.circleci/soltest.sh" +fi +((++STEP)) for OPTIMIZE in "${OPTIMIZE_VALUES[@]}" do @@ -63,13 +67,16 @@ do DISABLE_SMTCHECKER="" [ "${OPTIMIZE}" != "0" ] && DISABLE_SMTCHECKER="-t !smtCheckerTests" - [[ " $RUN_STEPS " == *" $STEP "* ]] && EVM="$EVM" OPTIMIZE="$OPTIMIZE" SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS $EWASM_ARGS" BOOST_TEST_ARGS="-t !@nooptions $DISABLE_SMTCHECKER" "${REPODIR}/.circleci/soltest.sh" - STEP=$((STEP + 1)) + if circleci_step_selected "$RUN_STEPS" "$STEP" + then + EVM="$EVM" \ + OPTIMIZE="$OPTIMIZE" \ + SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS $EWASM_ARGS" \ + BOOST_TEST_ARGS="-t !@nooptions $DISABLE_SMTCHECKER" \ + "${REPODIR}/.circleci/soltest.sh" + fi + ((++STEP)) done done -if ((STEP != STEPS + 1)) -then - echo "Step counter not properly adjusted!" >&2 - exit 1 -fi +((STEP == STEPS + 1)) || assertFail "Step counter not properly adjusted!" diff --git a/scripts/common.sh b/scripts/common.sh index 3e40754a61..d529b5bfc2 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -196,3 +196,25 @@ function safe_kill kill -9 "$PID" fi } + +function circleci_select_steps +{ + local all_steps="$1" + (( $# == 1 )) || assertFail + + if (( CIRCLE_NODE_TOTAL )) && (( CIRCLE_NODE_TOTAL > 1 )) + then + echo "$all_steps" | circleci tests split | xargs + else + echo "$all_steps" | xargs + fi +} + +function circleci_step_selected +{ + local selected_steps="$1" + local step="$2" + [[ $step != *" "* ]] || assertFail "Step names must not contain spaces." + + [[ " $selected_steps " == *" $step "* ]] || return 1 +} From 834f9d3a6ec00357efbb4e3b68813f281a71acff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 28 Oct 2021 12:46:34 +0200 Subject: [PATCH 0005/1704] Parallelize external test runs on CircleCI --- .circleci/config.yml | 2 ++ test/externalTests/colony.sh | 6 +++++- test/externalTests/common.sh | 9 +++++++++ test/externalTests/ens.sh | 6 +++++- test/externalTests/gnosis-v2.sh | 6 +++++- test/externalTests/gnosis.sh | 6 +++++- test/externalTests/zeppelin.sh | 6 +++++- 7 files changed, 36 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 72434ea15c..02787debc4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -943,6 +943,8 @@ jobs: default: 14 docker: - image: circleci/node:<> + # NOTE: Each external test does 3 separate compile&test runs + parallelism: 3 environment: TERM: xterm COMPILE_ONLY: <> diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index e32385af65..3aaff44138 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -38,6 +38,10 @@ function colony_test local min_optimizer_level=3 local max_optimizer_level=3 + local selected_optimizer_levels + selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") + print_optimizer_levels_or_exit "$selected_optimizer_levels" + setup_solcjs "$DIR" "$SOLJSON" download_project "$repo" "$branch" "$DIR" @@ -54,7 +58,7 @@ function colony_test replace_version_pragmas force_solc_modules "${DIR}/solc" - for level in $(seq "$min_optimizer_level" "$max_optimizer_level"); do + for level in $selected_optimizer_levels; do truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn done } diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index dbda3c3f46..2519a0f878 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -24,6 +24,15 @@ set -e CURRENT_EVM_VERSION=london +function print_optimizer_levels_or_exit +{ + local selected_levels="$1" + + [[ $selected_levels != "" ]] || { printWarning "No steps to run. Exiting."; exit 0; } + + printLog "Selected optimizer levels: ${selected_levels}" +} + function verify_input { if [ ! -f "$1" ]; then diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index bbdc573e21..9fed91be1f 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -38,6 +38,10 @@ function ens_test local min_optimizer_level=1 local max_optimizer_level=3 + local selected_optimizer_levels + selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") + print_optimizer_levels_or_exit "$selected_optimizer_levels" + setup_solcjs "$DIR" "$SOLJSON" download_project "$repo" "$branch" "$DIR" @@ -52,7 +56,7 @@ function ens_test replace_version_pragmas force_solc_modules "${DIR}/solc" - for level in $(seq "$min_optimizer_level" "$max_optimizer_level"); do + for level in $selected_optimizer_levels; do truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn done } diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index d92bcc1868..439a3dd91f 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -39,6 +39,10 @@ function gnosis_safe_test local min_optimizer_level=2 local max_optimizer_level=3 + local selected_optimizer_levels + selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") + print_optimizer_levels_or_exit "$selected_optimizer_levels" + setup_solcjs "$DIR" "$SOLJSON" download_project "$repo" "$branch" "$DIR" @@ -53,7 +57,7 @@ function gnosis_safe_test replace_version_pragmas force_solc_modules "${DIR}/solc" - for level in $(seq "$min_optimizer_level" "$max_optimizer_level"); do + for level in $selected_optimizer_levels; do truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn done } diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index b6d9ab0bcb..32b76d9c90 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -38,6 +38,10 @@ function gnosis_safe_test local min_optimizer_level=2 local max_optimizer_level=3 + local selected_optimizer_levels + selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") + print_optimizer_levels_or_exit "$selected_optimizer_levels" + setup_solcjs "$DIR" "$SOLJSON" download_project "$repo" "$branch" "$DIR" @@ -51,7 +55,7 @@ function gnosis_safe_test replace_version_pragmas force_solc_modules "${DIR}/solc" - for level in $(seq "$min_optimizer_level" "$max_optimizer_level"); do + for level in $selected_optimizer_levels; do truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn done } diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 1e23bb7ae5..24e576b931 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -38,6 +38,10 @@ function zeppelin_test local min_optimizer_level=1 local max_optimizer_level=3 + local selected_optimizer_levels + selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") + print_optimizer_levels_or_exit "$selected_optimizer_levels" + setup_solcjs "$DIR" "$SOLJSON" download_project "$repo" "$branch" "$DIR" @@ -48,7 +52,7 @@ function zeppelin_test replace_version_pragmas force_solc_modules "${DIR}/solc" - for level in $(seq "$min_optimizer_level" "$max_optimizer_level"); do + for level in $selected_optimizer_levels; do truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn done } From 0ec3f523bd22a8196135ea38a7bbab0b8cb1f62d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 10 Nov 2021 17:05:23 +0100 Subject: [PATCH 0006/1704] CI: Workaround for $CIRCLE_PULL_REQUEST pointing at random PRs in runs outside of PRs --- .circleci/config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 72434ea15c..5575c88727 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,7 +44,9 @@ commands: name: "Gitter notification" when: << parameters.condition >> command: | - [[ $CI_PULL_REQUEST == "" ]] || { echo "Running on a PR - notification skipped."; exit 0; } + # FIXME: Checking $CIRCLE_PULL_REQUEST would be better than hard-coding branch names + # but it's broken. CircleCI associates runs on develop/breaking with random old PRs. + [[ $CIRCLE_BRANCH == develop || $CIRCLE_BRANCH == breaking ]] || { echo "Running on a PR or a feature branch - notification skipped."; exit 0; } [[ "<< parameters.event >>" == "failure" ]] && message=" ❌ Nightly job **${CIRCLE_JOB}** failed on **${CIRCLE_BRANCH}**. Please see [build #${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." [[ "<< parameters.event >>" == "success" ]] && message=" ✅ Nightly job **${CIRCLE_JOB}** succeeded on **${CIRCLE_BRANCH}**. Please see [build #${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." From 0d82fe9ca7fcc2fa34a08100c694011261126189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 14 Oct 2021 17:30:13 +0200 Subject: [PATCH 0007/1704] cmdlineTests.sh: Test the equivalence of one and two-stage compilation via IR --- scripts/common.sh | 12 +++++++ test/cmdlineTests.sh | 85 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/scripts/common.sh b/scripts/common.sh index 3e40754a61..fabfb6d72c 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -171,6 +171,18 @@ function msg_on_error fi } +function diff_values +{ + (( $# >= 2 )) || fail "diff_values requires at least 2 arguments." + + local value1="$1" + local value2="$2" + shift + shift + + diff --color=auto --unified=0 <(echo "$value1") <(echo "$value2") "$@" +} + function safe_kill { local PID=${1} diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 2076eb993e..4f9d41384b 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -308,6 +308,61 @@ function test_solc_assembly_output fi } +function test_via_ir_equivalence() +{ + (( $# <= 2 )) || fail "This function accepts at most two arguments." + + if [[ $2 != --optimize ]] && [[ $2 != "" ]] + then + fail "The second argument must be --optimize if present." + fi + + local solidity_code="$1" + local optimize_flag="$2" + + local optimizer_flags=() + [[ $optimize_flag == "" ]] || optimizer_flags+=("$optimize_flag") + + local ir_output + ir_output=$( + echo "$solidity_code" | + msg_on_error --no-stderr "$SOLC" - --ir-optimized --debug-info location "${optimizer_flags[@]}" | + sed '/^Optimized IR:$/d' + ) + + local asm_output_two_stage asm_output_via_ir + asm_output_two_stage=$( + echo "$ir_output" | + msg_on_error --no-stderr "$SOLC" - --strict-assembly --asm "${optimizer_flags[@]}" | + sed '/^======= /d' | + sed '/^Text representation:$/d' + ) + asm_output_via_ir=$( + echo "$solidity_code" | + msg_on_error --no-stderr "$SOLC" - --experimental-via-ir --asm --debug-info location "${optimizer_flags[@]}" | + sed '/^======= /d' | + sed '/^EVM assembly:$/d' + ) + + diff_values "$asm_output_two_stage" "$asm_output_via_ir" --ignore-space-change --ignore-blank-lines + + local bin_output_two_stage bin_output_via_ir + bin_output_two_stage=$( + echo "$ir_output" | + msg_on_error --no-stderr "$SOLC" - --strict-assembly --bin "${optimizer_flags[@]}" | + sed '/^======= /d' | + sed '/^Binary representation:$/d' + ) + bin_output_via_ir=$( + echo "$solidity_code" | + msg_on_error --no-stderr "$SOLC" - --experimental-via-ir --bin "${optimizer_flags[@]}" | + sed '/^======= /d' | + sed '/^Binary:$/d' + ) + + diff_values "$bin_output_two_stage" "$bin_output_via_ir" --ignore-space-change --ignore-blank-lines +} + ## RUN echo "Checking that the bug list is up to date..." @@ -533,6 +588,36 @@ printTask "Testing assemble, yul, strict-assembly and optimize..." test_solc_assembly_output "{ let x := 0 }" "{ { } }" "--strict-assembly --optimize" ) +printTask "Testing the eqivalence of --experimental-via-ir and a two-stage compilation..." +( + printTask " - Smoke test" + test_via_ir_equivalence "contract C {}" + + printTask " - Smoke test (optimized)" + test_via_ir_equivalence "contract C {}" --optimize + + externalContracts=( + deposit_contract.sol + FixedFeeRegistrar.sol + _stringutils/stringutils.sol + ) + requiresOptimizer=( + deposit_contract.sol + FixedFeeRegistrar.sol + ) + + for contractFile in "${externalContracts[@]}" + do + if ! [[ "${requiresOptimizer[*]}" =~ $contractFile ]] + then + printTask " - ${contractFile}" + test_via_ir_equivalence "$(cat "${REPO_ROOT}/test/libsolidity/semanticTests/externalContracts/${contractFile}")" + fi + + printTask " - ${contractFile} (optimized)" + test_via_ir_equivalence "$(cat "${REPO_ROOT}/test/libsolidity/semanticTests/externalContracts/${contractFile}")" --optimize + done +) printTask "Testing standard input..." SOLTMPDIR=$(mktemp -d) From e2e393495eb7cd9fe9410a914ac772aa246f13ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 15 Oct 2021 15:50:52 +0200 Subject: [PATCH 0008/1704] Install diffutils on macOS to get diff with color support --- .circleci/osx_install_dependencies.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index ed11f24913..7ef8635a87 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -57,6 +57,7 @@ then brew install cmake brew install wget brew install coreutils + brew install diffutils ./scripts/install_obsolete_jsoncpp_1_7_4.sh # z3 From d3b246316622a3beb3ca71396584b4389fa8f630 Mon Sep 17 00:00:00 2001 From: Alessandro Coglio Date: Wed, 29 Sep 2021 13:05:08 -0700 Subject: [PATCH 0009/1704] Improve description of literal evaluation. --- docs/yul.rst | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/yul.rst b/docs/yul.rst index 8f59f28115..ef44a575ba 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -714,13 +714,15 @@ We will use a destructuring notation for the AST nodes. L'[$parami] = vi and L'[$reti] = 0 for all i. Let G'', L'', mode = E(Gn, L', block) G'', Ln, L''[$ret1], ..., L''[$retm] - E(G, L, l: StringLiteral) = G, L, utf8EncodeLeftAligned(l), - where utf8EncodeLeftAligned performs a UTF-8 encoding of l - and aligns it left into 32 bytes + E(G, L, l: StringLiteral) = G, L, str(l), + where str is the string evaluation function, + which for the EVM dialect is defined in the section 'Literals' above E(G, L, n: HexNumber) = G, L, hex(n) - where hex is the hexadecimal decoding function + where hex is the hexadecimal evaluation function, + which turns a sequence of hexadecimal digits into their big endian value E(G, L, n: DecimalNumber) = G, L, dec(n), - where dec is the decimal decoding function + where dec is the decimal evaluation function, + which turns a sequence of decimal digits into their big endian value .. _opcodes: From ab5a06e2b93aa57e84c3bea11561cf429abb19e5 Mon Sep 17 00:00:00 2001 From: Marenz Date: Wed, 27 Oct 2021 13:22:02 +0200 Subject: [PATCH 0010/1704] Refactor ASTJSON tests to allow easier addition of variations. --- test/libsolidity/ASTJSONTest.cpp | 144 +++++++++++++------------------ test/libsolidity/ASTJSONTest.h | 40 +++++++-- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/test/libsolidity/ASTJSONTest.cpp b/test/libsolidity/ASTJSONTest.cpp index 8579e9ea4b..82c6e7e186 100644 --- a/test/libsolidity/ASTJSONTest.cpp +++ b/test/libsolidity/ASTJSONTest.cpp @@ -16,17 +16,20 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include -#include -#include -#include #include #include -#include +#include +#include + +#include +#include + #include #include -#include +#include #include +#include + #include #include #include @@ -72,8 +75,13 @@ ASTJSONTest::ASTJSONTest(string const& _filename) if (!boost::algorithm::ends_with(_filename, ".sol")) BOOST_THROW_EXCEPTION(runtime_error("Invalid test contract file name: \"" + _filename + "\".")); - m_astFilename = _filename.substr(0, _filename.size() - 4) + ".json"; - m_astParseOnlyFilename = _filename.substr(0, _filename.size() - 4) + "_parseOnly.json"; + string_view baseName = _filename; + baseName.remove_suffix(4); + + m_variants = { + TestVariant(baseName, CompilerStack::State::Parsed), + TestVariant(baseName, CompilerStack::State::AnalysisPerformed), + }; ifstream file(_filename); if (!file) @@ -102,26 +110,13 @@ ASTJSONTest::ASTJSONTest(string const& _filename) } m_sources.emplace_back(sourceName.empty() ? "a" : sourceName, source); - file.close(); - file.open(m_astFilename); - if (file) - { - string line; - while (getline(file, line)) - m_expectation += line + "\n"; - } - file.close(); - file.open(m_astParseOnlyFilename); - if (file) + for (TestVariant& variant: m_variants) { - string line; - while (getline(file, line)) - m_expectationParseOnly += line + "\n"; + variant.expectation = readFileAsString(variant.astFilename()); + boost::replace_all(variant.expectation, "\r\n", "\n"); } - - file.close(); } TestCase::TestResult ASTJSONTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) @@ -135,97 +130,76 @@ TestCase::TestResult ASTJSONTest::run(ostream& _stream, string const& _linePrefi sources[m_sources[i].first] = m_sources[i].second; sourceIndices[m_sources[i].first] = static_cast(i + 1); } - c.setSources(sources); - c.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); + bool resultsMatch = true; - if (!c.compile(CompilerStack::State::Parsed)) + for (TestVariant& variant: m_variants) { - SourceReferenceFormatter formatter(_stream, c, _formatted, false); - formatter.printErrorInformation(c.errors()); - return TestResult::FatalError; - } + c.reset(); + c.setSources(sources); + c.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); - bool resultsMatch = runTest( - m_expectationParseOnly, - m_resultParseOnly, - sourceIndices, - c, - "parseOnly", - _stream, - _linePrefix, - _formatted - ); + if (!c.parseAndAnalyze(variant.stopAfter)) + { + // Ignore non-fatal analysis errors, we only want to export. + if (c.state() > CompilerStack::State::Parsed) + continue; - c.reset(); - c.setSources(sources); - c.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); - if (!c.parse()) - { - // Empty Expectations means we expect failure - if (m_expectation.empty()) - return resultsMatch ? TestResult::Success : TestResult::Failure; + SourceReferenceFormatter formatter(_stream, c, _formatted, false); + formatter.printErrorInformation(c.errors()); + return TestResult::FatalError; + } - SourceReferenceFormatter{_stream, c, _formatted, false} - .printErrorInformation(c.errors()); - return TestResult::FatalError; + resultsMatch = resultsMatch && runTest( + variant, + sourceIndices, + c, + _stream, + _linePrefix, + _formatted + ); } - c.analyze(); - - resultsMatch = runTest( - m_expectation, - m_result, - sourceIndices, - c, - "", - _stream, - _linePrefix, - _formatted - ) && resultsMatch; - return resultsMatch ? TestResult::Success : TestResult::Failure; } bool ASTJSONTest::runTest( - string& _expectation, - string& _result, + TestVariant& _variant, map const& _sourceIndices, CompilerStack& _compiler, - string const& _variation, ostream& _stream, string const& _linePrefix, bool const _formatted ) { if (m_sources.size() > 1) - _result += "[\n"; + _variant.result += "[\n"; for (size_t i = 0; i < m_sources.size(); i++) { ostringstream result; ASTJsonConverter(_compiler.state(), _sourceIndices).print(result, _compiler.ast(m_sources[i].first)); - _result += result.str(); + _variant.result += result.str(); if (i != m_sources.size() - 1) - _result += ","; - _result += "\n"; + _variant.result += ","; + _variant.result += "\n"; } if (m_sources.size() > 1) - _result += "]\n"; + _variant.result += "]\n"; - replaceTagWithVersion(_expectation); + replaceTagWithVersion(_variant.expectation); - if (_expectation != _result) + if (_variant.expectation != _variant.result) { string nextIndentLevel = _linePrefix + " "; AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result" << - (!_variation.empty() ? " (" + _variation + "):" : ":") << + (!_variant.name().empty() ? " (" + _variant.name() + "):" : ":") << endl; { - istringstream stream(_expectation); + istringstream stream(_variant.expectation); string line; while (getline(stream, line)) _stream << nextIndentLevel << line << endl; @@ -235,10 +209,10 @@ bool ASTJSONTest::runTest( AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result" << - (!_variation.empty() ? " (" + _variation + "):" : ":") << + (!_variant.name().empty() ? " (" + _variant.name() + "):" : ":") << endl; { - istringstream stream(_result); + istringstream stream(_variant.result); string line; while (getline(stream, line)) _stream << nextIndentLevel << line << endl; @@ -266,14 +240,18 @@ void ASTJSONTest::printSource(ostream& _stream, string const& _linePrefix, bool void ASTJSONTest::printUpdatedExpectations(std::ostream&, std::string const&) const { - updateExpectation(m_astFilename, m_result, ""); - updateExpectation(m_astParseOnlyFilename, m_resultParseOnly, "parseOnly "); + for (TestVariant const& variant: m_variants) + updateExpectation( + variant.astFilename(), + variant.result, + variant.name().empty() ? "" : variant.name() + " " + ); } -void ASTJSONTest::updateExpectation(string const& _filename, string const& _expectation, string const& _variation) const +void ASTJSONTest::updateExpectation(string const& _filename, string const& _expectation, string const& _variant) const { ofstream file(_filename.c_str()); - if (!file) BOOST_THROW_EXCEPTION(runtime_error("Cannot write " + _variation + "AST expectation to \"" + _filename + "\".")); + if (!file) BOOST_THROW_EXCEPTION(runtime_error("Cannot write " + _variant + "AST expectation to \"" + _filename + "\".")); file.exceptions(ios::badbit); string replacedResult = _expectation; diff --git a/test/libsolidity/ASTJSONTest.h b/test/libsolidity/ASTJSONTest.h index ac57277ac3..3365de589d 100644 --- a/test/libsolidity/ASTJSONTest.h +++ b/test/libsolidity/ASTJSONTest.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include @@ -37,6 +38,32 @@ namespace solidity::frontend::test class ASTJSONTest: public TestCase { public: + struct TestVariant + { + TestVariant(std::string_view _baseName, CompilerStack::State _stopAfter): + baseName(_baseName), + stopAfter(_stopAfter) + {} + + std::string name() const + { + return stopAfter == CompilerStack::State::Parsed ? "parseOnly" : ""; + } + + std::string astFilename() const + { + return std::string(baseName) + + (name().empty() ? "" : "_") + + name() + + ".json"; + } + + std::string baseName; + CompilerStack::State stopAfter; + std::string result; + std::string expectation; + }; + static std::unique_ptr create(Config const& _config) { return std::make_unique(_config.filename); @@ -49,11 +76,9 @@ class ASTJSONTest: public TestCase void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; private: bool runTest( - std::string& _expectation, - std::string& _result, + TestVariant& _testVariant, std::map const& _sourceIndices, CompilerStack& _compiler, - std::string const& _variation, std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false @@ -61,15 +86,12 @@ class ASTJSONTest: public TestCase void updateExpectation( std::string const& _filename, std::string const& _expectation, - std::string const& _variation + std::string const& _variant ) const; + std::vector m_variants; + std::vector> m_sources; - std::string m_expectationParseOnly; - std::string m_astFilename; - std::string m_astParseOnlyFilename; - std::string m_result; - std::string m_resultParseOnly; }; } From 49b4e77d6ba14aafd701b6f149227b7d138824f3 Mon Sep 17 00:00:00 2001 From: Marenz Date: Tue, 26 Oct 2021 14:03:23 +0200 Subject: [PATCH 0011/1704] Prevent crash when translating yul->ewasm with @use-src annotations --- Changelog.md | 1 + libyul/backends/wasm/EVMToEwasmTranslator.cpp | 6 +++- .../yul_to_wasm_source_location_crash/args | 1 + .../yul_to_wasm_source_location_crash/err | 1 + .../input.yul | 4 +++ .../yul_to_wasm_source_location_crash/output | 34 +++++++++++++++++++ 6 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/cmdlineTests/yul_to_wasm_source_location_crash/args create mode 100644 test/cmdlineTests/yul_to_wasm_source_location_crash/err create mode 100644 test/cmdlineTests/yul_to_wasm_source_location_crash/input.yul create mode 100644 test/cmdlineTests/yul_to_wasm_source_location_crash/output diff --git a/Changelog.md b/Changelog.md index 79d5df058c..b3af54d047 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: + * Code Generator: Fix a crash when using ``@use-src`` and compiling from Yul to ewasm. ### 0.8.10 (2021-11-09) diff --git a/libyul/backends/wasm/EVMToEwasmTranslator.cpp b/libyul/backends/wasm/EVMToEwasmTranslator.cpp index eb7a60a32f..359cc023bb 100644 --- a/libyul/backends/wasm/EVMToEwasmTranslator.cpp +++ b/libyul/backends/wasm/EVMToEwasmTranslator.cpp @@ -137,7 +137,11 @@ void EVMToEwasmTranslator::parsePolyfill() string(solidity::yul::wasm::polyfill::Logical) + string(solidity::yul::wasm::polyfill::Memory) + "}", ""); - m_polyfill = Parser(errorReporter, WasmDialect::instance()).parse(charStream); + + // Passing an empty SourceLocation() here is a workaround to prevent a crash + // when compiling from yul->ewasm. We're stripping nativeLocation and + // originLocation from the AST (but we only really need to strip nativeLocation) + m_polyfill = Parser(errorReporter, WasmDialect::instance(), langutil::SourceLocation()).parse(charStream); if (!errors.empty()) { string message; diff --git a/test/cmdlineTests/yul_to_wasm_source_location_crash/args b/test/cmdlineTests/yul_to_wasm_source_location_crash/args new file mode 100644 index 0000000000..254a1883c1 --- /dev/null +++ b/test/cmdlineTests/yul_to_wasm_source_location_crash/args @@ -0,0 +1 @@ +--strict-assembly --yul-dialect evm --machine ewasm --optimize --ewasm-ir diff --git a/test/cmdlineTests/yul_to_wasm_source_location_crash/err b/test/cmdlineTests/yul_to_wasm_source_location_crash/err new file mode 100644 index 0000000000..014a1178fa --- /dev/null +++ b/test/cmdlineTests/yul_to_wasm_source_location_crash/err @@ -0,0 +1 @@ +Warning: Yul is still experimental. Please use the output with care. diff --git a/test/cmdlineTests/yul_to_wasm_source_location_crash/input.yul b/test/cmdlineTests/yul_to_wasm_source_location_crash/input.yul new file mode 100644 index 0000000000..89e060931b --- /dev/null +++ b/test/cmdlineTests/yul_to_wasm_source_location_crash/input.yul @@ -0,0 +1,4 @@ +/// @use-src 0:"test.sol" +object "C" { + code { sstore(0,0) } +} diff --git a/test/cmdlineTests/yul_to_wasm_source_location_crash/output b/test/cmdlineTests/yul_to_wasm_source_location_crash/output new file mode 100644 index 0000000000..29ff631aa5 --- /dev/null +++ b/test/cmdlineTests/yul_to_wasm_source_location_crash/output @@ -0,0 +1,34 @@ + +======= yul_to_wasm_source_location_crash/input.yul (Ewasm) ======= + +========================== + +Translated source: +/// @use-src 0:"test.sol" +object "C" { + code { + function main() + { + let hi := i64.shl(i64.extend_i32_u(bswap32(i32.wrap_i64(0))), 32) + let y := i64.or(hi, i64.extend_i32_u(bswap32(i32.wrap_i64(i64.shr_u(0, 32))))) + i64.store(0:i32, y) + i64.store(i32.add(0:i32, 8:i32), y) + i64.store(i32.add(0:i32, 16:i32), y) + i64.store(i32.add(0:i32, 24:i32), y) + i64.store(32:i32, y) + i64.store(i32.add(32:i32, 8:i32), y) + i64.store(i32.add(32:i32, 16:i32), y) + i64.store(i32.add(32:i32, 24:i32), y) + eth.storageStore(0:i32, 32:i32) + } + function bswap16(x:i32) -> y:i32 + { + y := i32.or(i32.and(i32.shl(x, 8:i32), 0xff00:i32), i32.and(i32.shr_u(x, 8:i32), 0xff:i32)) + } + function bswap32(x:i32) -> y:i32 + { + let hi:i32 := i32.shl(bswap16(x), 16:i32) + y := i32.or(hi, bswap16(i32.shr_u(x, 16:i32))) + } + } +} From cf528271079c3eb3c2d43d1cf72a67998af3dd37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 15 Nov 2021 14:29:22 +0100 Subject: [PATCH 0012/1704] Fix gas mismatch in constructor not being counted as a failure --- test/libsolidity/SemanticTest.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index c5ee04044d..963967ca48 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -407,7 +407,10 @@ TestCase::TestResult SemanticTest::runTest( if (m_transactionSuccessful == test.call().expectations.failure) success = false; if (success && !checkGasCostExpectation(test, _isYulRun)) + { + success = false; m_gasCostFailure = true; + } test.setFailure(!m_transactionSuccessful); test.setRawBytes(bytes()); From 077b3a003d65e498e2bc7f5d0f421aba75d451f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 15 Nov 2021 14:36:13 +0100 Subject: [PATCH 0013/1704] Fix `--enforce-gas-cost-min-value` being applied only when the cost expectations are not provided in the test file --- test/libsolidity/SemanticTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 963967ca48..ad6f40fbb6 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -565,14 +565,14 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp // We don't check gas if enforce gas cost is not active // or test is run with abi encoder v1 only // or gas used less than threshold for enforcing feature + // or the test has used up all available gas (test will fail anyway) // or setting is "ir" and it's not included in expectations // or if the called function is an isoltest builtin e.g. `smokeTest` or `storageEmpty` if ( !m_enforceGasCost || - ( - (setting == "ir" || m_gasUsed < m_enforceGasCostMinValue || m_gasUsed >= m_gas) && - io_test.call().expectations.gasUsed.count(setting) == 0 - ) || + m_gasUsed < m_enforceGasCostMinValue || + m_gasUsed >= m_gas || + (setting == "ir" && io_test.call().expectations.gasUsed.count(setting) == 0) || io_test.call().kind == FunctionCall::Kind::Builtin ) return true; From f42180ef06d1bc101829f569fc8d133a1ed42588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 15 Nov 2021 14:42:10 +0100 Subject: [PATCH 0014/1704] Rename gas constants in ExecutionFramework --- test/ExecutionFramework.cpp | 6 +++--- test/ExecutionFramework.h | 5 +++-- test/libsolidity/SemanticTest.cpp | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index c153cd4717..600bedbf5e 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -182,7 +182,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 message.kind = EVMC_CALL; message.destination = EVMHost::convertToEVMC(m_contractAddress); } - message.gas = m_gas.convert_to(); + message.gas = InitialGas.convert_to(); evmc::result result = m_evmcHost->call(message); @@ -190,7 +190,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 if (_isCreation) m_contractAddress = EVMHost::convertFromEVMC(result.create_address); - m_gasUsed = m_gas - result.gas_left; + m_gasUsed = InitialGas - result.gas_left; m_transactionSuccessful = (result.status_code == EVMC_SUCCESS); if (m_showMessages) @@ -216,7 +216,7 @@ void ExecutionFramework::sendEther(h160 const& _addr, u256 const& _amount) message.value = EVMHost::convertToEVMC(_amount); message.kind = EVMC_CALL; message.destination = EVMHost::convertToEVMC(_addr); - message.gas = m_gas.convert_to(); + message.gas = InitialGas.convert_to(); m_evmcHost->call(message); } diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 0ee0214d4c..53a09eaf8e 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -273,6 +273,9 @@ class ExecutionFramework } protected: + u256 const GasPrice = 10 * gwei; + u256 const InitialGas = 100000000; + void selectVM(evmc_capabilities _cap = evmc_capabilities::EVMC_CAPABILITY_EVM1); void reset(); @@ -302,8 +305,6 @@ class ExecutionFramework bool m_transactionSuccessful = true; util::h160 m_sender = account(0); util::h160 m_contractAddress; - u256 const m_gasPrice = 10 * gwei; - u256 const m_gas = 100000000; bytes m_output; u256 m_gasUsed; }; diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index ad6f40fbb6..4fbb16614c 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -571,7 +571,7 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp if ( !m_enforceGasCost || m_gasUsed < m_enforceGasCostMinValue || - m_gasUsed >= m_gas || + m_gasUsed >= InitialGas || (setting == "ir" && io_test.call().expectations.gasUsed.count(setting) == 0) || io_test.call().kind == FunctionCall::Kind::Builtin ) From 032f2d8f9fc71c6ef4dbe37914c21fe42fb99e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 15 Nov 2021 16:19:33 +0100 Subject: [PATCH 0015/1704] Update gas expectations --- .../semanticTests/array/constant_var_as_array_length.sol | 3 +++ .../semanticTests/array/fixed_arrays_in_constructors.sol | 3 +++ .../constructor/bytes_in_constructors_unpacker.sol | 3 +++ .../constructor/constructor_arguments_external.sol | 3 +++ .../constructor/constructor_static_array_argument.sol | 3 +++ .../semanticTests/constructor_ihneritance_init_order_2.sol | 3 +++ .../semanticTests/constructor_inheritance_init_order.sol | 1 + test/libsolidity/semanticTests/constructor_with_params.sol | 2 ++ .../constructor_with_params_diamond_inheritance.sol | 3 +++ .../semanticTests/constructor_with_params_inheritance.sol | 3 +++ .../semanticTests/events/event_emit_from_other_contract.sol | 4 +++- .../semanticTests/events/event_signature_in_library.sol | 2 +- .../semanticTests/externalContracts/FixedFeeRegistrar.sol | 2 +- .../semanticTests/externalContracts/deposit_contract.sol | 6 +++--- .../semanticTests/externalContracts/prbmath_signed.sol | 4 ++-- .../semanticTests/externalContracts/prbmath_unsigned.sol | 2 +- .../semanticTests/externalContracts/ramanujan_pi.sol | 2 +- .../libsolidity/semanticTests/externalContracts/strings.sol | 2 +- .../functionCall/creation_function_call_with_args.sol | 3 +++ .../functionCall/creation_function_call_with_salt.sol | 3 +++ .../functionCall/external_call_to_nonexisting.sol | 3 ++- .../external_call_to_nonexisting_debugstrings.sol | 2 ++ .../semanticTests/functionCall/gas_and_value_basic.sol | 3 +++ .../functionCall/gas_and_value_brace_syntax.sol | 3 +++ .../semanticTests/functionCall/send_zero_ether.sol | 3 +++ test/libsolidity/semanticTests/immutable/use_scratch.sol | 3 +++ .../semanticTests/inheritance/value_for_constructor.sol | 3 +++ .../isoltestTesting/balance_other_contract.sol | 6 +++--- test/libsolidity/semanticTests/smoke/constructor.sol | 4 +++- test/libsolidity/semanticTests/state/blockhash_basic.sol | 3 +++ .../semanticTests/userDefinedValueType/erc20.sol | 2 +- test/libsolidity/semanticTests/various/address_code.sol | 5 ++++- test/libsolidity/semanticTests/various/code_length.sol | 3 ++- .../semanticTests/various/codebalance_assembly.sol | 1 + .../semanticTests/various/contract_binary_dependencies.sol | 1 + .../semanticTests/various/negative_stack_height.sol | 2 ++ test/libsolidity/semanticTests/various/senders_balance.sol | 3 +++ test/libsolidity/semanticTests/various/value_complex.sol | 3 +++ test/libsolidity/semanticTests/various/value_insane.sol | 3 +++ 39 files changed, 94 insertions(+), 19 deletions(-) diff --git a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol index c696002ad3..945de3cfea 100644 --- a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol +++ b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol @@ -11,6 +11,9 @@ contract C { // compileViaYul: also // ---- // constructor(): 1, 2, 3 -> +// gas irOptimized: 143598 +// gas legacy: 183490 +// gas legacyOptimized: 151938 // a(uint256): 0 -> 1 // a(uint256): 1 -> 2 // a(uint256): 2 -> 3 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol index c6e46a7fad..ddead0503b 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol @@ -11,5 +11,8 @@ contract Creator { // compileViaYul: also // ---- // constructor(): 1, 2, 3, 4 -> +// gas irOptimized: 132278 +// gas legacy: 176789 +// gas legacyOptimized: 129585 // r() -> 4 // ch() -> 3 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index e81755ff94..1a93f53b3f 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -10,5 +10,8 @@ contract Test { // compileViaYul: also // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> +// gas irOptimized: 291443 +// gas legacy: 309842 +// gas legacyOptimized: 260801 // m_x() -> 7 // m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol index bb271ec174..6ee258bd6b 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol @@ -19,5 +19,8 @@ contract Main { // compileViaYul: also // ---- // constructor(): "abc", true +// gas irOptimized: 112563 +// gas legacy: 145838 +// gas legacyOptimized: 104017 // getFlag() -> true // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index 099202c956..ab90a0bb91 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -12,6 +12,9 @@ contract C { // compileViaYul: also // ---- // constructor(): 1, 2, 3, 4 -> +// gas irOptimized: 180731 +// gas legacy: 221377 +// gas legacyOptimized: 177671 // a() -> 1 // b(uint256): 0 -> 2 // b(uint256): 1 -> 3 diff --git a/test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol b/test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol index 44a7fb2f3b..db58499ea4 100644 --- a/test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol +++ b/test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol @@ -12,4 +12,7 @@ contract B is A { // compileViaYul: also // ---- // constructor() -> +// gas irOptimized: 122233 +// gas legacy: 135046 +// gas legacyOptimized: 116176 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol index 757a5481f7..41a050fc40 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol @@ -15,4 +15,5 @@ contract B is A { // compileViaYul: true // ---- // constructor() -> +// gas irOptimized: 122233 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_with_params.sol b/test/libsolidity/semanticTests/constructor_with_params.sol index e3ac5b386c..cb61927745 100644 --- a/test/libsolidity/semanticTests/constructor_with_params.sol +++ b/test/libsolidity/semanticTests/constructor_with_params.sol @@ -11,5 +11,7 @@ contract C { // compileViaYul: also // ---- // constructor(): 2, 0 -> +// gas irOptimized: 104227 +// gas legacy: 117158 // i() -> 2 // k() -> 0 diff --git a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol index 89cb202c60..fe3c95b544 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol @@ -23,6 +23,9 @@ contract D is B, C { // compileViaYul: also // ---- // constructor(): 2, 0 -> +// gas irOptimized: 159542 +// gas legacy: 170665 +// gas legacyOptimized: 145396 // i() -> 2 // j() -> 2 // k() -> 1 diff --git a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol index d477bbc0d9..3d90783f82 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol @@ -14,5 +14,8 @@ contract D is C { // compileViaYul: also // ---- // constructor(): 2, 0 -> +// gas irOptimized: 124844 +// gas legacy: 139250 +// gas legacyOptimized: 119367 // i() -> 2 // k() -> 1 diff --git a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol index 128cf00ea3..690f555dc6 100644 --- a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol +++ b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol @@ -17,6 +17,8 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas legacy: 249112 +// gas irOptimized: 177344 +// gas legacy: 250376 +// gas legacyOptimized: 174522 // deposit(bytes32), 18 wei: 0x1234 -> // ~ emit Deposit(address,bytes32,uint256) from 0xf01f7809444bd9a93a854361c6fae3f23d9e23db: #0x0fdd67305928fcac8d213d1e47bfa6165cd0b87b, #0x1234, 0x00 diff --git a/test/libsolidity/semanticTests/events/event_signature_in_library.sol b/test/libsolidity/semanticTests/events/event_signature_in_library.sol index e43fc4c645..b301ebfd5a 100644 --- a/test/libsolidity/semanticTests/events/event_signature_in_library.sol +++ b/test/libsolidity/semanticTests/events/event_signature_in_library.sol @@ -20,4 +20,4 @@ contract C { // ---- // constructor() // ~ emit E((uint8,int16),(uint8,int16)): #0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5, 0x00, 0x00 -// gas legacy: 150662 +// gas legacy: 150602 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index 9205de434d..fc0b416fde 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -76,7 +76,7 @@ contract FixedFeeRegistrar is Registrar { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 425623 +// gas irOptimized: 426283 // gas legacy: 936897 // gas legacyOptimized: 490983 // reserve(string), 69 ether: 0x20, 3, "abc" -> diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index f054497e98..ed9a07f7ff 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -178,9 +178,9 @@ contract DepositContract is IDepositContract, ERC165 { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 1558013 -// gas legacy: 2580394 -// gas legacyOptimized: 1775403 +// gas irOptimized: 1558001 +// gas legacy: 2436584 +// gas legacyOptimized: 1776483 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index 01d2403a6d..9de7a30d81 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -50,8 +50,8 @@ contract test { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 1924584 -// gas legacy: 2602700 +// gas irOptimized: 1924392 +// gas legacy: 2480887 // gas legacyOptimized: 1874490 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22137 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index c31664c859..11001fffad 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -51,7 +51,7 @@ contract test { // ---- // constructor() // gas irOptimized: 1778342 -// gas legacy: 2356230 +// gas legacy: 2250130 // gas legacyOptimized: 1746528 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22004 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 1fc85adff7..763a8acdaf 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -36,7 +36,7 @@ contract test { // ---- // constructor() // gas irOptimized: 465357 -// gas legacy: 733634 +// gas legacy: 672749 // gas legacyOptimized: 479606 // prb_pi() -> 3141592656369545286 // gas irOptimized: 57478 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 238ed21840..7c4028bb9f 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -52,7 +52,7 @@ contract test { // ---- // constructor() // gas irOptimized: 702619 -// gas legacy: 1188228 +// gas legacy: 1130761 // gas legacyOptimized: 750416 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22660 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol index 56e458110d..2da7c2dd6d 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -17,4 +17,7 @@ contract D { // compileViaYul: also // ---- // constructor(): 2 -> +// gas irOptimized: 200295 +// gas legacy: 245842 +// gas legacyOptimized: 195676 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol index 725a54b547..0b0633c6d1 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -18,4 +18,7 @@ contract D { // compileViaYul: also // ---- // constructor(): 2 -> +// gas irOptimized: 200458 +// gas legacy: 246202 +// gas legacyOptimized: 195914 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index 9546f10986..942faa048b 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -25,8 +25,9 @@ contract C { // compileViaYul: also // ---- // constructor(), 1 ether -> +// gas irOptimized: 308423 // gas legacy: 465314 -// gas legacyOptimized: 510004 +// gas legacyOptimized: 304481 // f(uint256): 0 -> FAILURE // f(uint256): 1 -> FAILURE // f(uint256): 2 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol index f426e628eb..26faf248ff 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -27,6 +27,8 @@ contract C { // revertStrings: debug // ---- // constructor(), 1 ether -> +// gas irOptimized: 448383 +// gas legacy: 834272 // gas legacyOptimized: 510004 // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 1 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index 5ca46b4e19..b1d9299d88 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -41,6 +41,9 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> +// gas irOptimized: 285350 +// gas legacy: 402654 +// gas legacyOptimized: 274470 // sendAmount(uint256): 5 -> 5 // outOfGas() -> FAILURE # call to helper should not succeed but amount should be transferred anyway # // checkState() -> false, 15 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol index 3da540807c..9e2491ac1b 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -40,6 +40,9 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> +// gas irOptimized: 285350 +// gas legacy: 402654 +// gas legacyOptimized: 274470 // sendAmount(uint256): 5 -> 5 // outOfGas() -> FAILURE # call to helper should not succeed but amount should be transferred anyway # // checkState() -> false, 15 diff --git a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol index 5f821ff3dd..617a6dec28 100644 --- a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol +++ b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol @@ -19,4 +19,7 @@ contract Main { // compileViaYul: also // ---- // constructor(), 20 wei -> +// gas irOptimized: 102862 +// gas legacy: 116691 +// gas legacyOptimized: 100361 // s() -> true diff --git a/test/libsolidity/semanticTests/immutable/use_scratch.sol b/test/libsolidity/semanticTests/immutable/use_scratch.sol index 71381fc9b4..4fb3bf2455 100644 --- a/test/libsolidity/semanticTests/immutable/use_scratch.sol +++ b/test/libsolidity/semanticTests/immutable/use_scratch.sol @@ -17,5 +17,8 @@ contract C { // compileViaYul: also // ---- // constructor(): 3 -> +// gas irOptimized: 137184 +// gas legacy: 209361 +// gas legacyOptimized: 139324 // f() -> 84, 23 // m(uint256): 3 -> 7 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index 057b3b8e45..b2f0f8a6b1 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -42,6 +42,9 @@ contract Main { // compileViaYul: also // ---- // constructor(), 22 wei -> +// gas irOptimized: 288778 +// gas legacy: 402045 +// gas legacyOptimized: 266772 // getFlag() -> true // getName() -> "abc" // getBalances() -> 12, 10 diff --git a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol index 59ad2cd84b..5af1e5cdc6 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -18,9 +18,9 @@ contract ClientReceipt { // compileViaYul: also // ---- // constructor(), 2000 wei -> -// gas irOptimized: 191881 -// gas legacy: 235167 -// gas legacyOptimized: 180756 +// gas irOptimized: 184076 +// gas legacy: 235195 +// gas legacyOptimized: 176766 // balance -> 1500 // gas irOptimized: 191881 // gas legacy: 235167 diff --git a/test/libsolidity/semanticTests/smoke/constructor.sol b/test/libsolidity/semanticTests/smoke/constructor.sol index 3837fe071f..7667c2443f 100644 --- a/test/libsolidity/semanticTests/smoke/constructor.sol +++ b/test/libsolidity/semanticTests/smoke/constructor.sol @@ -14,7 +14,9 @@ contract C { // compileViaYul: also // ---- // constructor(), 2 wei: 3 -> -// gas legacy: 148000 +// gas irOptimized: 111723 +// gas legacy: 151416 +// gas legacyOptimized: 108388 // state() -> 3 // balance() -> 2 // balance -> 2 diff --git a/test/libsolidity/semanticTests/state/blockhash_basic.sol b/test/libsolidity/semanticTests/state/blockhash_basic.sol index 528c8aea64..d4dbffcb8f 100644 --- a/test/libsolidity/semanticTests/state/blockhash_basic.sol +++ b/test/libsolidity/semanticTests/state/blockhash_basic.sol @@ -14,6 +14,9 @@ contract C { // compileViaYul: also // ---- // constructor() +// gas irOptimized: 119839 +// gas legacy: 155081 +// gas legacyOptimized: 107997 // genesisHash() -> 0x3737373737373737373737373737373737373737373737373737373737373737 // currentHash() -> 0 // f(uint256): 0 -> 0x3737373737373737373737373737373737373737373737373737373737373737 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index 4db14ff739..efe2ee1148 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -116,7 +116,7 @@ contract ERC20 { // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 // gas irOptimized: 442239 -// gas legacy: 861547 +// gas legacy: 861559 // gas legacyOptimized: 420959 // totalSupply() -> 20 // gas irOptimized: 23415 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 8e840fd016..6072d5ac3e 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -13,10 +13,13 @@ contract C { function h() public view returns (uint) { return address(1).code.length; } } // ==== -// compileViaYul: also // compileToEwasm: also +// compileViaYul: also // ---- // constructor() -> +// gas irOptimized: 199687 +// gas legacy: 241124 +// gas legacyOptimized: 155549 // initCode() -> 0x20, 0 // f() -> true // g() -> 0 diff --git a/test/libsolidity/semanticTests/various/code_length.sol b/test/libsolidity/semanticTests/various/code_length.sol index 53b3534b25..ad4b6f874c 100644 --- a/test/libsolidity/semanticTests/various/code_length.sol +++ b/test/libsolidity/semanticTests/various/code_length.sol @@ -58,8 +58,9 @@ contract C { } } // ==== -// compileViaYul: also // compileToEwasm: also +// compileViaYul: also // ---- // constructor() +// gas legacy: 126455 // f(): true, true -> true, true diff --git a/test/libsolidity/semanticTests/various/codebalance_assembly.sol b/test/libsolidity/semanticTests/various/codebalance_assembly.sol index 2df9c5b4f2..98f4e29693 100644 --- a/test/libsolidity/semanticTests/various/codebalance_assembly.sol +++ b/test/libsolidity/semanticTests/various/codebalance_assembly.sol @@ -23,6 +23,7 @@ contract C { // compileViaYul: also // ---- // constructor(), 23 wei -> +// gas legacy: 100517 // f() -> 0 // g() -> 1 // h() -> 23 diff --git a/test/libsolidity/semanticTests/various/contract_binary_dependencies.sol b/test/libsolidity/semanticTests/various/contract_binary_dependencies.sol index 5303cdd52c..57942979ae 100644 --- a/test/libsolidity/semanticTests/various/contract_binary_dependencies.sol +++ b/test/libsolidity/semanticTests/various/contract_binary_dependencies.sol @@ -21,3 +21,4 @@ contract C { // compileViaYul: also // ---- // constructor() -> +// gas irOptimized: 104337 diff --git a/test/libsolidity/semanticTests/various/negative_stack_height.sol b/test/libsolidity/semanticTests/various/negative_stack_height.sol index ba1bebc18d..52fce16f51 100644 --- a/test/libsolidity/semanticTests/various/negative_stack_height.sol +++ b/test/libsolidity/semanticTests/various/negative_stack_height.sol @@ -65,3 +65,5 @@ contract C { // compileViaYul: false // ---- // constructor() -> +// gas legacy: 588138 +// gas legacyOptimized: 349636 diff --git a/test/libsolidity/semanticTests/various/senders_balance.sol b/test/libsolidity/semanticTests/various/senders_balance.sol index 08b83401c0..600e72e3e3 100644 --- a/test/libsolidity/semanticTests/various/senders_balance.sol +++ b/test/libsolidity/semanticTests/various/senders_balance.sol @@ -19,4 +19,7 @@ contract D { // compileViaYul: also // ---- // constructor(), 27 wei -> +// gas irOptimized: 175261 +// gas legacy: 222977 +// gas legacyOptimized: 169779 // f() -> 27 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol index 8d091ec982..bebf7557f0 100644 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ b/test/libsolidity/semanticTests/various/value_complex.sol @@ -22,4 +22,7 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> +// gas irOptimized: 185891 +// gas legacy: 265006 +// gas legacyOptimized: 182842 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/various/value_insane.sol b/test/libsolidity/semanticTests/various/value_insane.sol index c81570626c..9edd8061a1 100644 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ b/test/libsolidity/semanticTests/various/value_insane.sol @@ -21,4 +21,7 @@ contract test { // compileViaYul: also // ---- // constructor(), 20 wei -> +// gas irOptimized: 187835 +// gas legacy: 266728 +// gas legacyOptimized: 184762 // sendAmount(uint256): 5 -> 8 From 27dc77be5ddc8cb18009b9611b831bf75e5f4536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 15 Nov 2021 16:32:38 +0100 Subject: [PATCH 0016/1704] Fix typo in test name: ihneritance -> inheritance --- ..._init_order_2.sol => constructor_inheritance_init_order_2.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/semanticTests/{constructor_ihneritance_init_order_2.sol => constructor_inheritance_init_order_2.sol} (100%) diff --git a/test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol rename to test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol From 90fdea95e7a0cf5a8c29e054afb02018cf7a257d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 15 Nov 2021 19:58:59 +0100 Subject: [PATCH 0017/1704] TestFunctionCall::formatRawParameters(): Ensure that uint8_t overload of toHex() is called - Wrong overload results in isoltest padding each char to 32 bytes --- .../format_raw_string_with_control_chars.sol | 12 ++++++++++++ test/libsolidity/util/BytesUtils.cpp | 2 +- test/libsolidity/util/TestFunctionCall.cpp | 4 +++- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test/libsolidity/semanticTests/isoltestTesting/format_raw_string_with_control_chars.sol diff --git a/test/libsolidity/semanticTests/isoltestTesting/format_raw_string_with_control_chars.sol b/test/libsolidity/semanticTests/isoltestTesting/format_raw_string_with_control_chars.sol new file mode 100644 index 0000000000..205a4ae3dd --- /dev/null +++ b/test/libsolidity/semanticTests/isoltestTesting/format_raw_string_with_control_chars.sol @@ -0,0 +1,12 @@ +contract C { + function f(string memory s) external pure returns (string memory) { + return s; + } +} +// NOTE: The test is here to illustrate the problem with formatting control chars in strings in +// test expectations but unfortunately it can only be triggered manually. It does not test anything +// unless you introduce a difference in expectations to force isoltest to reformat them. +// ==== +// compileViaYul: also +// ---- +// f(string): 0x20, 16, "\xf0\x9f\x98\x83\xf0\x9f\x98\x83\xf0\x9f\x98\x83\xf0\x9f\x98\x83" -> 0x20, 16, "\xf0\x9f\x98\x83\xf0\x9f\x98\x83\xf0\x9f\x98\x83\xf0\x9f\x98\x83" # Input/Output: "😃😃😃😃" # diff --git a/test/libsolidity/util/BytesUtils.cpp b/test/libsolidity/util/BytesUtils.cpp index 6745bd1dfc..f74b256d0c 100644 --- a/test/libsolidity/util/BytesUtils.cpp +++ b/test/libsolidity/util/BytesUtils.cpp @@ -219,7 +219,7 @@ string BytesUtils::formatString(bytes const& _bytes, size_t _cutOff) if (isprint(v)) os << v; else - os << "\\x" << toHex(v); + os << "\\x" << toHex(v, HexCase::Lower); } } os << "\""; diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index 0f28f3b99b..43805c8f99 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -322,7 +322,9 @@ string TestFunctionCall::formatRawParameters( if (param.format.newline) os << endl << _linePrefix << "// "; for (auto const c: param.rawString) - os << (c >= ' ' ? string(1, c) : "\\x" + toHex(static_cast(c))); + // NOTE: Even though we have a toHex() overload specifically for uint8_t, the compiler + // chooses the one for bytes if the second argument is omitted. + os << (c >= ' ' ? string(1, c) : "\\x" + toHex(static_cast(c), HexCase::Lower)); if (¶m != &_params.back()) os << ", "; } From b36a3c6bf58cd4061e14bc03819d21536372b0ea Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 20 Nov 2021 22:41:19 +0000 Subject: [PATCH 0018/1704] Fix documentation for valid ASCII string literals --- docs/types/value-types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index f849f3f7eb..4cb0dec4fa 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -507,7 +507,7 @@ String literals are written with either double or single-quotes (``"foo"`` or `` For example, with ``bytes32 samevar = "stringliteral"`` the string literal is interpreted in its raw byte form when assigned to a ``bytes32`` type. -String literals can only contain printable ASCII characters, which means the characters between and including 0x1F .. 0x7E. +String literals can only contain printable ASCII characters, which means the characters between and including 0x20 .. 0x7E. Additionally, string literals also support the following escape characters: From ef3c562160b4e86da8ce5644e1d1ceb51e2b5a93 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 22 Nov 2021 15:18:43 -0600 Subject: [PATCH 0019/1704] Fix typo --- docs/introduction-to-smart-contracts.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index d19a0decf8..c448d7671d 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -584,5 +584,5 @@ but instead is implemented in the EVM execution environment itself. Different EVM-compatible chains might use a different set of precompiled contracts. It might also be possible that new precompiled contracts are added to the Ethereum main chain in the future, -but you can reasonabyly expect them to always be in the range between -``1`` and ``0xffff`` (inclusive). \ No newline at end of file +but you can reasonably expect them to always be in the range between +``1`` and ``0xffff`` (inclusive). From bd321b9f1f3b4e5527dc4958cc2b1c82c84e1c3f Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 23 Nov 2021 10:37:12 +0100 Subject: [PATCH 0020/1704] Rename RedundantAssignEliminator to UnusedAssignEliminator. --- libyul/CMakeLists.txt | 8 ++--- libyul/optimiser/SSATransform.h | 2 +- libyul/optimiser/Suite.cpp | 6 ++-- ...minator.cpp => UnusedAssignEliminator.cpp} | 36 +++++++++---------- ...nEliminator.h => UnusedAssignEliminator.h} | 10 +++--- ...ndantStoreBase.cpp => UnusedStoreBase.cpp} | 20 +++++------ ...RedundantStoreBase.h => UnusedStoreBase.h} | 8 ++--- test/libyul/YulOptimizerTestCommon.cpp | 10 +++--- .../for.yul | 0 .../for_branch.yul | 0 .../for_break.yul | 0 .../for_continue.yul | 0 .../for_continue_2.yul | 0 .../for_continue_3.yul | 0 .../for_decl_inside_break_continue.yul | 0 .../for_deep_noremove.yul | 0 .../for_deep_simple.yul | 0 .../for_multi_break.yul | 0 .../for_nested.yul | 0 .../for_rerun.yul | 0 .../for_stmnts_after_break_continue.yul | 0 .../function.yul | 0 .../if.yul | 0 .../if_overwrite_all_branches.yul | 0 .../if_used_in_one_branch.yul | 0 .../leave.yul | 0 .../multi_assign.yul | 0 .../multivar.yul | 0 .../non_movable.yul | 0 .../remove_break.yul | 0 .../remove_continue.yul | 0 .../scopes.yul | 0 .../simple.yul | 0 .../switch_overwrite_in_all.yul | 0 .../switch_overwrite_in_one.yul | 0 .../switch_overwrite_use_combination.yul | 0 .../switch_unused.yul | 0 test/yulPhaser/Chromosome.cpp | 4 +-- 38 files changed, 52 insertions(+), 52 deletions(-) rename libyul/optimiser/{RedundantAssignEliminator.cpp => UnusedAssignEliminator.cpp} (74%) rename libyul/optimiser/{RedundantAssignEliminator.h => UnusedAssignEliminator.h} (94%) rename libyul/optimiser/{RedundantStoreBase.cpp => UnusedStoreBase.cpp} (86%) rename libyul/optimiser/{RedundantStoreBase.h => UnusedStoreBase.h} (92%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_branch.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_break.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_continue.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_continue_2.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_continue_3.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_decl_inside_break_continue.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_deep_noremove.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_deep_simple.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_multi_break.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_nested.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_rerun.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/for_stmnts_after_break_continue.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/function.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/if.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/if_overwrite_all_branches.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/if_used_in_one_branch.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/leave.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/multi_assign.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/multivar.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/non_movable.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/remove_break.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/remove_continue.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/scopes.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/simple.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/switch_overwrite_in_all.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/switch_overwrite_in_one.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/switch_overwrite_use_combination.yul (100%) rename test/libyul/yulOptimizerTests/{redundantAssignEliminator => unusedAssignEliminator}/switch_unused.yul (100%) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 039e24ea91..16b68535a9 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -173,10 +173,10 @@ add_library(yul optimiser/OptimizerUtilities.h optimiser/ReasoningBasedSimplifier.cpp optimiser/ReasoningBasedSimplifier.h - optimiser/RedundantAssignEliminator.cpp - optimiser/RedundantAssignEliminator.h - optimiser/RedundantStoreBase.cpp - optimiser/RedundantStoreBase.h + optimiser/UnusedAssignEliminator.cpp + optimiser/UnusedAssignEliminator.h + optimiser/UnusedStoreBase.cpp + optimiser/UnusedStoreBase.h optimiser/Rematerialiser.cpp optimiser/Rematerialiser.h optimiser/SMTSolver.cpp diff --git a/libyul/optimiser/SSATransform.h b/libyul/optimiser/SSATransform.h index 66015362a1..64181bf208 100644 --- a/libyul/optimiser/SSATransform.h +++ b/libyul/optimiser/SSATransform.h @@ -70,7 +70,7 @@ class NameDispenser; * variable references can use the SSA variable. The only exception to this rule are * for loop conditions, as we cannot insert a variable declaration there. * - * After this stage, redundantAssignmentRemover is recommended to remove the unnecessary + * After this stage, UnusedAssignmentEliminator is recommended to remove the unnecessary * intermediate assignments. * * This stage provides best results if CSE is run right before it, because diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 766cc93b90..4012fa9700 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -55,7 +55,7 @@ #include #include #include -#include +#include #include #include #include @@ -219,7 +219,7 @@ map> const& OptimiserSuite::allSteps() LiteralRematerialiser, LoadResolver, LoopInvariantCodeMotion, - RedundantAssignEliminator, + UnusedAssignEliminator, ReasoningBasedSimplifier, Rematerialiser, SSAReverser, @@ -260,7 +260,7 @@ map const& OptimiserSuite::stepNameToAbbreviationMap() {LoadResolver::name, 'L'}, {LoopInvariantCodeMotion::name, 'M'}, {ReasoningBasedSimplifier::name, 'R'}, - {RedundantAssignEliminator::name, 'r'}, + {UnusedAssignEliminator::name, 'r'}, {Rematerialiser::name, 'm'}, {SSAReverser::name, 'V'}, {SSATransform::name, 'a'}, diff --git a/libyul/optimiser/RedundantAssignEliminator.cpp b/libyul/optimiser/UnusedAssignEliminator.cpp similarity index 74% rename from libyul/optimiser/RedundantAssignEliminator.cpp rename to libyul/optimiser/UnusedAssignEliminator.cpp index b6ac69c8f0..74dd599a11 100644 --- a/libyul/optimiser/RedundantAssignEliminator.cpp +++ b/libyul/optimiser/UnusedAssignEliminator.cpp @@ -20,7 +20,7 @@ * until they go out of scope or are re-assigned. */ -#include +#include #include #include @@ -33,36 +33,36 @@ using namespace std; using namespace solidity; using namespace solidity::yul; -void RedundantAssignEliminator::run(OptimiserStepContext& _context, Block& _ast) +void UnusedAssignEliminator::run(OptimiserStepContext& _context, Block& _ast) { - RedundantAssignEliminator rae{_context.dialect}; + UnusedAssignEliminator rae{_context.dialect}; rae(_ast); StatementRemover remover{rae.m_pendingRemovals}; remover(_ast); } -void RedundantAssignEliminator::operator()(Identifier const& _identifier) +void UnusedAssignEliminator::operator()(Identifier const& _identifier) { changeUndecidedTo(_identifier.name, State::Used); } -void RedundantAssignEliminator::operator()(VariableDeclaration const& _variableDeclaration) +void UnusedAssignEliminator::operator()(VariableDeclaration const& _variableDeclaration) { - RedundantStoreBase::operator()(_variableDeclaration); + UnusedStoreBase::operator()(_variableDeclaration); for (auto const& var: _variableDeclaration.variables) m_declaredVariables.emplace(var.name); } -void RedundantAssignEliminator::operator()(Assignment const& _assignment) +void UnusedAssignEliminator::operator()(Assignment const& _assignment) { visit(*_assignment.value); for (auto const& var: _assignment.variableNames) changeUndecidedTo(var.name, State::Unused); } -void RedundantAssignEliminator::operator()(FunctionDefinition const& _functionDefinition) +void UnusedAssignEliminator::operator()(FunctionDefinition const& _functionDefinition) { ScopedSaveAndRestore outerDeclaredVariables(m_declaredVariables, {}); ScopedSaveAndRestore outerReturnVariables(m_returnVariables, {}); @@ -70,28 +70,28 @@ void RedundantAssignEliminator::operator()(FunctionDefinition const& _functionDe for (auto const& retParam: _functionDefinition.returnVariables) m_returnVariables.insert(retParam.name); - RedundantStoreBase::operator()(_functionDefinition); + UnusedStoreBase::operator()(_functionDefinition); } -void RedundantAssignEliminator::operator()(Leave const&) +void UnusedAssignEliminator::operator()(Leave const&) { for (YulString name: m_returnVariables) changeUndecidedTo(name, State::Used); } -void RedundantAssignEliminator::operator()(Block const& _block) +void UnusedAssignEliminator::operator()(Block const& _block) { ScopedSaveAndRestore outerDeclaredVariables(m_declaredVariables, {}); - RedundantStoreBase::operator()(_block); + UnusedStoreBase::operator()(_block); for (auto const& var: m_declaredVariables) finalize(var, State::Unused); } -void RedundantAssignEliminator::visit(Statement const& _statement) +void UnusedAssignEliminator::visit(Statement const& _statement) { - RedundantStoreBase::visit(_statement); + UnusedStoreBase::visit(_statement); if (auto const* assignment = get_if(&_statement)) if (assignment->variableNames.size() == 1) @@ -99,7 +99,7 @@ void RedundantAssignEliminator::visit(Statement const& _statement) m_stores[assignment->variableNames.front().name][&_statement]; } -void RedundantAssignEliminator::shortcutNestedLoop(TrackedStores const& _zeroRuns) +void UnusedAssignEliminator::shortcutNestedLoop(TrackedStores const& _zeroRuns) { // Shortcut to avoid horrible runtime: // Change all assignments that were newly introduced in the for loop to "used". @@ -116,7 +116,7 @@ void RedundantAssignEliminator::shortcutNestedLoop(TrackedStores const& _zeroRun } } -void RedundantAssignEliminator::finalizeFunctionDefinition(FunctionDefinition const& _functionDefinition) +void UnusedAssignEliminator::finalizeFunctionDefinition(FunctionDefinition const& _functionDefinition) { for (auto const& param: _functionDefinition.parameters) finalize(param.name, State::Unused); @@ -124,14 +124,14 @@ void RedundantAssignEliminator::finalizeFunctionDefinition(FunctionDefinition co finalize(retParam.name, State::Used); } -void RedundantAssignEliminator::changeUndecidedTo(YulString _variable, RedundantAssignEliminator::State _newState) +void UnusedAssignEliminator::changeUndecidedTo(YulString _variable, UnusedAssignEliminator::State _newState) { for (auto& assignment: m_stores[_variable]) if (assignment.second == State::Undecided) assignment.second = _newState; } -void RedundantAssignEliminator::finalize(YulString _variable, RedundantAssignEliminator::State _finalState) +void UnusedAssignEliminator::finalize(YulString _variable, UnusedAssignEliminator::State _finalState) { std::map stores = std::move(m_stores[_variable]); m_stores.erase(_variable); diff --git a/libyul/optimiser/RedundantAssignEliminator.h b/libyul/optimiser/UnusedAssignEliminator.h similarity index 94% rename from libyul/optimiser/RedundantAssignEliminator.h rename to libyul/optimiser/UnusedAssignEliminator.h index 65bbb53fa2..b5a2998a17 100644 --- a/libyul/optimiser/RedundantAssignEliminator.h +++ b/libyul/optimiser/UnusedAssignEliminator.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -107,13 +107,13 @@ struct Dialect; * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ -class RedundantAssignEliminator: public RedundantStoreBase +class UnusedAssignEliminator: public UnusedStoreBase { public: - static constexpr char const* name{"RedundantAssignEliminator"}; + static constexpr char const* name{"UnusedAssignEliminator"}; static void run(OptimiserStepContext&, Block& _ast); - explicit RedundantAssignEliminator(Dialect const& _dialect): RedundantStoreBase(_dialect) {} + explicit UnusedAssignEliminator(Dialect const& _dialect): UnusedStoreBase(_dialect) {} void operator()(Identifier const& _identifier) override; void operator()(VariableDeclaration const& _variableDeclaration) override; @@ -122,7 +122,7 @@ class RedundantAssignEliminator: public RedundantStoreBase void operator()(Leave const&) override; void operator()(Block const& _block) override; - using RedundantStoreBase::visit; + using UnusedStoreBase::visit; void visit(Statement const& _statement) override; private: diff --git a/libyul/optimiser/RedundantStoreBase.cpp b/libyul/optimiser/UnusedStoreBase.cpp similarity index 86% rename from libyul/optimiser/RedundantStoreBase.cpp rename to libyul/optimiser/UnusedStoreBase.cpp index 6fc0570b74..27700bdf74 100644 --- a/libyul/optimiser/RedundantStoreBase.cpp +++ b/libyul/optimiser/UnusedStoreBase.cpp @@ -16,10 +16,10 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Base class for both RedundantAssignEliminator and RedundantStoreEliminator. + * Base class for both UnusedAssignEliminator and UnusedStoreEliminator. */ -#include +#include #include #include @@ -33,7 +33,7 @@ using namespace std; using namespace solidity; using namespace solidity::yul; -void RedundantStoreBase::operator()(If const& _if) +void UnusedStoreBase::operator()(If const& _if) { visit(*_if.condition); @@ -43,7 +43,7 @@ void RedundantStoreBase::operator()(If const& _if) merge(m_stores, move(skipBranch)); } -void RedundantStoreBase::operator()(Switch const& _switch) +void UnusedStoreBase::operator()(Switch const& _switch) { visit(*_switch.expression); @@ -69,7 +69,7 @@ void RedundantStoreBase::operator()(Switch const& _switch) merge(m_stores, move(branch)); } -void RedundantStoreBase::operator()(FunctionDefinition const& _functionDefinition) +void UnusedStoreBase::operator()(FunctionDefinition const& _functionDefinition) { ScopedSaveAndRestore outerAssignments(m_stores, {}); ScopedSaveAndRestore forLoopInfo(m_forLoopInfo, {}); @@ -79,7 +79,7 @@ void RedundantStoreBase::operator()(FunctionDefinition const& _functionDefinitio finalizeFunctionDefinition(_functionDefinition); } -void RedundantStoreBase::operator()(ForLoop const& _forLoop) +void UnusedStoreBase::operator()(ForLoop const& _forLoop) { ScopedSaveAndRestore outerForLoopInfo(m_forLoopInfo, {}); ScopedSaveAndRestore forLoopNestingDepth(m_forLoopNestingDepth, m_forLoopNestingDepth + 1); @@ -127,19 +127,19 @@ void RedundantStoreBase::operator()(ForLoop const& _forLoop) m_forLoopInfo.pendingBreakStmts.clear(); } -void RedundantStoreBase::operator()(Break const&) +void UnusedStoreBase::operator()(Break const&) { m_forLoopInfo.pendingBreakStmts.emplace_back(move(m_stores)); m_stores.clear(); } -void RedundantStoreBase::operator()(Continue const&) +void UnusedStoreBase::operator()(Continue const&) { m_forLoopInfo.pendingContinueStmts.emplace_back(move(m_stores)); m_stores.clear(); } -void RedundantStoreBase::merge(TrackedStores& _target, TrackedStores&& _other) +void UnusedStoreBase::merge(TrackedStores& _target, TrackedStores&& _other) { util::joinMap(_target, move(_other), []( map& _assignmentHere, @@ -150,7 +150,7 @@ void RedundantStoreBase::merge(TrackedStores& _target, TrackedStores&& _other) }); } -void RedundantStoreBase::merge(TrackedStores& _target, vector&& _source) +void UnusedStoreBase::merge(TrackedStores& _target, vector&& _source) { for (TrackedStores& ts: _source) merge(_target, move(ts)); diff --git a/libyul/optimiser/RedundantStoreBase.h b/libyul/optimiser/UnusedStoreBase.h similarity index 92% rename from libyul/optimiser/RedundantStoreBase.h rename to libyul/optimiser/UnusedStoreBase.h index ed588927c1..a65af4e45a 100644 --- a/libyul/optimiser/RedundantStoreBase.h +++ b/libyul/optimiser/UnusedStoreBase.h @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Base class for both RedundantAssignEliminator and RedundantStoreEliminator. + * Base class for both UnusedAssignEliminator and UnusedStoreEliminator. */ #pragma once @@ -34,14 +34,14 @@ namespace solidity::yul struct Dialect; /** - * Base class for both RedundantAssignEliminator and RedundantStoreEliminator. + * Base class for both UnusedAssignEliminator and UnusedStoreEliminator. * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ -class RedundantStoreBase: public ASTWalker +class UnusedStoreBase: public ASTWalker { public: - explicit RedundantStoreBase(Dialect const& _dialect): m_dialect(_dialect) {} + explicit UnusedStoreBase(Dialect const& _dialect): m_dialect(_dialect) {} using ASTWalker::operator(); void operator()(If const& _if) override; diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 962cb18a40..cc315c4b97 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include #include @@ -231,16 +231,16 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( ForLoopInitRewriter::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_ast); }}, - {"redundantAssignEliminator", [&]() { + {"unusedAssignEliminator", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); - RedundantAssignEliminator::run(*m_context, *m_ast); + UnusedAssignEliminator::run(*m_context, *m_ast); }}, {"ssaPlusCleanup", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_ast); - RedundantAssignEliminator::run(*m_context, *m_ast); + UnusedAssignEliminator::run(*m_context, *m_ast); }}, {"loadResolver", [&]() { disambiguate(); @@ -293,7 +293,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( ForLoopInitRewriter::run(*m_context, *m_ast); // apply SSA SSATransform::run(*m_context, *m_ast); - RedundantAssignEliminator::run(*m_context, *m_ast); + UnusedAssignEliminator::run(*m_context, *m_ast); // reverse SSA SSAReverser::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast); diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_branch.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_branch.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_branch.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_branch.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_break.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_break.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_break.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_break.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_continue.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_continue_2.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_2.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_continue_2.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_2.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_continue_3.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_3.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_continue_3.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_3.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_decl_inside_break_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_decl_inside_break_continue.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_decl_inside_break_continue.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_decl_inside_break_continue.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_deep_noremove.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_noremove.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_deep_noremove.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_noremove.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_deep_simple.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_simple.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_deep_simple.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_simple.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_multi_break.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_multi_break.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_multi_break.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_multi_break.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_nested.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_nested.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_nested.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_nested.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_rerun.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_rerun.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_rerun.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_rerun.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_stmnts_after_break_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_stmnts_after_break_continue.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/for_stmnts_after_break_continue.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/for_stmnts_after_break_continue.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/function.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/function.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/function.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/function.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/if.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/if.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_overwrite_all_branches.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_overwrite_all_branches.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/if_overwrite_all_branches.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/if_overwrite_all_branches.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_used_in_one_branch.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_used_in_one_branch.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/if_used_in_one_branch.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/if_used_in_one_branch.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/leave.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/leave.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/multi_assign.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/multi_assign.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/multi_assign.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/multi_assign.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/multivar.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/multivar.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/multivar.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/multivar.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/non_movable.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/non_movable.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/non_movable.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/non_movable.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/remove_break.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_break.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/remove_break.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_break.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/remove_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_continue.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/remove_continue.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_continue.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/scopes.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/scopes.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/scopes.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/scopes.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/simple.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/simple.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/simple.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/simple.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_all.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_all.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_all.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_all.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_one.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_one.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_one.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_one.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_use_combination.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_use_combination.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_use_combination.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_use_combination.yul diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_unused.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_unused.yul similarity index 100% rename from test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_unused.yul rename to test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_unused.yul diff --git a/test/yulPhaser/Chromosome.cpp b/test/yulPhaser/Chromosome.cpp index 55bfd8f24b..9a396283d2 100644 --- a/test/yulPhaser/Chromosome.cpp +++ b/test/yulPhaser/Chromosome.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -50,7 +50,7 @@ namespace solidity::phaser::test vector const ChrOmOsoMeSteps{ ConditionalSimplifier::name, FunctionHoister::name, - RedundantAssignEliminator::name, + UnusedAssignEliminator::name, ForLoopConditionOutOfBody::name, Rematerialiser::name, ForLoopConditionOutOfBody::name, From 3b98bee29adcac26e68c72fc4b5f59b43da08f68 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 23 Nov 2021 14:05:14 +0100 Subject: [PATCH 0021/1704] Update z3 version. --- scripts/deps-ppa/static_z3.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh index 66fbd3fa73..e8dec0faee 100755 --- a/scripts/deps-ppa/static_z3.sh +++ b/scripts/deps-ppa/static_z3.sh @@ -25,7 +25,7 @@ set -ev keyid=70D110489D66E2F6 email=builds@ethereum.org packagename=z3-static -version=4.8.12 +version=4.8.13 DISTRIBUTIONS="focal groovy hirsute" From 0e7a065a782b50b95bcca0291e1caefab6ac05bb Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 23 Nov 2021 10:42:18 +0100 Subject: [PATCH 0022/1704] Enhance documentation. --- libyul/optimiser/UnusedStoreBase.h | 5 +++++ test/libyul/yulOptimizerTests/unusedAssignEliminator/for.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/for_branch.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/for_break.yul | 2 +- .../unusedAssignEliminator/for_continue.yul | 2 +- .../unusedAssignEliminator/for_continue_2.yul | 2 +- .../unusedAssignEliminator/for_continue_3.yul | 2 +- .../for_decl_inside_break_continue.yul | 2 +- .../unusedAssignEliminator/for_deep_noremove.yul | 2 +- .../unusedAssignEliminator/for_deep_simple.yul | 2 +- .../unusedAssignEliminator/for_multi_break.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/for_nested.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/for_rerun.yul | 2 +- .../for_stmnts_after_break_continue.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/function.yul | 2 +- test/libyul/yulOptimizerTests/unusedAssignEliminator/if.yul | 2 +- .../unusedAssignEliminator/if_overwrite_all_branches.yul | 2 +- .../unusedAssignEliminator/if_used_in_one_branch.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/leave.yul | 2 +- .../unusedAssignEliminator/multi_assign.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/multivar.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/non_movable.yul | 2 +- .../unusedAssignEliminator/remove_break.yul | 2 +- .../unusedAssignEliminator/remove_continue.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/scopes.yul | 2 +- .../yulOptimizerTests/unusedAssignEliminator/simple.yul | 2 +- .../unusedAssignEliminator/switch_overwrite_in_all.yul | 2 +- .../unusedAssignEliminator/switch_overwrite_in_one.yul | 2 +- .../switch_overwrite_use_combination.yul | 2 +- .../unusedAssignEliminator/switch_unused.yul | 2 +- test/yulPhaser/Chromosome.cpp | 2 +- 31 files changed, 35 insertions(+), 30 deletions(-) diff --git a/libyul/optimiser/UnusedStoreBase.h b/libyul/optimiser/UnusedStoreBase.h index a65af4e45a..3bd4e42976 100644 --- a/libyul/optimiser/UnusedStoreBase.h +++ b/libyul/optimiser/UnusedStoreBase.h @@ -36,6 +36,11 @@ struct Dialect; /** * Base class for both UnusedAssignEliminator and UnusedStoreEliminator. * + * The class tracks the state of abstract "stores" (assignments or mstore/sstore + * statements) across the control-flow. It is the job of the derived class to create + * the stores and track references, but the base class adjusts their "used state" at + * control-flow splits and joins. + * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ class UnusedStoreBase: public ASTWalker diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for.yul index 3149633680..89de8920cd 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for.yul @@ -8,7 +8,7 @@ } } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let a := 2 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_branch.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_branch.yul index 120b43ce81..8700c8d28b 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_branch.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_branch.yul @@ -14,7 +14,7 @@ mstore(x, 0) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_break.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_break.yul index 1b795ad8c7..db55bf7588 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_break.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_break.yul @@ -13,7 +13,7 @@ mstore(x, 0x42) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul index 0ee9c551da..d3cfb0d84b 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul @@ -16,7 +16,7 @@ x := 3 } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_2.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_2.yul index ee747ae5d0..2d5bae46e2 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_2.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_2.yul @@ -13,7 +13,7 @@ mstore(x, 0x42) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_3.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_3.yul index b70f35d2bc..d9980d376d 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_3.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue_3.yul @@ -12,7 +12,7 @@ } } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_decl_inside_break_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_decl_inside_break_continue.yul index f54b21af8b..94b100e2a9 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_decl_inside_break_continue.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_decl_inside_break_continue.yul @@ -19,7 +19,7 @@ mstore(x, 0x42) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x := 1 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_noremove.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_noremove.yul index 5edd71d58b..02a735f9e5 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_noremove.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_noremove.yul @@ -26,7 +26,7 @@ x := 13 } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x := 1 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_simple.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_simple.yul index 5b086bab8a..039d856d96 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_simple.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_deep_simple.yul @@ -19,7 +19,7 @@ } } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // for { } 1 { } diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_multi_break.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_multi_break.yul index ce084b1ce1..3b18dcc8dc 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_multi_break.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_multi_break.yul @@ -35,7 +35,7 @@ mstore(x, 0x42) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x := 1 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_nested.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_nested.yul index a83f536668..101101b923 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_nested.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_nested.yul @@ -32,7 +32,7 @@ mstore(x, 0x42) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x := 1 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_rerun.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_rerun.yul index 5d1e607385..08cf63a52d 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_rerun.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_rerun.yul @@ -11,7 +11,7 @@ x := 3 } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_stmnts_after_break_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_stmnts_after_break_continue.yul index 5e88df9689..1a92d3b841 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_stmnts_after_break_continue.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_stmnts_after_break_continue.yul @@ -23,7 +23,7 @@ mstore(x, 0x42) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x := 1 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/function.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/function.yul index 2a20ca8b69..044a5f418f 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/function.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/function.yul @@ -12,7 +12,7 @@ r := 2 } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let r diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/if.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if.yul index 2fab04a36f..7c65680ae6 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/if.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if.yul @@ -10,7 +10,7 @@ mstore(0, d) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let c diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_overwrite_all_branches.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_overwrite_all_branches.yul index 7585f848a2..860050e59d 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_overwrite_all_branches.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_overwrite_all_branches.yul @@ -11,7 +11,7 @@ mstore(0, d) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let c diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_used_in_one_branch.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_used_in_one_branch.yul index 637a32c02a..90643f174c 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_used_in_one_branch.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/if_used_in_one_branch.yul @@ -11,7 +11,7 @@ mstore(0, d) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let c diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul index 1caee198a1..82bf493470 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul @@ -21,7 +21,7 @@ } } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // function f(a, b) -> x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/multi_assign.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/multi_assign.yul index f0845680f4..d4b35e7ee1 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/multi_assign.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/multi_assign.yul @@ -9,7 +9,7 @@ y := 4 } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // function f() -> a, b diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/multivar.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/multivar.yul index 2b13ba3c36..d4dda8f902 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/multivar.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/multivar.yul @@ -6,7 +6,7 @@ a := b } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let a := 2 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/non_movable.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/non_movable.yul index 343c672dea..e131b3549e 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/non_movable.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/non_movable.yul @@ -4,7 +4,7 @@ a := mload(0) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let a diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_break.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_break.yul index 035f66d385..76a536c2f3 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_break.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_break.yul @@ -12,7 +12,7 @@ } } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let i := 0 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_continue.yul index c4f3b3e43f..27083a73c2 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_continue.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/remove_continue.yul @@ -13,7 +13,7 @@ } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let i := 0 diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/scopes.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/scopes.yul index d3c6cb4a6d..bc2d4d80f6 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/scopes.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/scopes.yul @@ -7,7 +7,7 @@ } } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let a diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/simple.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/simple.yul index 12b9ae6b71..326ce29dcd 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/simple.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/simple.yul @@ -4,6 +4,6 @@ a := 2 } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { let a } diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_all.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_all.yul index a39cdedd70..a6b77f8973 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_all.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_all.yul @@ -8,7 +8,7 @@ mstore(x, 0) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_one.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_one.yul index 271bb4864c..9b0a23cd88 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_one.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_in_one.yul @@ -7,7 +7,7 @@ mstore(x, 0) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_use_combination.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_use_combination.yul index 8d38dcc161..611123db36 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_use_combination.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_overwrite_use_combination.yul @@ -8,7 +8,7 @@ mstore(x, 0) } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_unused.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_unused.yul index 94de51b889..c15c889919 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_unused.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/switch_unused.yul @@ -6,7 +6,7 @@ case 0 { mstore(0, 1) } } // ---- -// step: redundantAssignEliminator +// step: unusedAssignEliminator // // { // let x diff --git a/test/yulPhaser/Chromosome.cpp b/test/yulPhaser/Chromosome.cpp index 9a396283d2..19616cde0b 100644 --- a/test/yulPhaser/Chromosome.cpp +++ b/test/yulPhaser/Chromosome.cpp @@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(output_operator_should_create_concise_and_unambiguous_strin BOOST_TEST(chromosome.length() == allSteps.size()); BOOST_TEST(chromosome.optimisationSteps() == allSteps); - BOOST_TEST(toString(chromosome) == "flcCUnDvejsxIOoighFTLMRrmVatpud"); + BOOST_TEST(toString(chromosome) == "flcCUnDvejsxIOoighFTLMRmVatrpud"); } BOOST_AUTO_TEST_CASE(optimisationSteps_should_translate_chromosomes_genes_to_optimisation_step_names) From 4e6b5205ac0e7921edd311a9a2053ec5675a3b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 23 Nov 2021 16:40:54 +0100 Subject: [PATCH 0023/1704] CI: Include workflow name instead of hard-coded "nightly" in gitter notifications --- .circleci/config.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 10d0d0116d..b917dd5670 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,8 +48,13 @@ commands: # but it's broken. CircleCI associates runs on develop/breaking with random old PRs. [[ $CIRCLE_BRANCH == develop || $CIRCLE_BRANCH == breaking ]] || { echo "Running on a PR or a feature branch - notification skipped."; exit 0; } - [[ "<< parameters.event >>" == "failure" ]] && message=" ❌ Nightly job **${CIRCLE_JOB}** failed on **${CIRCLE_BRANCH}**. Please see [build #${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." - [[ "<< parameters.event >>" == "success" ]] && message=" ✅ Nightly job **${CIRCLE_JOB}** succeeded on **${CIRCLE_BRANCH}**. Please see [build #${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." + # Workflow name is not exposed as an env variable. Has to be queried from the API. + # The name is not critical so if anything fails, use the raw workflow ID as a fallback. + workflow_info=$(curl --silent "https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}") || true + workflow_name=$(echo "$workflow_info" | jq --raw-output .name || echo "$CIRCLE_WORKFLOW_ID") + + [[ "<< parameters.event >>" == "failure" ]] && message=" ❌ [${workflow_name}] Job **${CIRCLE_JOB}** failed on **${CIRCLE_BRANCH}**. Please see [build #${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." + [[ "<< parameters.event >>" == "success" ]] && message=" ✅ [${workflow_name}] Job **${CIRCLE_JOB}** succeeded on **${CIRCLE_BRANCH}**. Please see [build #${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." curl "https://api.gitter.im/v1/rooms/${GITTER_NOTIFY_ROOM_ID}/chatMessages" \ --request POST \ From 00fb719d03cb3495ceee9c63fd4a8df4da986f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 23 Nov 2021 16:41:22 +0100 Subject: [PATCH 0024/1704] CI: Don't use # in gitter notifications --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b917dd5670..dce0553751 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,8 +53,8 @@ commands: workflow_info=$(curl --silent "https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}") || true workflow_name=$(echo "$workflow_info" | jq --raw-output .name || echo "$CIRCLE_WORKFLOW_ID") - [[ "<< parameters.event >>" == "failure" ]] && message=" ❌ [${workflow_name}] Job **${CIRCLE_JOB}** failed on **${CIRCLE_BRANCH}**. Please see [build #${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." - [[ "<< parameters.event >>" == "success" ]] && message=" ✅ [${workflow_name}] Job **${CIRCLE_JOB}** succeeded on **${CIRCLE_BRANCH}**. Please see [build #${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." + [[ "<< parameters.event >>" == "failure" ]] && message=" ❌ [${workflow_name}] Job **${CIRCLE_JOB}** failed on **${CIRCLE_BRANCH}**. Please see [build ${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." + [[ "<< parameters.event >>" == "success" ]] && message=" ✅ [${workflow_name}] Job **${CIRCLE_JOB}** succeeded on **${CIRCLE_BRANCH}**. Please see [build ${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." curl "https://api.gitter.im/v1/rooms/${GITTER_NOTIFY_ROOM_ID}/chatMessages" \ --request POST \ From 406b1fbcec5bbc0d497adea016d02a98a32ad8e7 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Tue, 23 Nov 2021 18:07:59 +0100 Subject: [PATCH 0025/1704] bump docker hashes and z3 version --- .circleci/config.yml | 16 ++++++++-------- .circleci/osx_install_dependencies.sh | 4 ++-- CMakeLists.txt | 2 +- scripts/build_emscripten.sh | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index dce0553751..fb3abb37af 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,20 +9,20 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-8 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:9c3cdfc1d573d1ca3edacd892590a9a83487a1f746a6ca2093d7e009818c5179" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-9 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:3d8a912e8e78e98cd217955d06d98608ad60adc67728d4c3a569991235fa1abb" ubuntu-2004-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004.clang-8 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:61232feea23c8c57e82cf5fae890f8b86bbec353cdc04f2fcba383ca589e1d8b" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004.clang-9 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:a1ba002cae17279d1396a898b04e4e9c45602ad881295db3e2f484a7e24f6f43" ubuntu-1604-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu1604.clang.ossfuzz-13 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c26a7ffc9fc243a4ec3105b9dc1edcdd964ad0e9665c83172b7ebda74bbf3021" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu1604.clang.ossfuzz-14 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:f353823cce2f6cd2f9f1459d86cd76fdfc551a0261d87626615ea6c1d8f90587" emscripten-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:emscripten-7 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:9ffcd0944433fe100e9433f2aa9ba5c21e096e758ad8a05a4a76feaed3d1f463" + # solbuildpackpusher/solidity-buildpack-deps:emscripten-8 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:842d6074e0e7e5355c89122c1cafc1fdb59696596750e7d56e5f35c0d883ad59" evm-version: type: string default: london diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index 7ef8635a87..a973988a6e 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -61,8 +61,8 @@ then ./scripts/install_obsolete_jsoncpp_1_7_4.sh # z3 - z3_version="4.8.12" - z3_dir="z3-${z3_version}-x64-osx-10.15.7" + z3_version="4.8.13" + z3_dir="z3-${z3_version}-x64-osx-10.16" z3_package="${z3_dir}.zip" wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_package}" validate_checksum "$z3_package" a1f6ef3c99456147c4d3f2652dc6bc90951c4ab3fe7741a255eb794f0ab8938c diff --git a/CMakeLists.txt b/CMakeLists.txt index e3dc030c13..b4e91f8261 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ configure_file("${CMAKE_SOURCE_DIR}/cmake/templates/license.h.in" include/licens include(EthOptions) configure_project(TESTS) -set(LATEST_Z3_VERSION "4.8.12") +set(LATEST_Z3_VERSION "4.8.13") set(MINIMUM_Z3_VERSION "4.8.0") find_package(Z3) if (${Z3_FOUND}) diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index 7b8510026c..f6c9151ebf 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -34,7 +34,7 @@ else BUILD_DIR="$1" fi -# solbuildpackpusher/solidity-buildpack-deps:emscripten-7 +# solbuildpackpusher/solidity-buildpack-deps:emscripten-8 docker run -v "$(pwd):/root/project" -w /root/project \ - solbuildpackpusher/solidity-buildpack-deps@sha256:9ffcd0944433fe100e9433f2aa9ba5c21e096e758ad8a05a4a76feaed3d1f463 \ + solbuildpackpusher/solidity-buildpack-deps@sha256:842d6074e0e7e5355c89122c1cafc1fdb59696596750e7d56e5f35c0d883ad59 \ ./scripts/ci/build_emscripten.sh "$BUILD_DIR" From ff5c842d673b311a6dba7466f0506680dd3bab63 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Tue, 23 Nov 2021 18:08:36 +0100 Subject: [PATCH 0026/1704] update smtchecker tests --- .../smtCheckerTests/abi/abi_decode_array.sol | 12 +++--------- .../abi/abi_encode_with_sig_hash.sol | 4 +--- .../length_same_after_assignment_3_fail.sol | 2 +- .../array_members/push_as_lhs_1d.sol | 2 +- .../array_members/push_as_lhs_and_rhs_1d.sol | 2 +- .../push_overflow_2_safe_no_overflow_assumption.sol | 1 - .../array_members/push_push_no_args_2_fail.sol | 4 ++-- .../blockchain_state/balance_receive_4.sol | 2 +- .../blockchain_state/balance_receive_ext_calls.sol | 2 +- .../balance_receive_ext_calls_2.sol | 2 +- .../balance_receive_ext_calls_mutex.sol | 2 +- .../blockchain_state/balance_spend.sol | 2 +- .../blockchain_state/balance_spend_2.sol | 1 - .../this_does_not_change_external_call.sol | 2 +- .../branches_in_modifiers_2.sol | 2 +- .../crypto/crypto_functions_compare_hashes.sol | 12 +++++++++--- .../crypto/crypto_functions_not_same.sol | 4 +++- ..._functions_same_input_over_state_same_output.sol | 13 ++++++++++++- .../smtCheckerTests/external_calls/call_mutex.sol | 2 +- .../external_calls/call_reentrancy_view.sol | 2 +- .../smtCheckerTests/external_calls/call_safe.sol | 2 +- .../external_calls/call_with_value_1.sol | 4 +--- .../external_call_this_with_value_1.sol | 2 +- .../external_hash_known_code_state.sol | 2 +- .../external_hash_known_code_state_reentrancy_3.sol | 2 +- ...rnal_hash_known_code_state_reentrancy_unsafe.sol | 4 +--- .../external_calls/external_reentrancy_1.sol | 4 +++- .../external_calls/external_reentrancy_crypto.sol | 3 +++ .../external_calls/external_single_inc.sol | 2 +- .../functions/functions_external_1.sol | 2 +- .../functions/functions_external_2.sol | 2 +- .../smtCheckerTests/functions/getters/struct_3.sol | 11 +++++++++-- .../virtual_function_called_by_constructor.sol | 2 +- .../natspec/unsafe_assert_remains_unsafe.sol | 2 +- .../assignment_module_contract_member_variable.sol | 2 +- .../operators/compound_add_array_index.sol | 2 +- .../operators/compound_bitwise_string_literal_3.sol | 3 ++- .../operators/conditional_assignment_5.sol | 4 +--- .../operators/conditional_assignment_6.sol | 2 +- .../operators/slice_default_start.sol | 3 ++- .../smtCheckerTests/out_of_bounds/array_1.sol | 3 +-- .../overflow/unsigned_mul_overflow.sol | 2 +- .../smtCheckerTests/special/abi_decode_simple.sol | 2 +- .../special/tx_vars_chc_internal.sol | 2 +- .../special/tx_vars_reentrancy_1.sol | 2 +- .../special/tx_vars_reentrancy_2.sol | 2 +- .../try_catch/try_public_var_mapping.sol | 2 +- .../smtCheckerTests/types/abi_type_type_1.sol | 2 +- .../smtCheckerTests/types/address_staticcall.sol | 6 ++++-- .../smtCheckerTests/types/bool_simple_2.sol | 2 +- .../smtCheckerTests/types/fixed_bytes_access_3.sol | 3 +-- .../smtCheckerTests/userTypes/user_abi_1.sol | 2 +- .../smtCheckerTests/userTypes/user_abi_2.sol | 2 +- 53 files changed, 92 insertions(+), 75 deletions(-) diff --git a/test/libsolidity/smtCheckerTests/abi/abi_decode_array.sol b/test/libsolidity/smtCheckerTests/abi/abi_decode_array.sol index 3c88329a35..e2c0894934 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_decode_array.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_decode_array.sol @@ -32,9 +32,6 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 1218: (1009-1037): CHC: Error trying to invoke SMT solver. -// Warning 1218: (1056-1084): CHC: Error trying to invoke SMT solver. -// Warning 1218: (1103-1131): CHC: Error trying to invoke SMT solver. // Warning 6328: (182-210): CHC: Assertion violation happens here. // Warning 6328: (335-363): CHC: Assertion violation happens here. // Warning 6328: (414-442): CHC: Assertion violation happens here. @@ -42,9 +39,6 @@ contract C { // Warning 6328: (607-635): CHC: Assertion violation happens here. // Warning 6328: (654-682): CHC: Assertion violation happens here. // Warning 6328: (879-916): CHC: Assertion violation happens here. -// Warning 6328: (1009-1037): CHC: Assertion violation might happen here. -// Warning 6328: (1056-1084): CHC: Assertion violation might happen here. -// Warning 6328: (1103-1131): CHC: Assertion violation might happen here. -// Warning 4661: (1009-1037): BMC: Assertion violation happens here. -// Warning 4661: (1056-1084): BMC: Assertion violation happens here. -// Warning 4661: (1103-1131): BMC: Assertion violation happens here. +// Warning 6328: (1009-1037): CHC: Assertion violation happens here. +// Warning 6328: (1056-1084): CHC: Assertion violation happens here. +// Warning 6328: (1103-1131): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_hash.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_hash.sol index dbf4237411..61e755d82d 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_hash.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_hash.sol @@ -13,9 +13,7 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 1218: (337-375): CHC: Error trying to invoke SMT solver. // Warning 1218: (394-432): CHC: Error trying to invoke SMT solver. -// Warning 6328: (337-375): CHC: Assertion violation might happen here. +// Warning 6328: (337-375): CHC: Assertion violation happens here. // Warning 6328: (394-432): CHC: Assertion violation might happen here. -// Warning 4661: (337-375): BMC: Assertion violation happens here. // Warning 4661: (394-432): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_3_fail.sol b/test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_3_fail.sol index 062b668c38..7a7db383b2 100644 --- a/test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_3_fail.sol +++ b/test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_3_fail.sol @@ -31,4 +31,4 @@ contract C { // Warning 6328: (349-375): CHC: Assertion violation happens here.\nCounterexample:\narr = [[], [], [], [], [], [], [], [], []]\nx = 0\ny = 0\nz = 9\nt = 0\n\nTransaction trace:\nC.constructor()\nState: arr = [[], [], [], [], [], [], [], [], []]\nC.f() // Warning 6328: (379-402): CHC: Assertion violation happens here.\nCounterexample:\narr = [[], [], [], [], [], [], [], [], []]\nx = 0\ny = 0\nz = 9\nt = 0\n\nTransaction trace:\nC.constructor()\nState: arr = [[], [], [], [], [], [], [], [], []]\nC.f() // Warning 6328: (406-432): CHC: Assertion violation happens here.\nCounterexample:\narr = [[], [], [], [], [], [], [], [], []]\nx = 0\ny = 0\nz = 9\nt = 0\n\nTransaction trace:\nC.constructor()\nState: arr = [[], [], [], [], [], [], [], [], []]\nC.f() -// Info 1180: Contract invariant(s) for :C:\n!(arr.length <= 3)\n!(arr.length <= 5)\n!(arr.length <= 7)\n!(arr.length <= 8)\n +// Info 1180: Contract invariant(s) for :C:\n!(arr.length <= 7)\n!(arr.length <= 8)\n diff --git a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol index 30f194eb7c..5920a4e747 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol @@ -18,4 +18,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (199-229): CHC: Assertion violation happens here. +// Warning 6328: (199-229): CHC: Assertion violation happens here.\nCounterexample:\nb = [1]\n\nTransaction trace:\nC.constructor()\nState: b = []\nC.g() diff --git a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_and_rhs_1d.sol b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_and_rhs_1d.sol index ad3ba78234..66776ed49f 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_and_rhs_1d.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_and_rhs_1d.sol @@ -14,4 +14,4 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Warning 6328: (204-230): CHC: Assertion violation happens here.\nCounterexample:\nb = [0, 0]\nlength = 2\n\nTransaction trace:\nC.constructor()\nState: b = []\nC.f() +// Warning 6328: (204-230): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/array_members/push_overflow_2_safe_no_overflow_assumption.sol b/test/libsolidity/smtCheckerTests/array_members/push_overflow_2_safe_no_overflow_assumption.sol index 60b11c91a6..046cf59a13 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_overflow_2_safe_no_overflow_assumption.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_overflow_2_safe_no_overflow_assumption.sol @@ -13,4 +13,3 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Info 1180: Contract invariant(s) for :C:\n(x.length >= 0)\n diff --git a/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2_fail.sol b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2_fail.sol index dcda253ce4..42313dee93 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2_fail.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2_fail.sol @@ -13,5 +13,5 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 6328: (90-116): CHC: Assertion violation happens here.\nCounterexample:\narray2d = [[[0]]]\nlast = 0\n\nTransaction trace:\nC.constructor()\nState: array2d = []\nC.l() -// Warning 6328: (170-186): CHC: Assertion violation happens here. -// Warning 6328: (190-246): CHC: Assertion violation happens here. +// Warning 6328: (170-186): CHC: Assertion violation happens here.\nCounterexample:\narray2d = [[[0]]]\nlast = 1\n\nTransaction trace:\nC.constructor()\nState: array2d = []\nC.l() +// Warning 6328: (190-246): CHC: Assertion violation happens here.\nCounterexample:\narray2d = [[[0]]]\nlast = 1\n\nTransaction trace:\nC.constructor()\nState: array2d = []\nC.l() diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_4.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_4.sol index e8f750d07a..3e3e564317 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_4.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_4.sol @@ -15,7 +15,7 @@ contract C { // Warning 4984: (82-85): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 4984: (154-160): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 4984: (212-218): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6328: (180-219): CHC: Assertion violation happens here. +// Warning 6328: (180-219): CHC: Assertion violation happens here.\nCounterexample:\nc = 1\n\nTransaction trace:\nC.constructor()\nState: c = 0\nC.f(){ msg.value: 11 }\nState: c = 1\nC.inv() // Info 1180: Contract invariant(s) for :C:\n(((11 * c) + ((- 1) * (:var 1).balances[address(this)])) <= 0)\n // Warning 2661: (82-85): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. // Warning 2661: (154-160): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls.sol index e46dfda34b..1ee90e41d0 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls.sol @@ -15,5 +15,5 @@ contract C { // ---- // Warning 1218: (131-165): CHC: Error trying to invoke SMT solver. // Warning 6328: (131-165): CHC: Assertion violation might happen here. -// Info 1180: Reentrancy property(ies) for :C:\n(!( >= 2) && (((:var 0).balances[address(this)] + ((- 1) * (:var 1).balances[address(this)])) >= 0))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(address(this).balance == x)\n = 2 -> Assertion failed at assert(address(this).balance >= x)\n +// Info 1180: Reentrancy property(ies) for :C:\n(!( >= 2) && (((:var 1).balances[address(this)] + ((- 1) * (:var 0).balances[address(this)])) <= 0))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(address(this).balance == x)\n = 2 -> Assertion failed at assert(address(this).balance >= x)\n // Warning 4661: (131-165): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls_2.sol index 28c4734bd4..c53f156d63 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls_2.sol @@ -12,4 +12,4 @@ contract C { // ---- // Warning 9302: (82-93): Return value of low-level calls not used. // Warning 6328: (97-131): CHC: Assertion violation happens here. -// Info 1180: Reentrancy property(ies) for :C:\n((((:var 1).balances[address(this)] + ((- 1) * (:var 0).balances[address(this)])) <= 0) && !( >= 2))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(address(this).balance == x)\n = 2 -> Assertion failed at assert(address(this).balance >= x)\n +// Info 1180: Reentrancy property(ies) for :C:\n(!( >= 2) && (((:var 1).balances[address(this)] + ((- 1) * (:var 0).balances[address(this)])) <= 0))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(address(this).balance == x)\n = 2 -> Assertion failed at assert(address(this).balance >= x)\n diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls_mutex.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls_mutex.sol index 559f67e193..76443dfd05 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls_mutex.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls_mutex.sol @@ -22,4 +22,4 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 6328: (277-310): CHC: Assertion violation happens here. -// Info 1180: Reentrancy property(ies) for :C:\n((!lock || (((:var 3).balances[address(this)] + ((- 1) * (:var 1).balances[address(this)])) <= 0)) && !( = 1) && (lock' || !lock) && (!lock || (((:var 3).balances[address(this)] + ((- 1) * (:var 1).balances[address(this)])) >= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(address(this).balance == x)\n = 2 -> Assertion failed at assert(address(this).balance < x)\n +// Info 1180: Reentrancy property(ies) for :C:\n((lock' || !lock) && !( = 1) && (!lock || (((:var 3).balances[address(this)] + ((- 1) * (:var 1).balances[address(this)])) >= 0)) && (!lock || (((:var 3).balances[address(this)] + ((- 1) * (:var 1).balances[address(this)])) <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(address(this).balance == x)\n = 2 -> Assertion failed at assert(address(this).balance < x)\n diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol index 1e4ec7a32a..bd30b77d1f 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol @@ -19,5 +19,5 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 6328: (280-314): CHC: Assertion violation happens here. -// Info 1180: Contract invariant(s) for :C:\n((!(c <= 1) || !((:var 1).balances[address(this)] <= 91)) && !((:var 1).balances[address(this)] <= 82) && (!(c <= 0) || !((:var 1).balances[address(this)] <= 100)))\n +// Info 1180: Contract invariant(s) for :C:\n((!(c <= 1) || !((:var 1).balances[address(this)] <= 90)) && !((:var 1).balances[address(this)] <= 81) && (!(c <= 0) || !((:var 1).balances[address(this)] <= 100)))\n // Warning 1236: (175-190): BMC: Insufficient funds happens here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol index 0b3a432e8c..5df0b99956 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol @@ -16,7 +16,6 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 1218: (193-226): CHC: Error trying to invoke SMT solver. // Warning 6328: (193-226): CHC: Assertion violation might happen here. // Warning 6328: (245-279): CHC: Assertion violation happens here. // Warning 6328: (298-332): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/this_does_not_change_external_call.sol b/test/libsolidity/smtCheckerTests/blockchain_state/this_does_not_change_external_call.sol index 0b5136dcab..f169645010 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/this_does_not_change_external_call.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/this_does_not_change_external_call.sol @@ -18,4 +18,4 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Info 1180: Contract invariant(s) for :C:\n(((address(this) + ((- 1) * t)) <= 0) && ((address(this) + ((- 1) * t)) >= 0))\nReentrancy property(ies) for :C:\n((!( >= 2) || !((t + ((- 1) * address(this))) = 0)) && (!((t + ((- 1) * address(this))) <= 0) || ((t' + ((- 1) * address(this))) <= 0)) && (!((t + ((- 1) * address(this))) >= 0) || ((address(this) + ((- 1) * t')) <= 0)))\n((( <= 0) || !((t + ((- 1) * address(this))) = 0)) && (!((t + ((- 1) * address(this))) <= 0) || ((t' + ((- 1) * address(this))) <= 0)) && (!((t + ((- 1) * address(this))) >= 0) || ((address(this) + ((- 1) * t')) <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(address(this) == t)\n = 2 -> Assertion failed at assert(a == t)\n +// Info 1180: Contract invariant(s) for :C:\n(((address(this) + ((- 1) * t)) <= 0) && ((address(this) + ((- 1) * t)) >= 0))\nReentrancy property(ies) for :C:\n((!((t + ((- 1) * address(this))) = 0) || ( <= 0)) && (!((t + ((- 1) * address(this))) <= 0) || ((t' + ((- 1) * address(this))) <= 0)) && (!((t + ((- 1) * address(this))) >= 0) || ((address(this) + ((- 1) * t')) <= 0)))\n((!( >= 2) || !((t + ((- 1) * address(this))) = 0)) && (!((t + ((- 1) * address(this))) <= 0) || ((t' + ((- 1) * address(this))) <= 0)) && (!((t + ((- 1) * address(this))) >= 0) || ((address(this) + ((- 1) * t')) <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(address(this) == t)\n = 2 -> Assertion failed at assert(a == t)\n diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/branches_in_modifiers_2.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/branches_in_modifiers_2.sol index 9765fc1f91..4241fa9e29 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/branches_in_modifiers_2.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/branches_in_modifiers_2.sol @@ -44,5 +44,5 @@ contract C { // SMTEngine: all // ---- // Warning 6328: (255-269): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.test()\n C.reset_if_overflow() -- internal call -// Warning 6328: (502-519): CHC: Assertion violation happens here. +// Warning 6328: (502-519): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\noldx = 1\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.set(1)\nState: x = 1\nC.test()\n C.reset_if_overflow() -- internal call // Warning 6328: (615-629): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.set(10)\nState: x = 10\nC.test()\n C.reset_if_overflow() -- internal call diff --git a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_compare_hashes.sol b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_compare_hashes.sol index a49aeac090..79b30a1239 100644 --- a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_compare_hashes.sol +++ b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_compare_hashes.sol @@ -12,6 +12,12 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (150-164): CHC: Assertion violation happens here. -// Warning 6328: (168-182): CHC: Assertion violation happens here. -// Warning 6328: (186-200): CHC: Assertion violation happens here. +// Warning 1218: (150-164): CHC: Error trying to invoke SMT solver. +// Warning 1218: (168-182): CHC: Error trying to invoke SMT solver. +// Warning 1218: (186-200): CHC: Error trying to invoke SMT solver. +// Warning 6328: (150-164): CHC: Assertion violation might happen here. +// Warning 6328: (168-182): CHC: Assertion violation might happen here. +// Warning 6328: (186-200): CHC: Assertion violation might happen here. +// Warning 4661: (150-164): BMC: Assertion violation happens here. +// Warning 4661: (168-182): BMC: Assertion violation happens here. +// Warning 4661: (186-200): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_not_same.sol b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_not_same.sol index a8c6199d0f..59a011f240 100644 --- a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_not_same.sol +++ b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_not_same.sol @@ -12,4 +12,6 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (196-210): CHC: Assertion violation happens here. +// Warning 1218: (196-210): CHC: Error trying to invoke SMT solver. +// Warning 6328: (196-210): CHC: Assertion violation might happen here. +// Warning 4661: (196-210): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_input_over_state_same_output.sol b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_input_over_state_same_output.sol index 228f9d5809..94eedd5991 100644 --- a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_input_over_state_same_output.sol +++ b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_input_over_state_same_output.sol @@ -37,4 +37,15 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1180: Contract invariant(s) for :C:\n(((erc + ((- 1) * ecrecover(tuple_constructor(h, v, r, s)))) <= 0) && ((erc + ((- 1) * ecrecover(tuple_constructor(h, v, r, s)))) >= 0))\n(((kec + ((- 1) * keccak256(data))) >= 0) && ((kec + ((- 1) * keccak256(data))) <= 0))\n(((rip + ((- 1) * ripemd160(data))) <= 0) && ((rip + ((- 1) * ripemd160(data))) >= 0))\n(((sha + ((- 1) * sha256(data))) <= 0) && ((sha + ((- 1) * sha256(data))) >= 0))\n +// Warning 1218: (544-563): CHC: Error trying to invoke SMT solver. +// Warning 1218: (567-586): CHC: Error trying to invoke SMT solver. +// Warning 1218: (590-609): CHC: Error trying to invoke SMT solver. +// Warning 1218: (613-632): CHC: Error trying to invoke SMT solver. +// Warning 6328: (544-563): CHC: Assertion violation might happen here. +// Warning 6328: (567-586): CHC: Assertion violation might happen here. +// Warning 6328: (590-609): CHC: Assertion violation might happen here. +// Warning 6328: (613-632): CHC: Assertion violation might happen here. +// Warning 4661: (544-563): BMC: Assertion violation happens here. +// Warning 4661: (567-586): BMC: Assertion violation happens here. +// Warning 4661: (590-609): BMC: Assertion violation happens here. +// Warning 4661: (613-632): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_mutex.sol b/test/libsolidity/smtCheckerTests/external_calls/call_mutex.sol index a310939246..e85eb00aab 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_mutex.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_mutex.sol @@ -23,4 +23,4 @@ contract C { // SMTEngine: all // ---- // Warning 9302: (218-234): Return value of low-level calls not used. -// Info 1180: Reentrancy property(ies) for :C:\n((!lock || ((x' + ((- 1) * x)) = 0)) && ( <= 0) && (lock' || !lock))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(y == x)\n +// Info 1180: Reentrancy property(ies) for :C:\n((lock' || !lock) && ( <= 0) && (!lock || ((x' + ((- 1) * x)) = 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(y == x)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_reentrancy_view.sol b/test/libsolidity/smtCheckerTests/external_calls/call_reentrancy_view.sol index f0f844fff3..87a9e22614 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_reentrancy_view.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_reentrancy_view.sol @@ -15,4 +15,4 @@ contract C { // Warning 2519: (106-112): This declaration shadows an existing declaration. // Warning 2072: (106-112): Unused local variable. // Warning 2072: (114-131): Unused local variable. -// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n((!(x <= 0) || (x' <= 0)) && (( <= 0) || !(x <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n +// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n((!(x <= 0) || (x' <= 0)) && (!(x <= 0) || ( <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/call_safe.sol index 09d3a25922..f4f9d15ad4 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_safe.sol @@ -10,4 +10,4 @@ contract C { // ---- // Warning 2072: (57-63): Unused local variable. // Warning 2072: (65-82): Unused local variable. -// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n((!(x <= 0) || (x' <= 0)) && (( <= 0) || !(x <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n +// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n((!(x <= 0) || ( <= 0)) && (!(x <= 0) || (x' <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol index 2569802255..f9293f6930 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol @@ -11,8 +11,6 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 9302: (96-117): Return value of low-level calls not used. -// Warning 1218: (175-211): CHC: Error trying to invoke SMT solver. // Warning 6328: (121-156): CHC: Assertion violation might happen here. -// Warning 6328: (175-211): CHC: Assertion violation might happen here. +// Warning 6328: (175-211): CHC: Assertion violation happens here.\nCounterexample:\n\ni = 0x0\n\nTransaction trace:\nC.constructor()\nC.g(0x0)\n i.call{value: 10}("") -- untrusted external call // Warning 4661: (121-156): BMC: Assertion violation happens here. -// Warning 4661: (175-211): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_1.sol index 06390b12ca..c52e0773fb 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_this_with_value_1.sol @@ -11,4 +11,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (157-192): CHC: Assertion violation happens here. +// Warning 6328: (157-192): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.g()\n C.h() -- trusted external call diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state.sol index 317400e1d1..2468a1a72d 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state.sol @@ -36,4 +36,4 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 6328: (495-532): CHC: Assertion violation happens here. -// Info 1180: Reentrancy property(ies) for :C:\n(((owner + ((- 1) * owner')) >= 0) && !( = 1) && ((owner + ((- 1) * owner')) <= 0))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(prevOwner == owner)\n = 3 -> Assertion failed at assert(owner == address(0) || y != z)\n +// Info 1180: Reentrancy property(ies) for :C:\n(((owner + ((- 1) * owner')) <= 0) && !( = 1) && ((owner + ((- 1) * owner')) >= 0))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(prevOwner == owner)\n = 3 -> Assertion failed at assert(owner == address(0) || y != z)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol index e5259c6c44..508047c39b 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol @@ -41,4 +41,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1180: Contract invariant(s) for :C:\n((insidef || (z <= 0)) && (y <= 0))\nReentrancy property(ies) for :C:\n((!insidef || !( >= 2)) && (!(y <= 0) || (y' <= 0)) && (insidef' || !insidef))\n((!insidef || !( >= 3)) && (insidef' || !insidef))\n = 0 -> no errors\n = 2 -> Assertion failed at assert(z == y)\n = 3 -> Assertion failed at assert(prevOwner == owner)\n +// Info 1180: Contract invariant(s) for :C:\n((insidef || (z <= 0)) && (y <= 0))\nReentrancy property(ies) for :C:\n((!insidef || !( >= 2)) && (insidef' || !insidef) && (!(y <= 0) || (y' <= 0)))\n((!insidef || !( >= 3)) && (insidef' || !insidef))\n = 0 -> no errors\n = 2 -> Assertion failed at assert(z == y)\n = 3 -> Assertion failed at assert(prevOwner == owner)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe.sol index 32aa483a7d..d871d6e134 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe.sol @@ -35,7 +35,5 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 1218: (366-392): CHC: Error trying to invoke SMT solver. // Warning 6328: (348-362): CHC: Assertion violation happens here. -// Warning 6328: (366-392): CHC: Assertion violation might happen here. -// Warning 4661: (366-392): BMC: Assertion violation happens here. +// Warning 6328: (366-392): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_1.sol index adde1eb61c..5683a5248b 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_1.sol @@ -16,4 +16,6 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (206-220): CHC: Assertion violation happens here.\nCounterexample:\nlocked = false\ntarget = 0x0\n\nTransaction trace:\nC.constructor()\nState: locked = true\nC.call(0x0)\n D(target).e() -- untrusted external call, synthesized as:\n C.broken() -- reentrant call +// Warning 1218: (206-220): CHC: Error trying to invoke SMT solver. +// Warning 6328: (206-220): CHC: Assertion violation might happen here. +// Warning 4661: (206-220): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_crypto.sol b/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_crypto.sol index 2a79e6c4d2..46e8ac1487 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_crypto.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_crypto.sol @@ -27,6 +27,9 @@ contract C { // SMTEngine: all // SMTIgnoreInv: yes // ---- +// Warning 1218: (264-283): CHC: Error trying to invoke SMT solver. // Warning 1218: (302-333): CHC: Error trying to invoke SMT solver. +// Warning 6328: (264-283): CHC: Assertion violation might happen here. // Warning 6328: (302-333): CHC: Assertion violation might happen here. +// Warning 4661: (264-283): BMC: Assertion violation happens here. // Warning 4661: (302-333): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_single_inc.sol b/test/libsolidity/smtCheckerTests/external_calls/external_single_inc.sol index 0b944acb2b..994fbde16f 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_single_inc.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_single_inc.sol @@ -23,4 +23,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (223-240): CHC: Assertion violation happens here. +// Warning 6328: (223-240): CHC: Assertion violation happens here.\nCounterexample:\nx = 1, y = 1, d = 0\noldX = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, y = 0, d = 0\nC.inc()\nState: x = 0, y = 1, d = 0\nC.f()\n d.d() -- untrusted external call, synthesized as:\n C.inc() -- reentrant call diff --git a/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol b/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol index ace2d56f29..19dd010a5f 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol @@ -18,4 +18,4 @@ contract C // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n!( = 1)\n((!(x <= 0) || !( >= 2)) && (!(x <= 0) || (x' <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == y)\n = 2 -> Assertion failed at assert(x == y)\n +// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n!( = 1)\n((!( >= 2) || !(x <= 0)) && (!(x <= 0) || (x' <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == y)\n = 2 -> Assertion failed at assert(x == y)\n diff --git a/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol b/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol index 5efcb2da1b..3a3b295e45 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol @@ -25,4 +25,4 @@ contract C // SMTIgnoreOS: macos // ---- // Warning 6328: (234-253): CHC: Assertion violation happens here. -// Info 1180: Reentrancy property(ies) for :C:\n!( = 1)\n((!((map[1] + ((- 1) * map[0])) <= 0) || ((map'[1] + ((- 1) * map'[0])) <= 0)) && !( = 2) && (!((map[1] + ((- 1) * map[0])) >= 0) || ((map'[0] + ((- 1) * map'[1])) <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(map[0] == map[1])\n = 2 -> Assertion failed at assert(map[0] == map[1])\n = 3 -> Assertion failed at assert(map[0] == 0)\n +// Info 1180: Reentrancy property(ies) for :C:\n!( = 1)\n((!((map[1] + ((- 1) * map[0])) >= 0) || ((map'[0] + ((- 1) * map'[1])) <= 0)) && !( = 2) && (!((map[1] + ((- 1) * map[0])) <= 0) || ((map'[1] + ((- 1) * map'[0])) <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(map[0] == map[1])\n = 2 -> Assertion failed at assert(map[0] == map[1])\n = 3 -> Assertion failed at assert(map[0] == 0)\n diff --git a/test/libsolidity/smtCheckerTests/functions/getters/struct_3.sol b/test/libsolidity/smtCheckerTests/functions/getters/struct_3.sol index ea433b7863..b5cdcc32dd 100644 --- a/test/libsolidity/smtCheckerTests/functions/getters/struct_3.sol +++ b/test/libsolidity/smtCheckerTests/functions/getters/struct_3.sol @@ -21,5 +21,12 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (307-326): CHC: Assertion violation happens here. -// Info 1180: Contract invariant(s) for :C:\n!(m.b.length <= 2)\n +// Warning 1218: (273-277): CHC: Error trying to invoke SMT solver. +// Warning 1218: (281-287): CHC: Error trying to invoke SMT solver. +// Warning 1218: (314-318): CHC: Error trying to invoke SMT solver. +// Warning 1218: (307-326): CHC: Error trying to invoke SMT solver. +// Warning 6368: (273-277): CHC: Out of bounds access might happen here. +// Warning 6368: (281-287): CHC: Out of bounds access might happen here. +// Warning 6368: (314-318): CHC: Out of bounds access might happen here. +// Warning 6328: (307-326): CHC: Assertion violation might happen here. +// Warning 4661: (307-326): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/virtual_function_called_by_constructor.sol b/test/libsolidity/smtCheckerTests/functions/virtual_function_called_by_constructor.sol index 0117f9b49d..e30a5e7438 100644 --- a/test/libsolidity/smtCheckerTests/functions/virtual_function_called_by_constructor.sol +++ b/test/libsolidity/smtCheckerTests/functions/virtual_function_called_by_constructor.sol @@ -27,4 +27,4 @@ contract C is A { // ---- // Warning 6328: (199-214): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nA.constructor()\nState: x = 2\nA.i() // Warning 6328: (387-401): CHC: Assertion violation happens here.\nCounterexample:\nx = 10\n\nTransaction trace:\nC.constructor()\nState: x = 10\nC.i() -// Info 1180: Contract invariant(s) for :A:\n(!(x <= 1) && !(x >= 3))\nContract invariant(s) for :C:\n(!(x >= 11) && !(x <= 9))\n +// Info 1180: Contract invariant(s) for :A:\n(!(x <= 1) && !(x >= 3))\nContract invariant(s) for :C:\n(!(x <= 9) && !(x >= 11))\n diff --git a/test/libsolidity/smtCheckerTests/natspec/unsafe_assert_remains_unsafe.sol b/test/libsolidity/smtCheckerTests/natspec/unsafe_assert_remains_unsafe.sol index 1bb6caa423..6202478a69 100644 --- a/test/libsolidity/smtCheckerTests/natspec/unsafe_assert_remains_unsafe.sol +++ b/test/libsolidity/smtCheckerTests/natspec/unsafe_assert_remains_unsafe.sol @@ -24,4 +24,4 @@ contract C { // SMTEngine: chc // ---- // Warning 6328: (74-87): CHC: Assertion violation happens here.\nCounterexample:\nx = 0, y = 0\n_x = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, y = 0\nC.g(0)\n C.f1(0) -- internal call -// Warning 6328: (117-130): CHC: Assertion violation happens here.\nCounterexample:\nx = 1, y = 0\n_x = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, y = 0\nC.g(0)\n C.f1(0) -- internal call\n C.f2(0) -- internal call +// Warning 6328: (117-130): CHC: Assertion violation happens here.\nCounterexample:\nx = 0, y = 0\n_x = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, y = 0\nC.g(0)\n C.f1(0) -- internal call\n C.f2(0) -- internal call diff --git a/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol b/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol index e4b7646861..18869ee3a3 100644 --- a/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol +++ b/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol @@ -30,4 +30,4 @@ contract A { // ---- // Warning 6328: (AASource:159-178): CHC: Assertion violation happens here.\nCounterexample:\nx = (- 1), y = (- 2)\n\nTransaction trace:\nA.constructor()\nState: x = 0, y = 0\nA.a()\nState: x = (- 2), y = (- 2)\nA.a() // Warning 6328: (AASource:370-386): CHC: Assertion violation happens here.\nCounterexample:\nx = 8, y = (- 2)\n\nTransaction trace:\nA.constructor()\nState: x = 0, y = 0\nA.a() -// Info 1180: Contract invariant(s) for AASource:A:\n(((x = (- 2)) && (y = (- 2))) || ((x = 0) && (y = 0)))\n(((x = 0) && (y = 0)) || ((x = (- 2)) && (y = (- 2))))\n +// Info 1180: Contract invariant(s) for AASource:A:\n(((x = 0) && (y = 0)) || ((x = (- 2)) && (y = (- 2))))\n diff --git a/test/libsolidity/smtCheckerTests/operators/compound_add_array_index.sol b/test/libsolidity/smtCheckerTests/operators/compound_add_array_index.sol index 4068ad2b96..424baf927a 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_add_array_index.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_add_array_index.sol @@ -19,4 +19,4 @@ contract C // ==== // SMTEngine: all // ---- -// Warning 6328: (262-284): CHC: Assertion violation happens here.\nCounterexample:\narray = [200, 0]\nx = 0\np = 0\n\nTransaction trace:\nC.constructor()\nState: array = [0, 0]\nC.f(0, 0) +// Warning 6328: (262-284): CHC: Assertion violation happens here.\nCounterexample:\narray = [299, 0]\nx = 99\np = 0\n\nTransaction trace:\nC.constructor()\nState: array = [0, 0]\nC.f(99, 0) diff --git a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_string_literal_3.sol b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_string_literal_3.sol index 3ac248fb22..b2d56cb128 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_string_literal_3.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_string_literal_3.sol @@ -18,4 +18,5 @@ contract C { // SMTEngine: all // ---- // Warning 6328: (229-276): CHC: Assertion violation happens here.\nCounterexample:\n\ny = 0x6062606464666060606260646466606060626064646660606062606464666060\nz = 0x6062606464666060606260646466606060626064646660606062606464666060\n\nTransaction trace:\nC.constructor()\nC.f() -// Warning 6328: (394-437): CHC: Assertion violation happens here.\nCounterexample:\n\ny = 0x63666566676e616263666566676e616263666566676e616263666566676e6162\nz = 0x63666566676e616263666566676e616263666566676e616263666566676e6162\n\nTransaction trace:\nC.constructor()\nC.f() +// Warning 6328: (394-437): CHC: Assertion violation might happen here. +// Warning 4661: (394-437): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_5.sol b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_5.sol index dd467f8532..24be3cd8ea 100644 --- a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_5.sol +++ b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_5.sol @@ -25,6 +25,4 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 2072: (249-255): Unused local variable. -// Warning 1218: (271-295): CHC: Error trying to invoke SMT solver. -// Warning 6328: (271-295): CHC: Assertion violation might happen here. -// Warning 4661: (271-295): BMC: Assertion violation happens here. +// Warning 6328: (271-295): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_6.sol b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_6.sol index 3b89e1afb2..1affbb6ca0 100644 --- a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_6.sol +++ b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_6.sol @@ -25,4 +25,4 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 2072: (255-261): Unused local variable. -// Info 1180: Reentrancy property(ies) for :C:\n((!(x' <= 0) || ((x' + ((- 1) * x)) = 0)) && ( <= 0) && (!(x' >= 3) || ((x' + ((- 1) * x)) = 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 2 || x == 1)\n +// Info 1180: Reentrancy property(ies) for :C:\n((!(x' >= 3) || (a' = a)) && (!(x' <= 0) || !(x >= 2)) && ( <= 0) && (!(x <= 2) || !(x' >= 3)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 2 || x == 1)\n diff --git a/test/libsolidity/smtCheckerTests/operators/slice_default_start.sol b/test/libsolidity/smtCheckerTests/operators/slice_default_start.sol index a4dba47bcd..2dcb635193 100644 --- a/test/libsolidity/smtCheckerTests/operators/slice_default_start.sol +++ b/test/libsolidity/smtCheckerTests/operators/slice_default_start.sol @@ -11,5 +11,6 @@ contract C { // SMTEngine: all // ---- // Warning 6328: (150-182): CHC: Assertion violation might happen here. -// Warning 6328: (186-218): CHC: Assertion violation happens here. +// Warning 6328: (186-218): CHC: Assertion violation might happen here. // Warning 4661: (150-182): BMC: Assertion violation happens here. +// Warning 4661: (186-218): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol b/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol index ee57f069d4..c26e64fccb 100644 --- a/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol +++ b/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol @@ -21,7 +21,6 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 4984: (112-115): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 3944: (181-184): CHC: Underflow (resulting value less than 0) might happen here. // Warning 6368: (259-263): CHC: Out of bounds access happens here.\nCounterexample:\na = [0], l = 1\n = 0\n\nTransaction trace:\nC.constructor()\nState: a = [], l = 0\nC.p()\nState: a = [0], l = 1\nC.r() +// Info 1180: Contract invariant(s) for :C:\n((a.length + ((- 1) * l)) <= 0)\n // Warning 2661: (112-115): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (181-184): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/overflow/unsigned_mul_overflow.sol b/test/libsolidity/smtCheckerTests/overflow/unsigned_mul_overflow.sol index 045fcbff86..0a6d85a7ea 100644 --- a/test/libsolidity/smtCheckerTests/overflow/unsigned_mul_overflow.sol +++ b/test/libsolidity/smtCheckerTests/overflow/unsigned_mul_overflow.sol @@ -6,4 +6,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 4984: (80-85): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\n\nx = 2\ny = 57896044618658097711785492504343953926634992332820282019728792003956564819968\n = 0\n\nTransaction trace:\nC.constructor()\nC.f(2, 57896044618658097711785492504343953926634992332820282019728792003956564819968) +// Warning 4984: (80-85): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\n\nx = 57896044618658097711785492504343953926634992332820282019728792003956564819968\ny = 2\n = 0\n\nTransaction trace:\nC.constructor()\nC.f(57896044618658097711785492504343953926634992332820282019728792003956564819968, 2) diff --git a/test/libsolidity/smtCheckerTests/special/abi_decode_simple.sol b/test/libsolidity/smtCheckerTests/special/abi_decode_simple.sol index 618f762767..a015aba72a 100644 --- a/test/libsolidity/smtCheckerTests/special/abi_decode_simple.sol +++ b/test/libsolidity/smtCheckerTests/special/abi_decode_simple.sol @@ -13,4 +13,4 @@ contract C { // Warning 2072: (82-86): Unused local variable. // Warning 2072: (140-150): Unused local variable. // Warning 2072: (152-156): Unused local variable. -// Warning 6328: (220-236): CHC: Assertion violation happens here.\nCounterexample:\n\na1 = 2437\nb1 = 0x0a\nc1 = 9\na2 = 2437\nb2 = 0x0a\nc2 = 9\n\nTransaction trace:\nC.constructor()\nC.f(data) +// Warning 6328: (220-236): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol b/test/libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol index ad958fe958..4c3682c60a 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol @@ -20,4 +20,4 @@ contract C { // ==== // SMTEngine: chc // ---- -// Warning 6328: (343-377): CHC: Assertion violation happens here.\nCounterexample:\ngas = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: gas = 0, origin = 0x0\nC.f(){ tx.gasprice: 0, tx.origin: 0x0 }\n C.g() -- internal call +// Warning 6328: (343-377): CHC: Assertion violation happens here.\nCounterexample:\ngas = 0, origin = 0x52f7\n\nTransaction trace:\nC.constructor()\nState: gas = 0, origin = 0x0\nC.f(){ tx.gasprice: 0, tx.origin: 0x52f7 }\n C.g() -- internal call diff --git a/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_1.sol b/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_1.sol index 50260aa3d2..71608eabd3 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_1.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_1.sol @@ -13,4 +13,4 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Warning 6328: (135-169): CHC: Assertion violation happens here.\nCounterexample:\n\n_i = 0\nx = 841\n\nTransaction trace:\nC.constructor()\nC.g(0){ msg.value: 38 }\n _i.f() -- untrusted external call, synthesized as:\n C.g(0){ msg.value: 0 } -- reentrant call\n _i.f() -- untrusted external call +// Warning 6328: (135-169): CHC: Assertion violation happens here.\nCounterexample:\n\n_i = 0\nx = 1236\n\nTransaction trace:\nC.constructor()\nC.g(0){ msg.value: 38 }\n _i.f() -- untrusted external call, synthesized as:\n C.g(0){ msg.value: 1 } -- reentrant call\n _i.f() -- untrusted external call diff --git a/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_2.sol b/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_2.sol index aaddec5b5a..206d95c466 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_2.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_vars_reentrancy_2.sol @@ -13,4 +13,4 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Warning 6328: (157-191): CHC: Assertion violation happens here.\nCounterexample:\n\n_i = 0\nx = 2537\n\nTransaction trace:\nC.constructor()\nC.g(0){ msg.value: 38 }\n _i.f{ value: 100 }() -- untrusted external call +// Warning 6328: (157-191): CHC: Assertion violation happens here.\nCounterexample:\n\n_i = 0\nx = 101\n\nTransaction trace:\nC.constructor()\nC.g(0){ msg.value: 69 }\n _i.f{ value: 100 }() -- untrusted external call diff --git a/test/libsolidity/smtCheckerTests/try_catch/try_public_var_mapping.sol b/test/libsolidity/smtCheckerTests/try_catch/try_public_var_mapping.sol index 0854dedd17..2caae5e164 100644 --- a/test/libsolidity/smtCheckerTests/try_catch/try_public_var_mapping.sol +++ b/test/libsolidity/smtCheckerTests/try_catch/try_public_var_mapping.sol @@ -21,5 +21,5 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Warning 6328: (280-300): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.f() +// Warning 6328: (280-300): CHC: Assertion violation happens here. // Info 1180: Contract invariant(s) for :C:\n!(m[0].length <= 1)\n(!(m[0][1] >= 43) && !(m[0][1] <= 41))\n diff --git a/test/libsolidity/smtCheckerTests/types/abi_type_type_1.sol b/test/libsolidity/smtCheckerTests/types/abi_type_type_1.sol index d4207bc860..3effe1c05e 100644 --- a/test/libsolidity/smtCheckerTests/types/abi_type_type_1.sol +++ b/test/libsolidity/smtCheckerTests/types/abi_type_type_1.sol @@ -7,4 +7,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (107-128): CHC: Assertion violation happens here.\nCounterexample:\n\na = true\nx = 1\n\nTransaction trace:\nC.constructor()\nC.f(d) +// Warning 6328: (107-128): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/types/address_staticcall.sol b/test/libsolidity/smtCheckerTests/types/address_staticcall.sol index 11b862a10c..9d00904ad7 100644 --- a/test/libsolidity/smtCheckerTests/types/address_staticcall.sol +++ b/test/libsolidity/smtCheckerTests/types/address_staticcall.sol @@ -10,7 +10,8 @@ contract C assert(success); assert(x == 0); assert(map[0] == 0); - assert(localMap[0] == 0); + // Disabled because of Spacer's seg fault + //assert(localMap[0] == 0); } } // ==== @@ -18,6 +19,7 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- +// Warning 2072: (127-166): Unused local variable. // Warning 2072: (191-207): Unused local variable. // Warning 6328: (233-248): CHC: Assertion violation happens here. -// Info 1180: Reentrancy property(ies) for :C:\n!( >= 2)\n!( >= 3)\n!( >= 4)\n = 0 -> no errors\n = 1 -> Assertion failed at assert(success)\n = 2 -> Assertion failed at assert(x == 0)\n = 3 -> Assertion failed at assert(map[0] == 0)\n = 4 -> Assertion failed at assert(localMap[0] == 0)\n +// Info 1180: Reentrancy property(ies) for :C:\n!( >= 2)\n!( >= 3)\n = 0 -> no errors\n = 1 -> Assertion failed at assert(success)\n = 2 -> Assertion failed at assert(x == 0)\n = 3 -> Assertion failed at assert(map[0] == 0)\n diff --git a/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol index 44daa89128..ce35a65054 100644 --- a/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol +++ b/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol @@ -6,4 +6,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (66-80): CHC: Assertion violation happens here.\nCounterexample:\n\nx = true\ny = false\n\nTransaction trace:\nC.constructor()\nC.f(true, false) +// Warning 6328: (66-80): CHC: Assertion violation happens here.\nCounterexample:\n\nx = false\ny = true\n\nTransaction trace:\nC.constructor()\nC.f(false, true) diff --git a/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol b/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol index b55293231f..320d7dd10e 100644 --- a/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol +++ b/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol @@ -32,6 +32,5 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Warning 6368: (374-381): CHC: Out of bounds access might happen here. // Warning 6368: (456-462): CHC: Out of bounds access happens here. -// Info 1180: Contract invariant(s) for :C:\n!(a.length <= 4)\n +// Info 1180: Contract invariant(s) for :C:\n!(a.length <= 4)\n!(a[2].length <= 2)\n diff --git a/test/libsolidity/smtCheckerTests/userTypes/user_abi_1.sol b/test/libsolidity/smtCheckerTests/userTypes/user_abi_1.sol index 1d31cbe3d2..e4a68df6b4 100644 --- a/test/libsolidity/smtCheckerTests/userTypes/user_abi_1.sol +++ b/test/libsolidity/smtCheckerTests/userTypes/user_abi_1.sol @@ -11,4 +11,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (188-212): CHC: Assertion violation happens here.\nCounterexample:\n\ny = 2437\n\nTransaction trace:\nC.constructor()\nC.f(data) +// Warning 6328: (188-212): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/userTypes/user_abi_2.sol b/test/libsolidity/smtCheckerTests/userTypes/user_abi_2.sol index a4c4a3a29e..358e5404ea 100644 --- a/test/libsolidity/smtCheckerTests/userTypes/user_abi_2.sol +++ b/test/libsolidity/smtCheckerTests/userTypes/user_abi_2.sol @@ -11,4 +11,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (192-226): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.f(data) +// Warning 6328: (192-226): CHC: Assertion violation happens here. From 0c34d9df88434f48cee3b6b3f97e7097eb1a747f Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Tue, 23 Nov 2021 18:54:44 +0100 Subject: [PATCH 0027/1704] Adjust tests for nondeterminism --- .../array_members/push_storage_ref_unsafe_aliasing.sol | 7 ++++--- .../smtCheckerTests/external_calls/call_safe.sol | 2 +- .../external_calls/external_single_inc.sol | 3 ++- .../smtCheckerTests/functions/functions_external_1.sol | 3 +-- test/libsolidity/smtCheckerTests/try_catch/try_4.sol | 9 +++------ 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/test/libsolidity/smtCheckerTests/array_members/push_storage_ref_unsafe_aliasing.sol b/test/libsolidity/smtCheckerTests/array_members/push_storage_ref_unsafe_aliasing.sol index 87b9d92bf3..a8669fb601 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_storage_ref_unsafe_aliasing.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_storage_ref_unsafe_aliasing.sol @@ -13,7 +13,8 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreOS: macos +// SMTIgnoreCex: yes // ---- -// Warning 6368: (188-192): CHC: Out of bounds access happens here.\nCounterexample:\na = []\nb = [32]\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.f() -// Warning 6368: (188-195): CHC: Out of bounds access happens here.\nCounterexample:\n\nb = [32]\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.f() -// Warning 6328: (181-202): CHC: Assertion violation happens here.\nCounterexample:\n\nb = [32]\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.f() +// Warning 6368: (188-192): CHC: Out of bounds access happens here. +// Warning 6368: (188-195): CHC: Out of bounds access happens here. +// Warning 6328: (181-202): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/call_safe.sol index f4f9d15ad4..e4e3abc24f 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_safe.sol @@ -7,7 +7,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreInv: yes // ---- // Warning 2072: (57-63): Unused local variable. // Warning 2072: (65-82): Unused local variable. -// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n((!(x <= 0) || ( <= 0)) && (!(x <= 0) || (x' <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_single_inc.sol b/test/libsolidity/smtCheckerTests/external_calls/external_single_inc.sol index 994fbde16f..7b73311a0b 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_single_inc.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_single_inc.sol @@ -22,5 +22,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreCex: yes // ---- -// Warning 6328: (223-240): CHC: Assertion violation happens here.\nCounterexample:\nx = 1, y = 1, d = 0\noldX = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, y = 0, d = 0\nC.inc()\nState: x = 0, y = 1, d = 0\nC.f()\n d.d() -- untrusted external call, synthesized as:\n C.inc() -- reentrant call +// Warning 6328: (223-240): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol b/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol index 19dd010a5f..3a87f34c9d 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol @@ -17,5 +17,4 @@ contract C // ==== // SMTEngine: all // SMTIgnoreOS: macos -// ---- -// Info 1180: Contract invariant(s) for :C:\n(x <= 0)\nReentrancy property(ies) for :C:\n!( = 1)\n((!( >= 2) || !(x <= 0)) && (!(x <= 0) || (x' <= 0)))\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == y)\n = 2 -> Assertion failed at assert(x == y)\n +// SMTIgnoreInv: yes diff --git a/test/libsolidity/smtCheckerTests/try_catch/try_4.sol b/test/libsolidity/smtCheckerTests/try_catch/try_4.sol index 0abf62df8e..289f3943d7 100644 --- a/test/libsolidity/smtCheckerTests/try_catch/try_4.sol +++ b/test/libsolidity/smtCheckerTests/try_catch/try_4.sol @@ -14,7 +14,7 @@ contract C { function f() public { x = 0; try d.d() { - assert(x == 0); // should fail, x can be anything here + //assert(x == 0); // should fail, x can be anything here } catch { assert(x == 0); // should hold, all changes to x has been reverted assert(x == 1); // should fail @@ -25,8 +25,5 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 1218: (178-192): CHC: Error trying to invoke SMT solver. -// Warning 6328: (178-192): CHC: Assertion violation might happen here. -// Warning 6328: (318-332): CHC: Assertion violation happens here. -// Info 1180: Reentrancy property(ies) for :C:\n!( = 2)\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n = 2 -> Assertion failed at assert(x == 0)\n = 3 -> Assertion failed at assert(x == 1)\n -// Warning 4661: (178-192): BMC: Assertion violation happens here. +// Warning 6328: (320-334): CHC: Assertion violation happens here. +// Info 1180: Reentrancy property(ies) for :C:\n!( = 1)\n = 0 -> no errors\n = 1 -> Assertion failed at assert(x == 0)\n = 2 -> Assertion failed at assert(x == 1)\n From 6cff73af71542fe6a00975b53b3380c234295fac Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Tue, 23 Nov 2021 18:59:26 +0100 Subject: [PATCH 0028/1704] update osx z3 hash --- .circleci/osx_install_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index a973988a6e..36d3367746 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -65,7 +65,7 @@ then z3_dir="z3-${z3_version}-x64-osx-10.16" z3_package="${z3_dir}.zip" wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_package}" - validate_checksum "$z3_package" a1f6ef3c99456147c4d3f2652dc6bc90951c4ab3fe7741a255eb794f0ab8938c + validate_checksum "$z3_package" 191b26be2b617b2dffffce139d77abcd7e584859efbc10a58d01a1d7830697a4 unzip "$z3_package" rm "$z3_package" cp "${z3_dir}/bin/libz3.a" /usr/local/lib From a2588533e504c2a46827fe3ed87362f2bd7c4f32 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Wed, 24 Nov 2021 11:38:22 +0100 Subject: [PATCH 0029/1704] macos nondeterminism --- .../array_members/length_1d_struct_array_2d_1.sol | 1 + .../libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol | 1 + .../smtCheckerTests/blockchain_state/balance_receive_4.sol | 1 + .../blockchain_state/balance_receive_ext_calls.sol | 1 + .../branches_with_return/branches_in_modifiers_2.sol | 1 + .../control_flow/branches_with_return/triple_nested_if.sol | 1 + .../external_calls/external_call_with_value_3.sol | 1 + .../external_hash_known_code_state_reentrancy_unsafe.sol | 1 + .../operators/assignment_module_contract_member_variable.sol | 1 + .../smtCheckerTests/operators/compound_add_array_index.sol | 1 + .../smtCheckerTests/operators/compound_add_mapping.sol | 1 + .../smtCheckerTests/operators/compound_assignment_division_3.sol | 1 + .../smtCheckerTests/operators/compound_bitwise_or_int_1.sol | 1 + .../libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol | 1 + .../libsolidity/smtCheckerTests/userTypes/multisource_module.sol | 1 + 15 files changed, 15 insertions(+) diff --git a/test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_2d_1.sol b/test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_2d_1.sol index 71571d9448..ddda215df8 100644 --- a/test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_2d_1.sol +++ b/test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_2d_1.sol @@ -20,5 +20,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Info 1180: Contract invariant(s) for :C:\n!(s1.arr.length <= 0)\n!(s2.arr.length <= 0)\n(((s2.arr[0].length + ((- 1) * s1.arr[0].length)) <= 0) && ((s1.arr[0].length + ((- 1) * s2.arr[0].length)) <= 0))\n diff --git a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol index 5920a4e747..0d16306b72 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_1d.sol @@ -17,5 +17,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (199-229): CHC: Assertion violation happens here.\nCounterexample:\nb = [1]\n\nTransaction trace:\nC.constructor()\nState: b = []\nC.g() diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_4.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_4.sol index 3e3e564317..4fa420ff16 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_4.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_4.sol @@ -11,6 +11,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 4984: (82-85): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 4984: (154-160): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls.sol index 1ee90e41d0..96223b7e94 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_receive_ext_calls.sol @@ -12,6 +12,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 1218: (131-165): CHC: Error trying to invoke SMT solver. // Warning 6328: (131-165): CHC: Assertion violation might happen here. diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/branches_in_modifiers_2.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/branches_in_modifiers_2.sol index 4241fa9e29..f08a26bf70 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/branches_in_modifiers_2.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/branches_in_modifiers_2.sol @@ -42,6 +42,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (255-269): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.test()\n C.reset_if_overflow() -- internal call // Warning 6328: (502-519): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\noldx = 1\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.set(1)\nState: x = 1\nC.test()\n C.reset_if_overflow() -- internal call diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/triple_nested_if.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/triple_nested_if.sol index 09ee2b2b24..472ef8785e 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/triple_nested_if.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/triple_nested_if.sol @@ -17,5 +17,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Info 1180: Contract invariant(s) for :C:\n((c <= 0) && (a <= 0) && (b <= 0))\n diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol index d0e4c84aa6..2a535329ac 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol @@ -12,6 +12,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (150-183): CHC: Assertion violation might happen here. // Warning 6328: (202-236): CHC: Assertion violation happens here.\nCounterexample:\n\ni = 0\n\nTransaction trace:\nC.constructor()\nC.g(0)\n i.f{value: 20}() -- untrusted external call diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe.sol index d871d6e134..b3b43980ab 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe.sol @@ -34,6 +34,7 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTIgnoreOS: macos // ---- // Warning 6328: (348-362): CHC: Assertion violation happens here. // Warning 6328: (366-392): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol b/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol index 18869ee3a3..781476de25 100644 --- a/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol +++ b/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol @@ -27,6 +27,7 @@ contract A { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (AASource:159-178): CHC: Assertion violation happens here.\nCounterexample:\nx = (- 1), y = (- 2)\n\nTransaction trace:\nA.constructor()\nState: x = 0, y = 0\nA.a()\nState: x = (- 2), y = (- 2)\nA.a() // Warning 6328: (AASource:370-386): CHC: Assertion violation happens here.\nCounterexample:\nx = 8, y = (- 2)\n\nTransaction trace:\nA.constructor()\nState: x = 0, y = 0\nA.a() diff --git a/test/libsolidity/smtCheckerTests/operators/compound_add_array_index.sol b/test/libsolidity/smtCheckerTests/operators/compound_add_array_index.sol index 424baf927a..1c6e205d3f 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_add_array_index.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_add_array_index.sol @@ -18,5 +18,6 @@ contract C } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (262-284): CHC: Assertion violation happens here.\nCounterexample:\narray = [299, 0]\nx = 99\np = 0\n\nTransaction trace:\nC.constructor()\nState: array = [0, 0]\nC.f(99, 0) diff --git a/test/libsolidity/smtCheckerTests/operators/compound_add_mapping.sol b/test/libsolidity/smtCheckerTests/operators/compound_add_mapping.sol index 4169357d1b..ab133cefc9 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_add_mapping.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_add_mapping.sol @@ -11,5 +11,6 @@ contract C } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (165-185): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\np = 0\n\nTransaction trace:\nC.constructor()\nC.f(0, 0) diff --git a/test/libsolidity/smtCheckerTests/operators/compound_assignment_division_3.sol b/test/libsolidity/smtCheckerTests/operators/compound_assignment_division_3.sol index e762eb4be3..aa90aa2529 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_assignment_division_3.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_assignment_division_3.sol @@ -10,5 +10,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (162-181): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 2\np = 0\n\nTransaction trace:\nC.constructor()\nC.f(2, 0) diff --git a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_int_1.sol b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_int_1.sol index 8f7c69b2cd..fdd8c55cce 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_int_1.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_int_1.sol @@ -9,6 +9,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6368: (76-81): CHC: Out of bounds access might happen here. // Warning 6368: (76-84): CHC: Out of bounds access might happen here. diff --git a/test/libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol b/test/libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol index 4c3682c60a..95e3390b45 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_vars_chc_internal.sol @@ -19,5 +19,6 @@ contract C { } // ==== // SMTEngine: chc +// SMTIgnoreOS: macos // ---- // Warning 6328: (343-377): CHC: Assertion violation happens here.\nCounterexample:\ngas = 0, origin = 0x52f7\n\nTransaction trace:\nC.constructor()\nState: gas = 0, origin = 0x0\nC.f(){ tx.gasprice: 0, tx.origin: 0x52f7 }\n C.g() -- internal call diff --git a/test/libsolidity/smtCheckerTests/userTypes/multisource_module.sol b/test/libsolidity/smtCheckerTests/userTypes/multisource_module.sol index ee3277d1bc..491b8600d9 100644 --- a/test/libsolidity/smtCheckerTests/userTypes/multisource_module.sol +++ b/test/libsolidity/smtCheckerTests/userTypes/multisource_module.sol @@ -15,6 +15,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6328: (s2.sol:259-292): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.h()\n C.f(5) -- internal call\n C.f(5) -- internal call // Warning 6328: (s2.sol:346-377): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.h()\n C.f(5) -- internal call\n C.f(5) -- internal call\n C.g(1) -- internal call\n C.g(1) -- internal call From aa1a17072f5446dd553818c050bdbfd54aca635c Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Tue, 23 Nov 2021 12:03:43 +0100 Subject: [PATCH 0030/1704] Update z3 version in our docker files --- scripts/docker/buildpack-deps/Dockerfile.emscripten | 4 ++-- .../docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz | 4 ++-- scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index 9a3ca36af4..5f86b1e197 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -33,12 +33,12 @@ # Using $(em-config CACHE)/sysroot/usr seems to work, though, and still has cmake find the # dependencies automatically. FROM emscripten/emsdk:2.0.33 AS base -LABEL version="7" +LABEL version="8" ADD emscripten.jam /usr/src RUN set -ex; \ cd /usr/src; \ - git clone https://github.com/Z3Prover/z3.git -b z3-4.8.12 --depth 1 ; \ + git clone https://github.com/Z3Prover/z3.git -b z3-4.8.13 --depth 1 ; \ cd z3; \ mkdir build; \ cd build; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz index 48e9839dd9..0b1ed6125d 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="13" +LABEL version="14" ARG DEBIAN_FRONTEND=noninteractive @@ -61,7 +61,7 @@ RUN set -ex; \ # Z3 RUN set -ex; \ - git clone --depth 1 -b z3-4.8.12 https://github.com/Z3Prover/z3.git \ + git clone --depth 1 -b z3-4.8.13 https://github.com/Z3Prover/z3.git \ /usr/src/z3; \ cd /usr/src/z3; \ mkdir build; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 63f09e5138..8ed35d67e9 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="8" +LABEL version="9" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang index 1f96e41d5c..0ac9d4abf8 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="8" +LABEL version="9" ARG DEBIAN_FRONTEND=noninteractive From 6b69791f2bab4e543ec70882a6ea471ec6053462 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 24 Nov 2021 14:24:56 +0100 Subject: [PATCH 0031/1704] Disabling Clang-14 bitwise instead of logical warning in Hera build. --- .../docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz index 0b1ed6125d..64260c1b9c 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz @@ -109,7 +109,7 @@ RUN set -ex; \ cd hera; \ mkdir build; \ cd build; \ - cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="/usr" ..; \ + cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DCMAKE_CXX_FLAGS="-Wno-bitwise-instead-of-logical" -DCMAKE_INSTALL_PREFIX="/usr" ..; \ ninja; \ ninja install/strip; \ rm -rf /usr/src/hera From 1c8d430b8220733c41485d87e134865702a00a13 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 24 Nov 2021 17:55:52 +0100 Subject: [PATCH 0032/1704] Remove Hera as a dependency for oss-fuzz Docker image. --- .../Dockerfile.ubuntu1604.clang.ossfuzz | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz index 64260c1b9c..1d00eabce8 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz @@ -102,18 +102,6 @@ RUN set -ex; \ ninja install/strip; \ rm -rf /usr/src/evmone -# HERA -RUN set -ex; \ - cd /usr/src; \ - git clone --branch="v0.5.0" --depth 1 --recurse-submodules https://github.com/ewasm/hera.git; \ - cd hera; \ - mkdir build; \ - cd build; \ - cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DCMAKE_CXX_FLAGS="-Wno-bitwise-instead-of-logical" -DCMAKE_INSTALL_PREFIX="/usr" ..; \ - ninja; \ - ninja install/strip; \ - rm -rf /usr/src/hera - # gmp RUN set -ex; \ # Replace system installed libgmp static library From 26ac84300e3ab2206a931cb955911f4ca5d46254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 23 Nov 2021 17:09:50 +0100 Subject: [PATCH 0033/1704] CI: Extract workflow name without jq --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fb3abb37af..92c3d030fd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -51,7 +51,7 @@ commands: # Workflow name is not exposed as an env variable. Has to be queried from the API. # The name is not critical so if anything fails, use the raw workflow ID as a fallback. workflow_info=$(curl --silent "https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}") || true - workflow_name=$(echo "$workflow_info" | jq --raw-output .name || echo "$CIRCLE_WORKFLOW_ID") + workflow_name=$(echo "$workflow_info" | grep -E '"\s*name"\s*:\s*".*"' | cut -d \" -f 4 || echo "$CIRCLE_WORKFLOW_ID") [[ "<< parameters.event >>" == "failure" ]] && message=" ❌ [${workflow_name}] Job **${CIRCLE_JOB}** failed on **${CIRCLE_BRANCH}**. Please see [build ${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." [[ "<< parameters.event >>" == "success" ]] && message=" ✅ [${workflow_name}] Job **${CIRCLE_JOB}** succeeded on **${CIRCLE_BRANCH}**. Please see [build ${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL}) for details." From 674b1ecf3f78e61a17a2cd3fd6c6e8bf5d56b5ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 5 Nov 2021 17:38:25 +0100 Subject: [PATCH 0034/1704] CI: Change the default node version in t_ems_ext from 14 to latest --- .circleci/config.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fb3abb37af..398e73e49e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -946,8 +946,8 @@ jobs: type: integer default: 0 nodejs_version: - type: integer - default: 14 + type: string + default: latest docker: - image: circleci/node:<> # NOTE: Each external test does 3 separate compile&test runs @@ -1205,28 +1205,32 @@ workflows: name: t_ems_compile_ext_colony project: colony compile_only: 1 + nodejs_version: '14' - t_ems_ext: <<: *workflow_emscripten name: t_ems_compile_ext_gnosis project: gnosis compile_only: 1 + nodejs_version: '14' - t_ems_ext: <<: *workflow_emscripten name: t_ems_compile_ext_gnosis_v2 project: gnosis-v2 compile_only: 1 + nodejs_version: '14' - t_ems_ext: <<: *workflow_emscripten name: t_ems_compile_ext_zeppelin project: zeppelin compile_only: 1 + nodejs_version: '14' - t_ems_ext: <<: *workflow_emscripten name: t_ems_compile_ext_ens project: ens compile_only: 1 # NOTE: One of the dependencies (fsevents) fails to build its native extension on node.js 12+. - nodejs_version: 10 + nodejs_version: '10' # FIXME: Gnosis tests are pretty flaky right now. They often fail on CircleCI due to random ProviderError # and there are also other less frequent problems. See https://github.com/gnosis/safe-contracts/issues/216. @@ -1235,23 +1239,24 @@ workflows: # name: t_ems_test_ext_gnosis # project: gnosis # # NOTE: Tests do not start on node.js 14 ("ganache-cli exited early with code 1"). - # nodejs_version: 12 + # nodejs_version: '12' - t_ems_ext: <<: *workflow_emscripten name: t_ems_test_ext_gnosis_v2 project: gnosis-v2 # NOTE: Tests do not start on node.js 14 ("ganache-cli exited early with code 1"). - nodejs_version: 12 + nodejs_version: '12' - t_ems_ext: <<: *workflow_emscripten name: t_ems_test_ext_zeppelin project: zeppelin + nodejs_version: '14' - t_ems_ext: <<: *workflow_emscripten name: t_ems_test_ext_ens project: ens # NOTE: One of the dependencies (fsevents) fails to build its native extension on node.js 12+. - nodejs_version: 10 + nodejs_version: '10' # Windows build and tests - b_win: *workflow_trigger_on_tags From 9f59d1746b29591543ea103876a712ed21444845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 26 Oct 2021 15:49:00 +0200 Subject: [PATCH 0035/1704] Fix OpenZeppelin external tests to actually use Hardhat and the binary built in CI --- .circleci/config.yml | 4 +- test/externalTests/common.sh | 95 ++++++++++++++++++++++++++++++++++ test/externalTests/zeppelin.sh | 12 ++--- 3 files changed, 103 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 398e73e49e..7a24abab4f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1223,7 +1223,6 @@ workflows: name: t_ems_compile_ext_zeppelin project: zeppelin compile_only: 1 - nodejs_version: '14' - t_ems_ext: <<: *workflow_emscripten name: t_ems_compile_ext_ens @@ -1250,7 +1249,8 @@ workflows: <<: *workflow_emscripten name: t_ems_test_ext_zeppelin project: zeppelin - nodejs_version: '14' + # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" + nodejs_version: '16' - t_ems_ext: <<: *workflow_emscripten name: t_ems_test_ext_ens diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 2519a0f878..7e651d8c0b 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -74,6 +74,7 @@ function setup_solcjs npm install cp "$soljson" soljson.js SOLCVERSION=$(./solcjs --version) + SOLCVERSION_SHORT=$(echo "$SOLCVERSION" | sed -En 's/^([0-9.]+).*\+commit\.[0-9a-f]+.*$/\1/p') printLog "Using solcjs version $SOLCVERSION" cd .. } @@ -161,6 +162,40 @@ function force_truffle_compiler_settings echo "module.exports['compilers'] = $(truffle_compiler_settings "$solc_path" "$level" "$evm_version");" >> "$config_file" } +function force_hardhat_compiler_binary +{ + local config_file="$1" + local solc_path="$2" + + printLog "Configuring Hardhat..." + echo "-------------------------------------" + echo "Config file: ${config_file}" + echo "Compiler path: ${solc_path}" + hardhat_solc_build_subtask "$SOLCVERSION_SHORT" "$SOLCVERSION" "$solc_path" >> "$config_file" +} + +function force_hardhat_compiler_settings +{ + local config_file="$1" + local level="$2" + local evm_version="${3:-"$CURRENT_EVM_VERSION"}" + + printLog "Configuring Hardhat..." + echo "-------------------------------------" + echo "Config file: ${config_file}" + echo "Optimization level: ${level}" + echo "Optimizer settings: $(optimizer_settings_for_level "$level")" + echo "EVM version: ${evm_version}" + echo "Compiler version: ${SOLCVERSION_SHORT}" + echo "Compiler version (full): ${SOLCVERSION}" + echo "-------------------------------------" + + { + echo -n 'module.exports["solidity"] = ' + hardhat_compiler_settings "$SOLCVERSION_SHORT" "$level" "$evm_version" + } >> "$config_file" +} + function truffle_verify_compiler_version { local solc_version="$1" @@ -170,11 +205,26 @@ function truffle_verify_compiler_version grep "$full_solc_version" --with-filename --recursive build/contracts || fail "Wrong compiler version detected." } +function hardhat_verify_compiler_version +{ + local solc_version="$1" + local full_solc_version="$2" + + printLog "Verify that the correct version (${solc_version}/${full_solc_version}) of the compiler was used to compile the contracts..." + grep '"solcVersion": "'"${solc_version}"'"' --with-filename artifacts/build-info/*.json || fail "Wrong compiler version detected." + grep '"solcLongVersion": "'"${full_solc_version}"'"' --with-filename artifacts/build-info/*.json || fail "Wrong compiler version detected." +} + function truffle_clean { rm -rf build/ } +function hardhat_clean +{ + rm -rf artifacts/ cache/ +} + function run_test { local compile_fn="$1" @@ -221,6 +271,39 @@ function truffle_compiler_settings echo "}" } +function hardhat_solc_build_subtask { + local solc_version="$1" + local full_solc_version="$2" + local solc_path="$3" + + echo "const {TASK_COMPILE_SOLIDITY_GET_SOLC_BUILD} = require('hardhat/builtin-tasks/task-names');" + echo "const assert = require('assert');" + echo + echo "subtask(TASK_COMPILE_SOLIDITY_GET_SOLC_BUILD, async (args, hre, runSuper) => {" + echo " assert(args.solcVersion == '${solc_version}', 'Unexpected solc version: ' + args.solcVersion)" + echo " return {" + echo " compilerPath: '$(realpath "$solc_path")'," + echo " isSolcJs: true," + echo " version: args.solcVersion," + echo " longVersion: '${full_solc_version}'" + echo " }" + echo "})" +} + +function hardhat_compiler_settings { + local solc_version="$1" + local level="$2" + local evm_version="$3" + + echo "{" + echo " version: '${solc_version}'," + echo " settings: {" + echo " optimizer: $(optimizer_settings_for_level "$level")," + echo " evmVersion: '${evm_version}'" + echo " }" + echo "}" +} + function compile_and_run_test { local compile_fn="$1" @@ -252,6 +335,18 @@ function truffle_run_test compile_and_run_test compile_fn test_fn truffle_verify_compiler_version } +function hardhat_run_test +{ + local config_file="$1" + local optimizer_level="$2" + local compile_fn="$3" + local test_fn="$4" + + hardhat_clean + force_hardhat_compiler_settings "$config_file" "$optimizer_level" + compile_and_run_test compile_fn test_fn hardhat_verify_compiler_version +} + function external_test { local name="$1" diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 24e576b931..cd290b860f 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -27,14 +27,14 @@ source test/externalTests/common.sh verify_input "$1" SOLJSON="$1" -function compile_fn { npx truffle compile; } -function test_fn { npm run test; } +function compile_fn { npm run compile; } +function test_fn { npm test; } function zeppelin_test { local repo="https://github.com/OpenZeppelin/openzeppelin-contracts.git" local branch=master - local config_file="truffle-config.js" + local config_file="hardhat.config.js" local min_optimizer_level=1 local max_optimizer_level=3 @@ -46,14 +46,14 @@ function zeppelin_test download_project "$repo" "$branch" "$DIR" neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "${DIR}/solc" "$min_optimizer_level" + force_hardhat_compiler_binary "$config_file" "$SOLJSON" + force_hardhat_compiler_settings "$config_file" "$min_optimizer_level" npm install replace_version_pragmas - force_solc_modules "${DIR}/solc" for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn + hardhat_run_test "$config_file" "$level" compile_fn test_fn done } From 5e59325d0692665166a072555025152b8d1a63b2 Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Sat, 13 Nov 2021 01:31:11 +0530 Subject: [PATCH 0036/1704] relocated downloads section in versions flyout menu and added downloads Hint in index.html --- docs/_templates/versions.html | 8 ++++---- docs/index.rst | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/_templates/versions.html b/docs/_templates/versions.html index f680b6506d..fcd79cb3fc 100644 --- a/docs/_templates/versions.html +++ b/docs/_templates/versions.html @@ -13,13 +13,13 @@
-
{{ _('Versions') }}
{% for slug, url in versions %} -
{{ slug }}
+
{{ _('Downloads') }}
{% for type, url in downloads %} +
{{ type }}
{% endfor %}
-
{{ _('Downloads') }}
{% for type, url in downloads %} -
{{ type }}
+
{{ _('Versions') }}
{% for slug, url in versions %} +
{{ slug }}
{% endfor %}
diff --git a/docs/index.rst b/docs/index.rst index 60b3d61fac..1086df9a7b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,6 +31,12 @@ a 0.y.z version number `to indicate this fast pace of change ` for more details. +.. Hint:: + + You can download this documentation as PDF, HTML or Epub by clicking on the versions + flyout menu in the left bottom corner and selecting the preferred download format. + + Getting Started --------------- From ecf6c8e122da75423bf680a7a0ab62a882654c3e Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Sat, 13 Nov 2021 01:41:38 +0530 Subject: [PATCH 0037/1704] trailing whitespace removed in index.rst as per the requirements of a syntax test --- docs/_templates/versions.html | 8 ++++++-- docs/index.rst | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/_templates/versions.html b/docs/_templates/versions.html index fcd79cb3fc..9168179dfd 100644 --- a/docs/_templates/versions.html +++ b/docs/_templates/versions.html @@ -1,7 +1,11 @@ {# Add rst-badge after rst-versions for small badge style. #}
- RTD + {% for type, url in downloads %} + {% if type == 'PDF' %} + {{ type }} + {% endif %} + {% endfor %} @@ -33,4 +37,4 @@
- \ No newline at end of file + diff --git a/docs/index.rst b/docs/index.rst index 1086df9a7b..f69f8692b0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -33,8 +33,8 @@ read our :doc:`contributors guide ` for more details. .. Hint:: - You can download this documentation as PDF, HTML or Epub by clicking on the versions - flyout menu in the left bottom corner and selecting the preferred download format. + You can download this documentation as PDF, HTML or Epub by clicking on the versions + flyout menu in the bottom-left corner and selecting the preferred download format. Getting Started From 49d9f334aa3490590eeb4a339cf74565e38052ea Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Sun, 21 Nov 2021 00:14:34 +0530 Subject: [PATCH 0038/1704] Extracted some test cases from SolidityEndToEnd.cpp --- test/libsolidity/SolidityEndToEndTest.cpp | 210 ------------------ .../enums/invalid_enum_logged.sol | 24 ++ .../library_staticcall_delegatecall.sol | 20 ++ .../memory_types_initialisation.sol | 17 ++ .../strings/constant_string_literal.sol | 25 +++ .../semanticTests/strings/return_string.sol | 20 ++ .../structs/packed_storage_structs_delete.sol | 27 +++ .../variables/storing_invalid_boolean.sol | 35 +++ 8 files changed, 168 insertions(+), 210 deletions(-) create mode 100644 test/libsolidity/semanticTests/enums/invalid_enum_logged.sol create mode 100644 test/libsolidity/semanticTests/libraries/library_staticcall_delegatecall.sol create mode 100644 test/libsolidity/semanticTests/memoryManagement/memory_types_initialisation.sol create mode 100644 test/libsolidity/semanticTests/strings/constant_string_literal.sol create mode 100644 test/libsolidity/semanticTests/strings/return_string.sol create mode 100644 test/libsolidity/semanticTests/structs/packed_storage_structs_delete.sol create mode 100644 test/libsolidity/semanticTests/variables/storing_invalid_boolean.sol diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e5a6b8cf7c..4731149618 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1607,30 +1607,6 @@ BOOST_AUTO_TEST_CASE(library_call_protection) ) } -BOOST_AUTO_TEST_CASE(library_staticcall_delegatecall) -{ - char const* sourceCode = R"( - library Lib { - function x() public view returns (uint) { - return 1; - } - } - contract Test { - uint t; - function f() public returns (uint) { - t = 2; - return this.g(); - } - function g() public view returns (uint) { - return Lib.x(); - } - } - )"; - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs(1)); -} - BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) { char const* sourceCode = R"( @@ -1786,49 +1762,6 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) ); } -BOOST_AUTO_TEST_CASE(storing_invalid_boolean) -{ - char const* sourceCode = R"( - contract C { - event Ev(bool); - bool public perm; - function set() public returns(uint) { - bool tmp; - assembly { - tmp := 5 - } - perm = tmp; - return 1; - } - function ret() public returns(bool) { - bool tmp; - assembly { - tmp := 5 - } - return tmp; - } - function ev() public returns(uint) { - bool tmp; - assembly { - tmp := 5 - } - emit Ev(tmp); - return 1; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("set()"), encodeArgs(1)); - ABI_CHECK(callContractFunction("perm()"), encodeArgs(1)); - ABI_CHECK(callContractFunction("ret()"), encodeArgs(1)); - ABI_CHECK(callContractFunction("ev()"), encodeArgs(1)); - BOOST_REQUIRE_EQUAL(numLogs(), 1); - BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); - BOOST_CHECK(logData(0) == encodeArgs(1)); - BOOST_REQUIRE_EQUAL(numLogTopics(0), 1); - BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("Ev(bool)"))); -} - BOOST_AUTO_TEST_CASE(struct_referencing) { static char const* sourceCode = R"( @@ -2059,70 +1992,6 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi) // ABI_CHECK(callContractFunction("f()"), encodeArgs(5)); //} -BOOST_AUTO_TEST_CASE(packed_storage_structs_delete) -{ - char const* sourceCode = R"( - contract C { - struct str { uint8 a; uint16 b; uint8 c; } - uint8 x; - uint16 y; - str data; - function test() public returns (uint) { - x = 1; - y = 2; - data.a = 2; - data.b = 0xabcd; - data.c = 0xfa; - if (x != 1 || y != 2 || data.a != 2 || data.b != 0xabcd || data.c != 0xfa) - return 2; - delete y; - delete data.b; - if (x != 1 || y != 0 || data.a != 2 || data.b != 0 || data.c != 0xfa) - return 3; - delete x; - delete data; - return 1; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); - BOOST_CHECK(storageEmpty(m_contractAddress)); -} - -BOOST_AUTO_TEST_CASE(invalid_enum_logged) -{ - char const* sourceCode = R"( - contract C { - enum X { A, B } - event Log(X); - - function test_log() public returns (uint) { - X garbled = X.A; - assembly { - garbled := 5 - } - emit Log(garbled); - return 1; - } - function test_log_ok() public returns (uint) { - X x = X.A; - emit Log(x); - return 1; - } - } - )"; - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("test_log_ok()"), encodeArgs(u256(1))); - BOOST_REQUIRE_EQUAL(numLogs(), 1); - BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); - BOOST_REQUIRE_EQUAL(numLogTopics(0), 1); - BOOST_REQUIRE_EQUAL(logTopic(0, 0), util::keccak256(string("Log(uint8)"))); - BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(0))); - - ABI_CHECK(callContractFunction("test_log()"), panicData(PanicCode::EnumConversionError)); -} - BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) { char const* sourceCode = R"( @@ -2164,31 +2033,6 @@ BOOST_AUTO_TEST_CASE(failing_send) BOOST_REQUIRE(callContractFunction("callHelper(address)", c_helperAddress) == encodeArgs(true, 20)); } -BOOST_AUTO_TEST_CASE(return_string) -{ - char const* sourceCode = R"( - contract Main { - string public s; - function set(string calldata _s) external { - s = _s; - } - function get1() public returns (string memory r) { - return s; - } - function get2() public returns (string memory r) { - r = s; - } - } - )"; - compileAndRun(sourceCode, 0, "Main"); - string s("Julia"); - bytes args = encodeArgs(u256(0x20), u256(s.length()), s); - BOOST_REQUIRE(callContractFunction("set(string)", asString(args)) == encodeArgs()); - ABI_CHECK(callContractFunction("get1()"), args); - ABI_CHECK(callContractFunction("get2()"), args); - ABI_CHECK(callContractFunction("s()"), args); -} - BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes) { char const* sourceCode = R"( @@ -2343,28 +2187,6 @@ BOOST_AUTO_TEST_CASE(return_bytes_internal) } } -BOOST_AUTO_TEST_CASE(memory_types_initialisation) -{ - char const* sourceCode = R"( - contract Test { - mapping(uint=>uint) data; - function stat() public returns (uint[5] memory) - { - data[2] = 3; // make sure to use some memory - } - function dyn() public returns (uint[] memory) { stat(); } - function nested() public returns (uint[3][] memory) { stat(); } - function nestedStat() public returns (uint[3][7] memory) { stat(); } - } - )"; - compileAndRun(sourceCode, 0, "Test"); - - ABI_CHECK(callContractFunction("stat()"), encodeArgs(vector(5))); - ABI_CHECK(callContractFunction("dyn()"), encodeArgs(u256(0x20), u256(0))); - ABI_CHECK(callContractFunction("nested()"), encodeArgs(u256(0x20), u256(0))); - ABI_CHECK(callContractFunction("nestedStat()"), encodeArgs(vector(3 * 7))); -} - BOOST_AUTO_TEST_CASE(calldata_struct_short) { char const* sourceCode = R"( @@ -2718,38 +2540,6 @@ BOOST_AUTO_TEST_CASE(nested_mixed_string_as_public_mapping_key) ), encodeArgs(u256(i - 3))); } -BOOST_AUTO_TEST_CASE(constant_string_literal) -{ - char const* sourceCode = R"( - contract Test { - bytes32 constant public b = "abcdefghijklmnopq"; - string constant public x = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca"; - - constructor() { - string memory xx = x; - bytes32 bb = b; - } - function getB() public returns (bytes32) { return b; } - function getX() public returns (string memory) { return x; } - function getX2() public returns (string memory r) { r = x; } - function unused() public returns (uint) { - "unusedunusedunusedunusedunusedunusedunusedunusedunusedunusedunusedunused"; - return 2; - } - } - )"; - - compileAndRun(sourceCode); - string longStr = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca"; - string shortStr = "abcdefghijklmnopq"; - ABI_CHECK(callContractFunction("b()"), encodeArgs(shortStr)); - ABI_CHECK(callContractFunction("x()"), encodeDyn(longStr)); - ABI_CHECK(callContractFunction("getB()"), encodeArgs(shortStr)); - ABI_CHECK(callContractFunction("getX()"), encodeDyn(longStr)); - ABI_CHECK(callContractFunction("getX2()"), encodeDyn(longStr)); - ABI_CHECK(callContractFunction("unused()"), encodeArgs(2)); -} - BOOST_AUTO_TEST_CASE(library_call) { char const* sourceCode = R"( diff --git a/test/libsolidity/semanticTests/enums/invalid_enum_logged.sol b/test/libsolidity/semanticTests/enums/invalid_enum_logged.sol new file mode 100644 index 0000000000..33cec7482a --- /dev/null +++ b/test/libsolidity/semanticTests/enums/invalid_enum_logged.sol @@ -0,0 +1,24 @@ +contract C { + enum X { A, B } + event Log(X); + + function test_log() public returns (uint) { + X garbled = X.A; + assembly { + garbled := 5 + } + emit Log(garbled); + return 1; + } + function test_log_ok() public returns (uint) { + X x = X.A; + emit Log(x); + return 1; + } +} +// ==== +// compileViaYul: also +// ---- +// test_log_ok() -> 1 +// ~ emit Log(uint8): 0x00 +// test_log() -> FAILURE, hex"4e487b71", 0x21 diff --git a/test/libsolidity/semanticTests/libraries/library_staticcall_delegatecall.sol b/test/libsolidity/semanticTests/libraries/library_staticcall_delegatecall.sol new file mode 100644 index 0000000000..d566f71801 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/library_staticcall_delegatecall.sol @@ -0,0 +1,20 @@ +library Lib { + function x() public view returns (uint) { + return 1; + } +} +contract Test { + uint t; + function f() public returns (uint) { + t = 2; + return this.g(); + } + function g() public view returns (uint) { + return Lib.x(); + } +} +// ==== +// compileViaYul: also +// ---- +// library: Lib +// f() -> 1 diff --git a/test/libsolidity/semanticTests/memoryManagement/memory_types_initialisation.sol b/test/libsolidity/semanticTests/memoryManagement/memory_types_initialisation.sol new file mode 100644 index 0000000000..7ad6b61672 --- /dev/null +++ b/test/libsolidity/semanticTests/memoryManagement/memory_types_initialisation.sol @@ -0,0 +1,17 @@ +contract Test { + mapping(uint=>uint) data; + function stat() public returns (uint[5] memory) + { + data[2] = 3; // make sure to use some memory + } + function dyn() public returns (uint[] memory) { stat(); } + function nested() public returns (uint[3][] memory) { stat(); } + function nestedStat() public returns (uint[3][7] memory) { stat(); } +} +// ==== +// compileViaYul: also +// ---- +// stat() -> 0, 0, 0, 0, 0 +// dyn() -> 0x20, 0 +// nested() -> 0x20, 0 +// nestedStat() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 diff --git a/test/libsolidity/semanticTests/strings/constant_string_literal.sol b/test/libsolidity/semanticTests/strings/constant_string_literal.sol new file mode 100644 index 0000000000..9c112c1faa --- /dev/null +++ b/test/libsolidity/semanticTests/strings/constant_string_literal.sol @@ -0,0 +1,25 @@ +contract Test { + bytes32 constant public b = "abcdefghijklmnopq"; + string constant public x = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca"; + + constructor() { + string memory xx = x; + bytes32 bb = b; + } + function getB() public returns (bytes32) { return b; } + function getX() public returns (string memory) { return x; } + function getX2() public returns (string memory r) { r = x; } + function unused() public returns (uint) { + "unusedunusedunusedunusedunusedunusedunusedunusedunusedunusedunusedunused"; + return 2; + } +} +// ==== +// compileViaYul: also +// ---- +// b() -> 0x6162636465666768696a6b6c6d6e6f7071000000000000000000000000000000 +// x() -> 0x20, 0x35, 0x616265666768696a6b6c6d6e6f70716162636465666768696a6b6c6d6e6f7071, 44048183304486788312148433451363384677562177293131179093971701692629931524096 +// getB() -> 0x6162636465666768696a6b6c6d6e6f7071000000000000000000000000000000 +// getX() -> 0x20, 0x35, 0x616265666768696a6b6c6d6e6f70716162636465666768696a6b6c6d6e6f7071, 44048183304486788312148433451363384677562177293131179093971701692629931524096 +// getX2() -> 0x20, 0x35, 0x616265666768696a6b6c6d6e6f70716162636465666768696a6b6c6d6e6f7071, 44048183304486788312148433451363384677562177293131179093971701692629931524096 +// unused() -> 2 diff --git a/test/libsolidity/semanticTests/strings/return_string.sol b/test/libsolidity/semanticTests/strings/return_string.sol new file mode 100644 index 0000000000..f221a5e156 --- /dev/null +++ b/test/libsolidity/semanticTests/strings/return_string.sol @@ -0,0 +1,20 @@ +contract Main { + string public s; + function set(string calldata _s) external { + s = _s; + } + function get1() public returns (string memory r) { + return s; + } + function get2() public returns (string memory r) { + r = s; + } +} +// ==== +// compileToEwasm: also +// compileViaYul: also +// ---- +// set(string): 0x20, 5, "Julia" -> +// get1() -> 0x20, 5, "Julia" +// get2() -> 0x20, 5, "Julia" +// s() -> 0x20, 5, "Julia" diff --git a/test/libsolidity/semanticTests/structs/packed_storage_structs_delete.sol b/test/libsolidity/semanticTests/structs/packed_storage_structs_delete.sol new file mode 100644 index 0000000000..8d4931554d --- /dev/null +++ b/test/libsolidity/semanticTests/structs/packed_storage_structs_delete.sol @@ -0,0 +1,27 @@ +contract C { + struct str { uint8 a; uint16 b; uint8 c; } + uint8 x; + uint16 y; + str data; + function test() public returns (uint) { + x = 1; + y = 2; + data.a = 2; + data.b = 0xabcd; + data.c = 0xfa; + if (x != 1 || y != 2 || data.a != 2 || data.b != 0xabcd || data.c != 0xfa) + return 2; + delete y; + delete data.b; + if (x != 1 || y != 0 || data.a != 2 || data.b != 0 || data.c != 0xfa) + return 3; + delete x; + delete data; + return 1; + } +} +// ==== +// compileViaYul: also +// ---- +// test() -> 1 +// storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/variables/storing_invalid_boolean.sol b/test/libsolidity/semanticTests/variables/storing_invalid_boolean.sol new file mode 100644 index 0000000000..930ded40bf --- /dev/null +++ b/test/libsolidity/semanticTests/variables/storing_invalid_boolean.sol @@ -0,0 +1,35 @@ +contract C { + event Ev(bool); + bool public perm; + function set() public returns(uint) { + bool tmp; + assembly { + tmp := 5 + } + perm = tmp; + return 1; + } + function ret() public returns(bool) { + bool tmp; + assembly { + tmp := 5 + } + return tmp; + } + function ev() public returns(uint) { + bool tmp; + assembly { + tmp := 5 + } + emit Ev(tmp); + return 1; + } +} +// ==== +// compileViaYul: also +// ---- +// set() -> 1 +// perm() -> true +// ret() -> true +// ev() -> 1 +// ~ emit Ev(bool): true From bd399e37e3cd2224c9403b6c7ce4ab6f7c990817 Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Tue, 30 Nov 2021 00:12:52 +0530 Subject: [PATCH 0039/1704] restoring the RTD section. Downloads section to still be above versions section --- docs/_templates/versions.html | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/_templates/versions.html b/docs/_templates/versions.html index 9168179dfd..a2432e3703 100644 --- a/docs/_templates/versions.html +++ b/docs/_templates/versions.html @@ -1,11 +1,7 @@ {# Add rst-badge after rst-versions for small badge style. #}
- {% for type, url in downloads %} - {% if type == 'PDF' %} - {{ type }} - {% endif %} - {% endfor %} + RTD From 310f74302d893243a0abc03352654f8e21157be7 Mon Sep 17 00:00:00 2001 From: Dallon Asnes Date: Mon, 29 Nov 2021 15:31:52 -0600 Subject: [PATCH 0040/1704] Add fixed size type details to encodePacked doc --- docs/abi-spec.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 6f50c70d9e..02e5f8b2a4 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -749,7 +749,7 @@ Non-standard Packed Mode Through ``abi.encodePacked()``, Solidity supports a non-standard packed mode where: -- types shorter than 32 bytes are neither zero padded nor sign extended and +- types shorter than 32 bytes are concatenated directly, without padding or sign extension - dynamic types are encoded in-place and without the length. - array elements are padded, but still encoded in-place From 86ce5f1da50e7de9c4d0649273637adda10f46b9 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 29 Nov 2021 21:19:41 +0100 Subject: [PATCH 0041/1704] Use LineColumn type. --- liblangutil/CharStream.cpp | 4 ++-- liblangutil/CharStream.h | 3 ++- liblangutil/SourceLocation.h | 19 +++++++++++++++++++ liblangutil/SourceReferenceExtractor.h | 9 --------- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/liblangutil/CharStream.cpp b/liblangutil/CharStream.cpp index 3b30bad776..96a6aebe29 100644 --- a/liblangutil/CharStream.cpp +++ b/liblangutil/CharStream.cpp @@ -100,7 +100,7 @@ string CharStream::lineAtPosition(int _position) const return line; } -tuple CharStream::translatePositionToLineColumn(int _position) const +LineColumn CharStream::translatePositionToLineColumn(int _position) const { using size_type = string::size_type; using diff_type = string::difference_type; @@ -114,7 +114,7 @@ tuple CharStream::translatePositionToLineColumn(int _position) const lineStart = m_source.rfind('\n', searchPosition - 1); lineStart = lineStart == string::npos ? 0 : lineStart + 1; } - return tuple(lineNumber, searchPosition - lineStart); + return LineColumn{lineNumber, static_cast(searchPosition - lineStart)}; } string_view CharStream::text(SourceLocation const& _location) const diff --git a/liblangutil/CharStream.h b/liblangutil/CharStream.h index 761cece316..2e5d79d932 100644 --- a/liblangutil/CharStream.h +++ b/liblangutil/CharStream.h @@ -59,6 +59,7 @@ namespace solidity::langutil { struct SourceLocation; +struct LineColumn; /** * Bidirectional stream of characters. @@ -97,7 +98,7 @@ class CharStream /// Functions that help pretty-printing parse errors /// Do only use in error cases, they are quite expensive. std::string lineAtPosition(int _position) const; - std::tuple translatePositionToLineColumn(int _position) const; + LineColumn translatePositionToLineColumn(int _position) const; ///@} /// Tests whether or not given octet sequence is present at the current position in stream. diff --git a/liblangutil/SourceLocation.h b/liblangutil/SourceLocation.h index ea9958933d..ddb4575356 100644 --- a/liblangutil/SourceLocation.h +++ b/liblangutil/SourceLocation.h @@ -119,4 +119,23 @@ SourceLocation parseSourceLocation( /// Stream output for Location (used e.g. in boost exceptions). std::ostream& operator<<(std::ostream& _out, SourceLocation const& _location); + +/** + * Alternative, line-column-based representation for source locations. + * Both line and column are zero-based. + * If used as a range, the second location is considered exclusive. + * Negative values are invalid. + */ +struct LineColumn +{ + /// Line value, can be between zero and number of `\n` characters in the source file. + int line = -1; + /// Column value, can be between zero and number of characters in the line (inclusive). + int column = -1; + + LineColumn() = default; + explicit LineColumn(int _line, int _column): line(_line), column(_column) {} +}; + + } diff --git a/liblangutil/SourceReferenceExtractor.h b/liblangutil/SourceReferenceExtractor.h index 6aeb6065e1..3b418fcfa2 100644 --- a/liblangutil/SourceReferenceExtractor.h +++ b/liblangutil/SourceReferenceExtractor.h @@ -30,15 +30,6 @@ namespace solidity::langutil class CharStreamProvider; -struct LineColumn -{ - int line = {-1}; - int column = {-1}; - - LineColumn() = default; - LineColumn(std::tuple const& _t): line{std::get<0>(_t)}, column{std::get<1>(_t)} {} -}; - struct SourceReference { std::string message; ///< A message that relates to this source reference (such as a warning, info or an error message). From a0aacb91a6d42a2220081cfaaab17ddaf569f354 Mon Sep 17 00:00:00 2001 From: Dallon Asnes Date: Mon, 29 Nov 2021 23:43:28 -0600 Subject: [PATCH 0042/1704] Fix cl test script on macOS --- test/cmdlineTests.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 4f9d41384b..87442c6067 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -54,7 +54,13 @@ do shift ;; *) - matching_tests=$(find . -mindepth 1 -maxdepth 1 -type d -name "$1" | cut --characters 3- | sort) + if [[ "$OSTYPE" == "darwin"* ]] + then + matching_tests=$(find . -mindepth 1 -maxdepth 1 -type d -name "$1" | cut -c 3- | sort) + else + matching_tests=$(find . -mindepth 1 -maxdepth 1 -type d -name "$1" | cut --characters 3- | sort) + fi + if [[ $matching_tests == "" ]] then From 70e925dbfc98a6e8c519f0095d4077fa28fda2c5 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Tue, 30 Nov 2021 10:07:50 -0600 Subject: [PATCH 0043/1704] Update test/cmdlineTests.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- test/cmdlineTests.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 87442c6067..f9a26cb46b 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -54,12 +54,7 @@ do shift ;; *) - if [[ "$OSTYPE" == "darwin"* ]] - then - matching_tests=$(find . -mindepth 1 -maxdepth 1 -type d -name "$1" | cut -c 3- | sort) - else - matching_tests=$(find . -mindepth 1 -maxdepth 1 -type d -name "$1" | cut --characters 3- | sort) - fi + matching_tests=$(find . -mindepth 1 -maxdepth 1 -type d -name "$1" | cut -c 3- | sort) if [[ $matching_tests == "" ]] From bd193ae8401066bce6fbc3cede100f693b17922b Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 1 Dec 2021 12:46:02 +0100 Subject: [PATCH 0044/1704] Fix whitespace problem. --- test/cmdlineTests.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index f9a26cb46b..d33dd208c1 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -55,7 +55,6 @@ do ;; *) matching_tests=$(find . -mindepth 1 -maxdepth 1 -type d -name "$1" | cut -c 3- | sort) - if [[ $matching_tests == "" ]] then From b6bd85202c0e5e6bae0dcc71b9ebcfea17de5f9a Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 1 Dec 2021 12:30:36 +0100 Subject: [PATCH 0045/1704] Accessors for exceptions. --- liblangutil/Exceptions.cpp | 10 ++++++++++ liblangutil/Exceptions.h | 5 ++++- libsolidity/interface/StandardCompiler.cpp | 2 +- libsolutil/Exceptions.h | 2 -- test/libsolidity/AnalysisFramework.cpp | 2 +- test/libsolidity/SyntaxTest.cpp | 5 +++-- test/libyul/SyntaxTest.cpp | 2 +- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/liblangutil/Exceptions.cpp b/liblangutil/Exceptions.cpp index a410a98635..2595c7755c 100644 --- a/liblangutil/Exceptions.cpp +++ b/liblangutil/Exceptions.cpp @@ -75,6 +75,16 @@ Error::Error( *this << util::errinfo_comment(_description); } +SourceLocation const* Error::sourceLocation() const noexcept +{ + return boost::get_error_info(*this); +} + +SecondarySourceLocation const* Error::secondarySourceLocation() const noexcept +{ + return boost::get_error_info(*this); +} + optional Error::severityFromString(string _input) { boost::algorithm::to_lower(_input); diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index 0c8f03cb94..10fca80293 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -197,6 +197,9 @@ class Error: virtual public util::Exception Type type() const { return m_type; } std::string const& typeName() const { return m_typeName; } + SourceLocation const* sourceLocation() const noexcept; + SecondarySourceLocation const* secondarySourceLocation() const noexcept; + /// helper functions static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type) { @@ -206,7 +209,7 @@ class Error: virtual public util::Exception return nullptr; } - static Severity errorSeverity(Type _type) + static constexpr Severity errorSeverity(Type _type) { if (_type == Type::Info) return Severity::Info; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index da28cf29f2..39ed7c10fb 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -129,7 +129,7 @@ Json::Value formatErrorWithException( _charStreamProvider ); - if (string const* description = boost::get_error_info(_exception)) + if (string const* description = _exception.comment()) message = ((_message.length() > 0) ? (_message + ":") : "") + *description; else message = _message; diff --git a/libsolutil/Exceptions.h b/libsolutil/Exceptions.h index d83d8004b4..9d351a28d2 100644 --- a/libsolutil/Exceptions.h +++ b/libsolutil/Exceptions.h @@ -39,8 +39,6 @@ struct Exception: virtual std::exception, virtual boost::exception /// @returns the errinfo_comment of this exception. std::string const* comment() const noexcept; - -private: }; /// Throws an exception with a given description and extra information about the location the diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 84c7a5e0bd..5dce2211f9 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -100,7 +100,7 @@ ErrorList AnalysisFramework::filterErrors(ErrorList const& _errorList, bool _inc for (auto const& messagePrefix: m_messagesToCut) if (currentError->comment()->find(messagePrefix) == 0) { - SourceLocation const* location = boost::get_error_info(*currentError); + SourceLocation const* location = currentError->sourceLocation(); // sufficient for now, but in future we might clone the error completely, including the secondary location newError = make_shared( currentError->errorId(), diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 4998b628b3..d3e5124508 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -118,9 +118,10 @@ void SyntaxTest::filterObtainedErrors() { for (auto const& currentError: filterErrors(compiler().errors(), true)) { - int locationStart = -1, locationEnd = -1; + int locationStart = -1; + int locationEnd = -1; string sourceName; - if (auto location = boost::get_error_info(*currentError)) + if (SourceLocation const* location = currentError->sourceLocation()) { solAssert(location->sourceName, ""); sourceName = *location->sourceName; diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 4668773e93..8ab5bb9530 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -54,7 +54,7 @@ void SyntaxTest::parseAndAnalyze() int locationStart = -1; int locationEnd = -1; - if (auto location = boost::get_error_info(*error)) + if (SourceLocation const* location = error->sourceLocation()) { locationStart = location->start; locationEnd = location->end; From 264b7bd85739deb1baff7678a7ea34130b988d88 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 1 Dec 2021 12:20:09 +0100 Subject: [PATCH 0046/1704] LineColumn handling for CharStream. --- liblangutil/CharStream.cpp | 29 +++++++++++ liblangutil/CharStream.h | 7 +++ test/liblangutil/CharStream.cpp | 85 ++++++++++++++++++++++++++++++++- 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/liblangutil/CharStream.cpp b/liblangutil/CharStream.cpp index 96a6aebe29..6ecd85bfed 100644 --- a/liblangutil/CharStream.cpp +++ b/liblangutil/CharStream.cpp @@ -144,3 +144,32 @@ string CharStream::singleLineSnippet(string const& _sourceCode, SourceLocation c return cut; } + +optional CharStream::translateLineColumnToPosition(LineColumn const& _lineColumn) const +{ + return translateLineColumnToPosition(m_source, _lineColumn); +} + +optional CharStream::translateLineColumnToPosition(std::string const& _text, LineColumn const& _input) +{ + if (_input.line < 0) + return nullopt; + + size_t offset = 0; + for (int i = 0; i < _input.line; i++) + { + offset = _text.find('\n', offset); + if (offset == _text.npos) + return nullopt; + offset++; // Skip linefeed. + } + + size_t endOfLine = _text.find('\n', offset); + if (endOfLine == string::npos) + endOfLine = _text.size(); + + if (offset + static_cast(_input.column) > endOfLine) + return nullopt; + return offset + static_cast(_input.column); +} + diff --git a/liblangutil/CharStream.h b/liblangutil/CharStream.h index 2e5d79d932..08f86129b2 100644 --- a/liblangutil/CharStream.h +++ b/liblangutil/CharStream.h @@ -51,6 +51,7 @@ #pragma once #include +#include #include #include #include @@ -101,6 +102,12 @@ class CharStream LineColumn translatePositionToLineColumn(int _position) const; ///@} + /// Translates a line:column to the absolute position. + std::optional translateLineColumnToPosition(LineColumn const& _lineColumn) const; + + /// Translates a line:column to the absolute position for the given input text. + static std::optional translateLineColumnToPosition(std::string const& _text, LineColumn const& _input); + /// Tests whether or not given octet sequence is present at the current position in stream. /// @returns true if the sequence could be found, false otherwise. bool prefixMatch(std::string_view _sequence) diff --git a/test/liblangutil/CharStream.cpp b/test/liblangutil/CharStream.cpp index 9321b14e0d..766a700986 100644 --- a/test/liblangutil/CharStream.cpp +++ b/test/liblangutil/CharStream.cpp @@ -28,6 +28,33 @@ #include +using namespace std; +using namespace solidity::test; + +namespace boost::test_tools::tt_detail +{ + +template<> +struct print_log_value> +{ + void operator()(std::ostream& _out, std::optional const& _value) const + { + _out << (_value ? to_string(*_value) : "[nullopt]"); + } +}; + +template<> +struct print_log_value +{ + void operator()(std::ostream& _out, nullopt_t const&) const + { + _out << "[nullopt]"; + } +}; + +} // namespace boost::test_tools::tt_detail + + namespace solidity::langutil::test { @@ -48,6 +75,62 @@ BOOST_AUTO_TEST_CASE(test_fail) ); } +namespace +{ +std::optional toPosition(int _line, int _column, string const& _text) +{ + return CharStream{_text, "source"}.translateLineColumnToPosition( + LineColumn{_line, _column} + ); +} + +} + +BOOST_AUTO_TEST_CASE(translateLineColumnToPosition) +{ + BOOST_CHECK_EQUAL(toPosition(-1, 0, "ABC"), nullopt); + BOOST_CHECK_EQUAL(toPosition(0, -1, "ABC"), nullopt); + + BOOST_CHECK_EQUAL(toPosition(0, 0, ""), 0); + BOOST_CHECK_EQUAL(toPosition(1, 0, ""), nullopt); + BOOST_CHECK_EQUAL(toPosition(0, 1, ""), nullopt); + + // With last line containing no LF + BOOST_CHECK_EQUAL(toPosition(0, 0, "ABC"), 0); + BOOST_CHECK_EQUAL(toPosition(0, 1, "ABC"), 1); + BOOST_CHECK_EQUAL(toPosition(0, 2, "ABC"), 2); + BOOST_CHECK_EQUAL(toPosition(0, 3, "ABC"), 3); + BOOST_CHECK_EQUAL(toPosition(0, 4, "ABC"), nullopt); + BOOST_CHECK_EQUAL(toPosition(1, 0, "ABC"), nullopt); + + BOOST_CHECK_EQUAL(toPosition(0, 3, "ABC\nDEF"), 3); + BOOST_CHECK_EQUAL(toPosition(0, 4, "ABC\nDEF"), nullopt); + BOOST_CHECK_EQUAL(toPosition(1, 0, "ABC\nDEF"), 4); + BOOST_CHECK_EQUAL(toPosition(1, 1, "ABC\nDEF"), 5); + BOOST_CHECK_EQUAL(toPosition(1, 2, "ABC\nDEF"), 6); + BOOST_CHECK_EQUAL(toPosition(1, 3, "ABC\nDEF"), 7); + BOOST_CHECK_EQUAL(toPosition(1, 4, "ABC\nDEF"), nullopt); + BOOST_CHECK_EQUAL(toPosition(2, 0, "ABC\nDEF"), nullopt); + BOOST_CHECK_EQUAL(toPosition(2, 1, "ABC\nDEF"), nullopt); + + // With last line containing LF + BOOST_CHECK_EQUAL(toPosition(0, 0, "ABC\nDEF\n"), 0); + BOOST_CHECK_EQUAL(toPosition(0, 1, "ABC\nDEF\n"), 1); + BOOST_CHECK_EQUAL(toPosition(0, 2, "ABC\nDEF\n"), 2); + + BOOST_CHECK_EQUAL(toPosition(1, 0, "ABC\nDEF\n"), 4); + BOOST_CHECK_EQUAL(toPosition(1, 1, "ABC\nDEF\n"), 5); + BOOST_CHECK_EQUAL(toPosition(1, 2, "ABC\nDEF\n"), 6); + BOOST_CHECK_EQUAL(toPosition(1, 3, "ABC\nDEF\n"), 7); + BOOST_CHECK_EQUAL(toPosition(1, 4, "ABC\nDEF\n"), nullopt); + BOOST_CHECK_EQUAL(toPosition(2, 0, "ABC\nDEF\n"), 8); + BOOST_CHECK_EQUAL(toPosition(2, 1, "ABC\nDEF\n"), nullopt); + + BOOST_CHECK_EQUAL(toPosition(2, 0, "ABC\nDEF\nGHI\n"), 8); + BOOST_CHECK_EQUAL(toPosition(2, 1, "ABC\nDEF\nGHI\n"), 9); + BOOST_CHECK_EQUAL(toPosition(2, 2, "ABC\nDEF\nGHI\n"), 10); +} + BOOST_AUTO_TEST_SUITE_END() -} // end namespaces +} From d56fb3afffd23dfac656a14d2c3c60c7db841f16 Mon Sep 17 00:00:00 2001 From: Tynan Richards Date: Wed, 24 Nov 2021 14:39:14 +0100 Subject: [PATCH 0047/1704] Fix ExpressionSplitter example Fix error (0x123 and 0x456 were swapped) and split constants into expressions --- docs/internals/optimizer.rst | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index d75eca4198..ccb72b9396 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -521,7 +521,7 @@ ExpressionSplitter The expression splitter turns expressions like ``add(mload(0x123), mul(mload(0x456), 0x20))`` into a sequence of declarations of unique variables that are assigned sub-expressions -of that expression so that each function call has only variables or literals +of that expression so that each function call has only variables as arguments. The above would be transformed into @@ -529,10 +529,13 @@ The above would be transformed into .. code-block:: yul { - let _1 := mload(0x123) - let _2 := mul(_1, 0x20) - let _3 := mload(0x456) - let z := add(_3, _2) + let _1 = 0x20 + let _2 = 0x456 + let _3 = mload(_2) + let _4 = mul(_3, _1) + let _5 = 0x123 + let _6 = mload(_5) + let z = add(_6, _4) } Note that this transformation does not change the order of opcodes or function calls. @@ -543,7 +546,7 @@ this "outlining" of the inner expressions in all cases. We can sidestep this lim The final program should be in a form such that (with the exception of loop conditions) function calls cannot appear nested inside expressions -and all function call arguments have to be literals or variables. +and all function call arguments have to be variables. The benefits of this form are that it is much easier to re-order the sequence of opcodes and it is also easier to perform function call inlining. Furthermore, it is simpler From 829fe6615ba601de8f605941251b2996aad6032a Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 1 Dec 2021 16:23:26 +0100 Subject: [PATCH 0048/1704] Fix Yul example. --- docs/internals/optimizer.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index ccb72b9396..19bca791e8 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -529,13 +529,13 @@ The above would be transformed into .. code-block:: yul { - let _1 = 0x20 - let _2 = 0x456 - let _3 = mload(_2) - let _4 = mul(_3, _1) - let _5 = 0x123 - let _6 = mload(_5) - let z = add(_6, _4) + let _1 := 0x20 + let _2 := 0x456 + let _3 := mload(_2) + let _4 := mul(_3, _1) + let _5 := 0x123 + let _6 := mload(_5) + let z := add(_6, _4) } Note that this transformation does not change the order of opcodes or function calls. From d9a4020a92db3fdc92163fa1bdb8b46ce13fae86 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 1 Dec 2021 12:31:21 +0100 Subject: [PATCH 0049/1704] Function to read a number of bytes from an input stream. --- libsolutil/CommonIO.cpp | 11 +++++++++++ libsolutil/CommonIO.h | 4 ++++ test/libsolutil/CommonIO.cpp | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/libsolutil/CommonIO.cpp b/libsolutil/CommonIO.cpp index 9da5b2422a..6089f4db66 100644 --- a/libsolutil/CommonIO.cpp +++ b/libsolutil/CommonIO.cpp @@ -79,6 +79,17 @@ string solidity::util::readUntilEnd(istream& _stdin) return ss.str(); } +string solidity::util::readBytes(istream& _input, size_t _length) +{ + string output; + output.resize(_length); + _input.read(output.data(), static_cast(_length)); + // If read() reads fewer bytes it sets failbit in addition to eofbit. + if (_input.fail()) + output.resize(static_cast(_input.gcount())); + return output; +} + #if defined(_WIN32) class DisableConsoleBuffering { diff --git a/libsolutil/CommonIO.h b/libsolutil/CommonIO.h index ab0000f868..e6cd0c1616 100644 --- a/libsolutil/CommonIO.h +++ b/libsolutil/CommonIO.h @@ -57,6 +57,10 @@ std::string readFileAsString(boost::filesystem::path const& _file); /// Retrieves and returns the whole content of the specified input stream (until EOF). std::string readUntilEnd(std::istream& _stdin); +/// Tries to read exactly @a _length bytes from @a _input. +/// Returns a string containing as much data as has been read. +std::string readBytes(std::istream& _input, size_t _length); + /// Retrieves and returns a character from standard input (without waiting for EOL). int readStandardInputChar(); diff --git a/test/libsolutil/CommonIO.cpp b/test/libsolutil/CommonIO.cpp index ce1a24a414..8b8c3d3263 100644 --- a/test/libsolutil/CommonIO.cpp +++ b/test/libsolutil/CommonIO.cpp @@ -90,6 +90,15 @@ BOOST_AUTO_TEST_CASE(readUntilEnd_empty) BOOST_TEST(readUntilEnd(inputStream) == ""); } +BOOST_AUTO_TEST_CASE(readBytes_past_end) +{ + istringstream inputStream("abc"); + BOOST_CHECK_EQUAL(readBytes(inputStream, 0), ""); + BOOST_CHECK_EQUAL(readBytes(inputStream, 1), "a"); + BOOST_CHECK_EQUAL(readBytes(inputStream, 20), "bc"); + BOOST_CHECK_EQUAL(readBytes(inputStream, 20), ""); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace solidity::util::test From 105de2561acda08ae4220c63f21093e1a30c032e Mon Sep 17 00:00:00 2001 From: Saska Karsi <44523813+saska@users.noreply.github.com> Date: Fri, 3 Dec 2021 01:11:04 +0200 Subject: [PATCH 0050/1704] rm trailing comma in style-guide.rst example --- docs/style-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 9e0fba5f66..64e76526f5 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -747,7 +747,7 @@ Yes: function thisFunctionNameIsReallyLong( address x, address y, - address z, + address z ) public onlyOwner From 16535aae3272e676a140ea94e3f2a757a2ee20ec Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Wed, 1 Dec 2021 17:38:23 +0100 Subject: [PATCH 0051/1704] Fix ICE when unsafe targets are solved more than once and the cex is different --- Changelog.md | 1 + libsolidity/formal/CHC.cpp | 2 - .../smtCheckerTests/imports/ExtCall.sol | 42 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/imports/ExtCall.sol diff --git a/Changelog.md b/Changelog.md index b3af54d047..e24cb24628 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: * Code Generator: Fix a crash when using ``@use-src`` and compiling from Yul to ewasm. + * SMTChecker: Fix internal error when an unsafe target is solved more than once and the counterexample messages are different. ### 0.8.10 (2021-11-09) diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 76a5ded998..0edfc27fff 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -972,8 +972,6 @@ void CHC::resetSourceAnalysis() { SMTEncoder::resetSourceAnalysis(); - m_safeTargets.clear(); - m_unsafeTargets.clear(); m_unprovedTargets.clear(); m_invariants.clear(); m_functionTargetIds.clear(); diff --git a/test/libsolidity/smtCheckerTests/imports/ExtCall.sol b/test/libsolidity/smtCheckerTests/imports/ExtCall.sol new file mode 100644 index 0000000000..047148a90c --- /dev/null +++ b/test/libsolidity/smtCheckerTests/imports/ExtCall.sol @@ -0,0 +1,42 @@ +==== Source: ExtCall.sol ==== +interface Unknown { + function callme() external; +} + +contract ExtCall { + uint x; + + bool lock; + modifier mutex { + require(!lock); + lock = true; + _; + lock = false; + } + + function setX(uint y) mutex public { + x = y; + } + + function xMut(Unknown u) public { + uint x_prev = x; + u.callme(); + assert(x_prev == x); + } +} +==== Source: ExtCall.t.sol ==== +import "ExtCall.sol"; + +contract ExtCallTest { + ExtCall call; + + function setUp() public { + call = new ExtCall(); + } +} +// ==== +// SMTEngine: all +// SMTIgnoreCex: yes +// ---- +// Warning 6328: (ExtCall.sol:362-381): CHC: Assertion violation happens here. +// Warning 4588: (ExtCall.t.sol:110-123): Assertion checker does not yet implement this type of function call. From a4fbc607c65ed63484e130dea58377b70f573bbe Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Wed, 10 Nov 2021 17:46:36 +0530 Subject: [PATCH 0052/1704] Issue 11610 : Replced typeError with fataTypeError in lines 390 and 406. Test file added in test/libsolidity/syntaxTests/calldata_struct_argument_with_internal_type_inside.sol Issue : 11610 : Test cases updated, Changelog.md file updated to include change on 0.8.11 --- Changelog.md | 2 ++ libsolidity/analysis/TypeChecker.cpp | 4 ++-- ...s_taking_internal_types_nested_struct_with_mapping.sol | 1 - ...unctions_taking_internal_types_struct_with_mapping.sol | 1 - test/libsolidity/syntaxTests/array/function_mapping.sol | 1 - .../constructor/constructor_mapping_memory.sol | 1 - ...ata_struct_argument_with_internal_data_type_inside.sol | 8 ++++++++ ...ruct_array_argument_with_internal_data_type_inside.sol | 8 ++++++++ ...internal_data_type_inside_as_constructor_parameter.sol | 8 ++++++++ .../structs/calldata_struct_mapping_function.sol | 1 - .../recursion/recursive_struct_nested_mapping_memory.sol | 1 - ...apping_array_data_location_function_param_external.sol | 1 - .../mapping_data_location_function_param_external.sol | 1 - .../mapping_data_location_function_param_public.sol | 1 - .../types/mapping/mapping_function_calldata.sol | 1 - .../types/mapping/mapping_return_public_memory.sol | 1 - .../types/mapping/mapping_struct_data_location_memory.sol | 1 - .../mapping_struct_recusrive_data_location_memory.sol | 1 - 18 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 test/libsolidity/syntaxTests/functionCalls/calldata_struct_argument_with_internal_data_type_inside.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/calldata_struct_array_argument_with_internal_data_type_inside.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/calldata_struct_array_argument_with_internal_data_type_inside_as_constructor_parameter.sol diff --git a/Changelog.md b/Changelog.md index e24cb24628..9ecf2ce556 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,8 @@ Compiler Features: Bugfixes: * Code Generator: Fix a crash when using ``@use-src`` and compiling from Yul to ewasm. * SMTChecker: Fix internal error when an unsafe target is solved more than once and the counterexample messages are different. + * Fix internal error when a function has a calldata struct argument with an internal type inside. + ### 0.8.10 (2021-11-09) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 05fdc489bb..5cc208d698 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -387,7 +387,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function) _var.referenceLocation() == VariableDeclaration::Location::Storage && !m_currentContract->abstract() ) - m_errorReporter.typeError( + m_errorReporter.fatalTypeError( 3644_error, _var.location(), "This parameter has a type that can only be used internally. " @@ -403,7 +403,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function) solAssert(!message.empty(), "Expected detailed error message!"); if (_function.isConstructor()) message += " You can make the contract abstract to avoid this problem."; - m_errorReporter.typeError(4103_error, _var.location(), message); + m_errorReporter.fatalTypeError(4103_error, _var.location(), message); } else if ( !useABICoderV2() && diff --git a/test/libsolidity/syntaxTests/abiEncoder/external_functions_taking_internal_types_nested_struct_with_mapping.sol b/test/libsolidity/syntaxTests/abiEncoder/external_functions_taking_internal_types_nested_struct_with_mapping.sol index 78660bdae4..9c82812e96 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/external_functions_taking_internal_types_nested_struct_with_mapping.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/external_functions_taking_internal_types_nested_struct_with_mapping.sol @@ -7,4 +7,3 @@ contract C { } // ---- // TypeError 4103: (132-140): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (132-140): Type struct C.S is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/abiEncoder/external_functions_taking_internal_types_struct_with_mapping.sol b/test/libsolidity/syntaxTests/abiEncoder/external_functions_taking_internal_types_struct_with_mapping.sol index 297f809fd6..144962c2a0 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/external_functions_taking_internal_types_struct_with_mapping.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/external_functions_taking_internal_types_struct_with_mapping.sol @@ -6,4 +6,3 @@ contract C { } // ---- // TypeError 4103: (105-113): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (105-113): Type struct C.S is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/array/function_mapping.sol b/test/libsolidity/syntaxTests/array/function_mapping.sol index 531ef6c7b6..3f64c081c3 100644 --- a/test/libsolidity/syntaxTests/array/function_mapping.sol +++ b/test/libsolidity/syntaxTests/array/function_mapping.sol @@ -5,4 +5,3 @@ contract Test { } // ---- // TypeError 4103: (66-98): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (66-98): Type mapping(uint256 => uint256)[] is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/constructor/constructor_mapping_memory.sol b/test/libsolidity/syntaxTests/constructor/constructor_mapping_memory.sol index 266a440d63..b9e0ed801d 100644 --- a/test/libsolidity/syntaxTests/constructor/constructor_mapping_memory.sol +++ b/test/libsolidity/syntaxTests/constructor/constructor_mapping_memory.sol @@ -3,4 +3,3 @@ contract A { } // ---- // TypeError 4103: (29-59): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. You can make the contract abstract to avoid this problem. -// TypeError 4061: (29-59): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/functionCalls/calldata_struct_argument_with_internal_data_type_inside.sol b/test/libsolidity/syntaxTests/functionCalls/calldata_struct_argument_with_internal_data_type_inside.sol new file mode 100644 index 0000000000..729dba7786 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/calldata_struct_argument_with_internal_data_type_inside.sol @@ -0,0 +1,8 @@ +contract C { + struct S { + function() a; + } + function f(S calldata) public {} +} +// ---- +// TypeError 4103: (56-66): Internal type is not allowed for public or external functions. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/functionCalls/calldata_struct_array_argument_with_internal_data_type_inside.sol b/test/libsolidity/syntaxTests/functionCalls/calldata_struct_array_argument_with_internal_data_type_inside.sol new file mode 100644 index 0000000000..f618934e3d --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/calldata_struct_array_argument_with_internal_data_type_inside.sol @@ -0,0 +1,8 @@ +contract C { + struct S { + function() a; + } + function f(S[2] calldata) public {} +} +// ---- +// TypeError 4103: (56-69): Internal type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/functionCalls/calldata_struct_array_argument_with_internal_data_type_inside_as_constructor_parameter.sol b/test/libsolidity/syntaxTests/functionCalls/calldata_struct_array_argument_with_internal_data_type_inside_as_constructor_parameter.sol new file mode 100644 index 0000000000..796b0fc586 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/calldata_struct_array_argument_with_internal_data_type_inside_as_constructor_parameter.sol @@ -0,0 +1,8 @@ +contract C { + struct S { + function() a; + } + constructor (S[2] storage) public {} +} +// ---- +// TypeError 3644: (58-70): This parameter has a type that can only be used internally. You can make the contract abstract to avoid this problem. diff --git a/test/libsolidity/syntaxTests/structs/calldata_struct_mapping_function.sol b/test/libsolidity/syntaxTests/structs/calldata_struct_mapping_function.sol index dcdbad68bc..9ff30c6ec0 100644 --- a/test/libsolidity/syntaxTests/structs/calldata_struct_mapping_function.sol +++ b/test/libsolidity/syntaxTests/structs/calldata_struct_mapping_function.sol @@ -12,4 +12,3 @@ contract test { } // ---- // TypeError 4103: (155-167): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (155-167): Type struct test.S is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_nested_mapping_memory.sol b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_nested_mapping_memory.sol index 6009ee94d2..c8708e3e0d 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_nested_mapping_memory.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_nested_mapping_memory.sol @@ -7,4 +7,3 @@ library a { } // ---- // TypeError 4103: (149-157): Recursive structs can only be passed as storage pointers to libraries, not as memory objects to contract functions. -// TypeError 4061: (149-157): Type struct a.b is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol index 72c2a12a85..f959394d1f 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol @@ -3,4 +3,3 @@ contract c { } // ---- // TypeError 4103: (29-61): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (29-61): Type mapping(uint256 => uint256)[] is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol index 3bc5d7a29c..1281e4b514 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol @@ -3,4 +3,3 @@ contract c { } // ---- // TypeError 4103: (29-59): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (29-59): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol index f8a6666750..667c0b1013 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol @@ -3,4 +3,3 @@ contract c { } // ---- // TypeError 4103: (29-57): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (29-57): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_function_calldata.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_function_calldata.sol index 1301a03c3c..8b780ea8d4 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_function_calldata.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_function_calldata.sol @@ -9,4 +9,3 @@ contract test { } // ---- // TypeError 4103: (121-133): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (121-133): Type struct test.S is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol index 4d06bad5a4..6594401c6e 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol @@ -4,4 +4,3 @@ contract C { } // ---- // TypeError 4103: (51-79): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (51-79): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_struct_data_location_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_data_location_memory.sol index 8208c2e2e8..399f7c6ae4 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_struct_data_location_memory.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_data_location_memory.sol @@ -5,4 +5,3 @@ contract C { } // ---- // TypeError 4103: (104-112): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (104-112): Type struct C.S is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol index fa09bdeaee..49cf314873 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol @@ -7,4 +7,3 @@ contract C { } // ---- // TypeError 4103: (148-156): Types containing (nested) mappings can only be parameters or return variables of internal or library functions. -// TypeError 4061: (148-156): Type struct C.U is only valid in storage because it contains a (nested) mapping. From 0cece8e6e745708dfeda209b884301de0d5f9931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 28 Oct 2021 22:34:48 +0200 Subject: [PATCH 0053/1704] CI: Optimize machine sizes for best speed/cost ratio --- .circleci/build_win.ps1 | 4 +- .circleci/config.yml | 155 +++++++++++++++++++++++++++++----------- 2 files changed, 115 insertions(+), 44 deletions(-) diff --git a/.circleci/build_win.ps1 b/.circleci/build_win.ps1 index 9be967c970..730bb63195 100644 --- a/.circleci/build_win.ps1 +++ b/.circleci/build_win.ps1 @@ -20,7 +20,7 @@ cd build $boost_dir=(Resolve-Path $PSScriptRoot\..\deps\boost\lib\cmake\Boost-*) ..\deps\cmake\bin\cmake -G "Visual Studio 16 2019" -DBoost_DIR="$boost_dir\" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_INSTALL_PREFIX="$PSScriptRoot\..\upload" -DUSE_Z3=OFF .. if ( -not $? ) { throw "CMake configure failed." } -msbuild solidity.sln /p:Configuration=Release /m:5 /v:minimal +msbuild solidity.sln /p:Configuration=Release /m:10 /v:minimal if ( -not $? ) { throw "Build failed." } -..\deps\cmake\bin\cmake --build . -j 5 --target install --config Release +..\deps\cmake\bin\cmake --build . -j 10 --target install --config Release if ( -not $? ) { throw "Install target failed." } diff --git a/.circleci/config.yml b/.circleci/config.yml index cadd37ab23..5a8968deac 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -226,6 +226,14 @@ defaults: - image: << pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image >> environment: TERM: xterm + MAKEFLAGS: -j 3 + + - base_ubuntu1604_clang_small: &base_ubuntu1604_clang_small + <<: *base_ubuntu1604_clang + resource_class: small + environment: + TERM: xterm + MAKEFLAGS: -j 2 - base_ubuntu2004_clang: &base_ubuntu2004_clang docker: @@ -236,20 +244,44 @@ defaults: CXX: clang++ MAKEFLAGS: -j 3 - - base_ubuntu2004_clang_xlarge: &base_ubuntu2004_clang_xlarge + - base_ubuntu2004_clang_small: &base_ubuntu2004_clang_small <<: *base_ubuntu2004_clang - resource_class: xlarge + resource_class: small environment: TERM: xterm CC: clang CXX: clang++ - MAKEFLAGS: -j 10 + MAKEFLAGS: -j 2 + + - base_ubuntu2004_clang_large: &base_ubuntu2004_clang_large + <<: *base_ubuntu2004_clang + resource_class: large + environment: + TERM: xterm + CC: clang + CXX: clang++ + MAKEFLAGS: -j 5 - base_ubuntu2004: &base_ubuntu2004 docker: - image: << pipeline.parameters.ubuntu-2004-docker-image >> environment: TERM: xterm + MAKEFLAGS: -j 3 + + - base_ubuntu2004_small: &base_ubuntu2004_small + <<: *base_ubuntu2004 + resource_class: small + environment: + TERM: xterm + MAKEFLAGS: -j 2 + + - base_ubuntu2004_large: &base_ubuntu2004_large + <<: *base_ubuntu2004 + resource_class: large + environment: + TERM: xterm + MAKEFLAGS: -j 5 - base_ubuntu2004_xlarge: &base_ubuntu2004_xlarge <<: *base_ubuntu2004 @@ -258,29 +290,48 @@ defaults: TERM: xterm MAKEFLAGS: -j 10 - - base_buildpack_focal: &base_buildpack_focal + - base_buildpack_focal_small: &base_buildpack_focal_small docker: - image: buildpack-deps:focal + resource_class: small environment: TERM: xterm + MAKEFLAGS: -j 2 - - base_buildpack_latest: &base_buildpack_latest + - base_buildpack_latest_small: &base_buildpack_latest_small docker: - image: buildpack-deps:latest + resource_class: small environment: TERM: xterm + MAKEFLAGS: -j 2 - base_archlinux: &base_archlinux docker: - image: archlinux:base environment: TERM: xterm + MAKEFLAGS: -j 3 + + - base_archlinux_large: &base_archlinux_large + docker: + - image: archlinux:base + resource_class: large + environment: + TERM: xterm + MAKEFLAGS: -j 5 - base_win_powershell: &base_win_powershell executor: name: win/default shell: powershell.exe + - base_win_powershell_large: &base_win_powershell_large + executor: + name: win/default + shell: powershell.exe + size: large + - base_win_cmd: &base_win_cmd executor: name: win/default @@ -291,26 +342,31 @@ defaults: xcode: "11.0.0" environment: TERM: xterm + MAKEFLAGS: -j 5 - - base_ems_xlarge: &base_ems_xlarge + - base_ems_large: &base_ems_large docker: - image: << pipeline.parameters.emscripten-docker-image >> - resource_class: xlarge + resource_class: large environment: TERM: xterm - MAKEFLAGS: -j 10 + MAKEFLAGS: -j 5 - - base_python: &base_python + - base_python_small: &base_python_small docker: - image: circleci/python:3.6 + resource_class: small environment: TERM: xterm + MAKEFLAGS: -j 2 - - base_node_latest: &base_node_latest + - base_node_latest_small: &base_node_latest_small docker: - image: circleci/node + resource_class: small environment: TERM: xterm + MAKEFLAGS: -j 2 # -------------------------------------------------------------------------- # Workflow Templates @@ -394,7 +450,7 @@ defaults: jobs: chk_spelling: - <<: *base_python + <<: *base_python_small steps: - checkout - attach_workspace: @@ -409,7 +465,7 @@ jobs: - gitter_notify_failure_unless_pr chk_docs_examples: - <<: *base_node_latest + <<: *base_node_latest_small steps: - checkout - attach_workspace: @@ -423,7 +479,7 @@ jobs: - gitter_notify_failure_unless_pr chk_coding_style: - <<: *base_buildpack_focal + <<: *base_buildpack_focal_small steps: - checkout - run: @@ -441,7 +497,7 @@ jobs: - gitter_notify_failure_unless_pr chk_errorcodes: - <<: *base_python + <<: *base_python_small steps: - checkout - run: @@ -450,7 +506,7 @@ jobs: - gitter_notify_failure_unless_pr chk_pylint: - <<: *base_buildpack_focal + <<: *base_buildpack_focal_small steps: - checkout - run: @@ -466,7 +522,7 @@ jobs: - gitter_notify_failure_unless_pr chk_antlr_grammar: - <<: *base_buildpack_focal + <<: *base_buildpack_focal_small steps: - checkout - run: @@ -478,7 +534,7 @@ jobs: - gitter_notify_failure_unless_pr chk_buglist: - <<: *base_node_latest + <<: *base_node_latest_small steps: - checkout - run: @@ -493,7 +549,7 @@ jobs: - gitter_notify_failure_unless_pr chk_proofs: - <<: *base_buildpack_latest + <<: *base_buildpack_latest_small steps: - checkout - run: @@ -506,14 +562,14 @@ jobs: - gitter_notify_failure_unless_pr chk_docs_pragma_min_version: - <<: *base_ubuntu2004 + <<: *base_ubuntu2004_small steps: - checkout - run: *run_docs_pragma_min_version - gitter_notify_failure_unless_pr t_ubu_pyscripts: - <<: *base_ubuntu2004 + <<: *base_ubuntu2004_small steps: - checkout - run: @@ -532,6 +588,8 @@ jobs: - gitter_notify_failure_unless_pr b_ubu: &b_ubu + # 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. <<: *base_ubuntu2004_xlarge steps: - checkout @@ -544,10 +602,11 @@ jobs: # x64 ASAN build, for testing for memory related bugs b_ubu_asan: &b_ubu_asan - <<: *base_ubuntu2004_xlarge + # Runs slightly faster on large and xlarge but we only run it nightly so efficiency matters more. + <<: *base_ubuntu2004 environment: CMAKE_OPTIONS: -DSANITIZE=address - MAKEFLAGS: -j 10 + MAKEFLAGS: -j 3 CMAKE_BUILD_TYPE: Release steps: - checkout @@ -557,7 +616,7 @@ jobs: - gitter_notify_failure_unless_pr b_ubu_clang: &b_ubu_clang - <<: *base_ubuntu2004_clang_xlarge + <<: *base_ubuntu2004_clang_large steps: - checkout - run: *run_build @@ -566,6 +625,7 @@ jobs: - gitter_notify_failure_unless_pr b_ubu_asan_clang: &b_ubu_asan_clang + # This runs a bit faster on large and xlarge but on nightly efficiency matters more. <<: *base_ubuntu2004_clang environment: CC: clang @@ -580,6 +640,7 @@ jobs: - 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 @@ -600,9 +661,10 @@ jobs: MAKEFLAGS: -j 10 b_ubu_static: - <<: *base_ubuntu2004_xlarge + # Runs 2x faster on large and 3x on xlarge but no other jobs depend on it we can live with medium. + <<: *base_ubuntu2004 environment: - MAKEFLAGS: -j 10 + MAKEFLAGS: -j 3 CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON steps: - checkout @@ -614,11 +676,12 @@ jobs: - gitter_notify_failure_unless_pr b_ubu_codecov: - <<: *base_ubuntu2004_xlarge + # Runs ~30% faster on large but we only run it nightly so efficiency matters more. + <<: *base_ubuntu2004 environment: COVERAGE: ON CMAKE_BUILD_TYPE: Debug - MAKEFLAGS: -j 10 + MAKEFLAGS: -j 3 steps: - checkout - run: *run_build @@ -651,11 +714,11 @@ jobs: # Builds in C++20 mode and uses debug build in order to speed up. # Do *NOT* store any artifacts or workspace as we don't run tests on this build. b_ubu_cxx20: - <<: *base_ubuntu2004_xlarge + <<: *base_ubuntu2004_large environment: CMAKE_BUILD_TYPE: Debug CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 -DUSE_CVC4=OFF - MAKEFLAGS: -j 10 + MAKEFLAGS: -j 5 steps: - checkout - run: *run_build @@ -671,7 +734,7 @@ jobs: - gitter_notify_failure_unless_pr t_ubu_ossfuzz: &t_ubu_ossfuzz - <<: *base_ubuntu1604_clang + <<: *base_ubuntu1604_clang_small steps: - checkout - attach_workspace: @@ -688,10 +751,10 @@ jobs: - gitter_notify_success_unless_pr b_archlinux: - <<: *base_archlinux + <<: *base_archlinux_large environment: TERM: xterm - MAKEFLAGS: -j 3 + MAKEFLAGS: -j 5 steps: - run: name: Install build dependencies @@ -772,7 +835,7 @@ jobs: - gitter_notify_failure_unless_pr b_ems: - <<: *base_ems_xlarge + <<: *base_ems_large steps: - checkout - run: @@ -793,7 +856,7 @@ jobs: - gitter_notify_failure_unless_pr b_docs: - <<: *base_ubuntu2004 + <<: *base_ubuntu2004_small steps: - checkout - run: *setup_prerelease_commit_hash @@ -850,14 +913,15 @@ jobs: <<: *t_ubu_soltest_all t_ubu_cli: &t_ubu_cli - <<: *base_ubuntu2004 + <<: *base_ubuntu2004_small <<: *steps_cmdline_tests t_ubu_release_cli: &t_ubu_release_cli <<: *t_ubu_cli t_ubu_asan_cli: - <<: *base_ubuntu2004 + # Runs slightly faster on medium but we only run it nightly so efficiency matters more. + <<: *base_ubuntu2004_small environment: TERM: xterm ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 @@ -889,10 +953,11 @@ jobs: <<: *steps_soltest t_ubu_ubsan_clang_cli: - <<: *base_ubuntu2004_clang + <<: *base_ubuntu2004_clang_small <<: *steps_cmdline_tests t_ems_solcjs: + # Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small). <<: *base_ubuntu2004 steps: - checkout @@ -913,7 +978,7 @@ jobs: - gitter_notify_failure_unless_pr t_ems_ext_hardhat: - <<: *base_node_latest + <<: *base_node_latest_small environment: TERM: xterm HARDHAT_TESTS_SOLC_PATH: /tmp/workspace/soljson.js @@ -948,8 +1013,12 @@ jobs: nodejs_version: type: string default: latest + resource_class: + type: string + default: small docker: - image: circleci/node:<> + resource_class: <> # NOTE: Each external test does 3 separate compile&test runs parallelism: 3 environment: @@ -971,7 +1040,7 @@ jobs: - gitter_notify_failure_unless_pr b_win: &b_win - <<: *base_win_powershell + <<: *base_win_powershell_large steps: # NOTE: Not disabling git's core.autocrlf here because we want to build using the typical Windows config. - checkout @@ -1028,7 +1097,7 @@ jobs: <<: *t_win_soltest b_bytecode_ubu: - <<: *base_ubuntu2004 + <<: *base_ubuntu2004_small steps: - checkout - attach_workspace: @@ -1094,7 +1163,7 @@ jobs: - gitter_notify_failure_unless_pr b_bytecode_ems: - <<: *base_node_latest + <<: *base_node_latest_small environment: SOLC_EMSCRIPTEN: "On" steps: @@ -1111,7 +1180,7 @@ jobs: - gitter_notify_failure_unless_pr t_bytecode_compare: - <<: *base_ubuntu2004 + <<: *base_ubuntu2004_small environment: REPORT_FILES: | bytecode-report-emscripten.txt @@ -1251,6 +1320,7 @@ workflows: project: zeppelin # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' + resource_class: medium - t_ems_ext: <<: *workflow_emscripten name: t_ems_test_ext_ens @@ -1321,3 +1391,4 @@ workflows: <<: *workflow_emscripten name: t_ems_test_ext_colony project: colony + resource_class: medium From 075d7b61527fee52cf8be0b9e7b05295be6a8445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 28 Oct 2021 13:19:04 +0200 Subject: [PATCH 0054/1704] CI: Remove separate compile-only runs for external tests that execute quickly --- .circleci/config.yml | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5a8968deac..af3da5886d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1269,6 +1269,7 @@ workflows: - t_ems_solcjs: *workflow_emscripten - t_ems_ext_hardhat: *workflow_emscripten + # Separate compile-only runs of those external tests where a full run takes much longer. - t_ems_ext: <<: *workflow_emscripten name: t_ems_compile_ext_colony @@ -1281,24 +1282,6 @@ workflows: project: gnosis compile_only: 1 nodejs_version: '14' - - t_ems_ext: - <<: *workflow_emscripten - name: t_ems_compile_ext_gnosis_v2 - project: gnosis-v2 - compile_only: 1 - nodejs_version: '14' - - t_ems_ext: - <<: *workflow_emscripten - name: t_ems_compile_ext_zeppelin - project: zeppelin - compile_only: 1 - - t_ems_ext: - <<: *workflow_emscripten - name: t_ems_compile_ext_ens - project: ens - compile_only: 1 - # NOTE: One of the dependencies (fsevents) fails to build its native extension on node.js 12+. - nodejs_version: '10' # FIXME: Gnosis tests are pretty flaky right now. They often fail on CircleCI due to random ProviderError # and there are also other less frequent problems. See https://github.com/gnosis/safe-contracts/issues/216. From b96d238c2389b3557f9cb0d3a5c29c550145ff99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 5 Nov 2021 17:26:52 +0100 Subject: [PATCH 0055/1704] CI: Double the number of threads for jobs that did slow down after switching to a smaller resource class --- .circleci/config.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index af3da5886d..312695ebf7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -617,6 +617,11 @@ jobs: b_ubu_clang: &b_ubu_clang <<: *base_ubuntu2004_clang_large + environment: + TERM: xterm + CC: clang + CXX: clang++ + MAKEFLAGS: -j 10 steps: - checkout - run: *run_build @@ -664,7 +669,7 @@ jobs: # Runs 2x faster on large and 3x on xlarge but no other jobs depend on it we can live with medium. <<: *base_ubuntu2004 environment: - MAKEFLAGS: -j 3 + MAKEFLAGS: -j 5 CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON steps: - checkout @@ -718,7 +723,7 @@ jobs: environment: CMAKE_BUILD_TYPE: Debug CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 -DUSE_CVC4=OFF - MAKEFLAGS: -j 5 + MAKEFLAGS: -j 10 steps: - checkout - run: *run_build @@ -836,6 +841,9 @@ jobs: b_ems: <<: *base_ems_large + environment: + TERM: xterm + MAKEFLAGS: -j 10 steps: - checkout - run: @@ -1303,7 +1311,7 @@ workflows: project: zeppelin # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - resource_class: medium + resource_class: large - t_ems_ext: <<: *workflow_emscripten name: t_ems_test_ext_ens From 25a26d2f8bca41e9f488bc8b2eef558da32fb27a Mon Sep 17 00:00:00 2001 From: minami Date: Sun, 5 Dec 2021 16:57:48 +0900 Subject: [PATCH 0056/1704] Fix cheatsheet --- docs/cheatsheet.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index d36a963603..17537914ac 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -81,7 +81,7 @@ Global Variables - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: :ref:`ABI `-encodes the given arguments starting from the second and prepends the given four-byte selector - ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent - to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``` + to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)`` - ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of arguments to one byte array` - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) From 907405e2e06082389be99eb763e797c142f757a1 Mon Sep 17 00:00:00 2001 From: minami Date: Sun, 5 Dec 2021 16:57:59 +0900 Subject: [PATCH 0057/1704] Fix units-and-global-variables --- docs/units-and-global-variables.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 8a6173280a..ac11e08067 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -135,7 +135,7 @@ ABI Encoding and Decoding Functions - ``abi.encode(...) returns (bytes memory)``: ABI-encodes the given arguments - ``abi.encodePacked(...) returns (bytes memory)``: Performs :ref:`packed encoding ` of the given arguments. Note that packed encoding can be ambiguous! - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: ABI-encodes the given arguments starting from the second and prepends the given four-byte selector -- ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)``` +- ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`` .. note:: These encoding functions can be used to craft data for external function calls without actually From 6bafeca8a25ec87f50ee2c2de8a8eb1cd549a7e9 Mon Sep 17 00:00:00 2001 From: minami Date: Sun, 5 Dec 2021 16:58:03 +0900 Subject: [PATCH 0058/1704] Fix yul --- docs/yul.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/yul.rst b/docs/yul.rst index ef44a575ba..219905cd5f 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -166,7 +166,7 @@ Inside a code block, the following elements can be used - if statements, e.g. ``if lt(a, b) { sstore(0, 1) }`` - switch statements, e.g. ``switch mload(0) case 0 { revert() } default { mstore(0, 1) }`` - for loops, e.g. ``for { let i := 0} lt(i, 10) { i := add(i, 1) } { mstore(i, 7) }`` -- function definitions, e.g. ``function f(a, b) -> c { c := add(a, b) }``` +- function definitions, e.g. ``function f(a, b) -> c { c := add(a, b) }`` Multiple syntactical elements can follow each other simply separated by whitespace, i.e. there is no terminating ``;`` or newline required. From f0a9cd7504efa34496ab3e0897a1c0cc3b76ebd2 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 6 Dec 2021 16:15:32 +0100 Subject: [PATCH 0059/1704] Typo in changelog. --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index e24cb24628..f5be36a1bf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -104,7 +104,7 @@ Bugfixes: * SMTChecker: Fix false positive in external calls from constructors. * SMTChecker: Fix internal error on some multi-source uses of ``abi.*``, cryptographic functions and constants. * Standard JSON: Fix non-fatal errors in Yul mode being discarded if followed by a fatal error. - * Type Checker: Correct wrong error message in inline assembly complaining about ``.slot`` or ``.offset` not valid when actually ``.length`` was used. + * Type Checker: Correct wrong error message in inline assembly complaining about ``.slot`` or ``.offset`` not valid when actually ``.length`` was used. * Type Checker: Disallow modifier declarations and definitions in interfaces. * Yul Optimizer: Fix a crash in LoadResolver, when ``keccak256`` has particular non-identifier arguments. From d41415325803e97479d111bd70465d7867e0a19c Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 6 Dec 2021 15:59:08 +0100 Subject: [PATCH 0060/1704] Some clarifications on literals. --- docs/types/value-types.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 4cb0dec4fa..49e35d9eae 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -437,14 +437,16 @@ an error. You can prepend (for integer types) or append (for bytesNN types) zero Rational and Integer Literals ----------------------------- -Integer literals are formed from a sequence of numbers in the range 0-9. +Integer literals are formed from a sequence of digits in the range 0-9. They are interpreted as decimals. For example, ``69`` means sixty nine. Octal literals do not exist in Solidity and leading zeros are invalid. -Decimal fraction literals are formed by a ``.`` with at least one number on +Decimal fractional literals are formed by a ``.`` with at least one number on one side. Examples include ``1.``, ``.1`` and ``1.3``. -Scientific notation is also supported, where the base can have fractions and the exponent cannot. +Scientific notation in the form of ``2e10`` is also supported, where the +mantissa can be fractional but the exponent has to be an integer. +The literal ``MeE`` is equivalent to ``M * 10**E``. Examples include ``2e10``, ``-2e10``, ``2e-10``, ``2.5e1``. Underscores can be used to separate the digits of a numeric literal to aid readability. From af02678dee8da8e63c90e2b822f04889843c00d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 8 Dec 2021 20:04:35 +0100 Subject: [PATCH 0061/1704] CI: Adjust job parallelism to actually match available resources - Some jobs don't actually run in parallel but have the `parallelism` setting enabled. - `soltest_all` could be parallelized much more. --- .circleci/config.yml | 4 +--- .circleci/soltest_all.sh | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 312695ebf7..3c47b55c6a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -695,7 +695,6 @@ jobs: t_ubu_codecov: <<: *base_ubuntu2004 - parallelism: 6 environment: EVM: << pipeline.parameters.evm-version >> OPTIMIZE: 1 @@ -878,7 +877,7 @@ jobs: t_ubu_soltest_all: &t_ubu_soltest_all <<: *base_ubuntu2004 - parallelism: 6 + parallelism: 15 # 7 EVM versions, each with/without optimization + 1 ABIv1/@nooptions run <<: *steps_soltest_all t_archlinux_soltest: &t_archlinux_soltest @@ -937,7 +936,6 @@ jobs: t_ubu_asan_soltest: <<: *base_ubuntu2004 - parallelism: 6 environment: EVM: << pipeline.parameters.evm-version >> OPTIMIZE: 0 diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 0c414593f3..5bd5ed9f1c 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,6 +31,7 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" +# NOTE: If you add/remove values, remember to update `parallelism` setting in CircleCI config. EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin london) DEFAULT_EVM=london [[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]] From 8ada7db7e9a0e1f0dd0647af3a5943ad294cc153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Dec 2021 15:34:07 +0100 Subject: [PATCH 0062/1704] externalTests: Fix optimizer level 2 to make it actually run without Yul optimizer --- test/externalTests/colony.sh | 1 + test/externalTests/common.sh | 2 +- test/externalTests/gnosis-v2.sh | 1 + test/externalTests/gnosis.sh | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index 3aaff44138..4f0ca07574 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -35,6 +35,7 @@ function colony_test local repo="https://github.com/solidity-external-tests/colonyNetwork.git" local branch=develop_080 local config_file="truffle.js" + # On levels 1 and 2 it compiles but tests run out of gas local min_optimizer_level=3 local max_optimizer_level=3 diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 7e651d8c0b..777df7d465 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -245,7 +245,7 @@ function optimizer_settings_for_level case "$level" in 1) echo "{enabled: false}" ;; - 2) echo "{enabled: true}" ;; + 2) echo "{enabled: true, details: {yul: false}}" ;; 3) echo "{enabled: true, details: {yul: true}}" ;; *) printError "Optimizer level not found. Please define OPTIMIZER_LEVEL=[1, 2, 3]" diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index 439a3dd91f..803e06b3a2 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -36,6 +36,7 @@ function gnosis_safe_test local repo="https://github.com/solidity-external-tests/safe-contracts.git" local branch=v2_080 local config_file="truffle-config.js" + # level 1: "Error: while migrating GnosisSafe: Returned error: base fee exceeds gas limit" local min_optimizer_level=2 local max_optimizer_level=3 diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 32b76d9c90..a419ea6e75 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -35,7 +35,8 @@ function gnosis_safe_test local repo="https://github.com/solidity-external-tests/safe-contracts.git" local branch=development_080 local config_file="truffle-config.js" - local min_optimizer_level=2 + # levels 1 and 2: "Stack too deep" error + local min_optimizer_level=3 local max_optimizer_level=3 local selected_optimizer_levels From 937597c1cd4b199389a52c1775b44f3667f26f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 9 Dec 2021 14:51:45 +0100 Subject: [PATCH 0063/1704] Use unique name for gnosis-v2 ext test --- test/externalTests/gnosis-v2.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index 803e06b3a2..f43e415674 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -63,4 +63,4 @@ function gnosis_safe_test done } -external_test Gnosis-Safe gnosis_safe_test +external_test Gnosis-Safe-V2 gnosis_safe_test From 5fb0246f1c057fcdb4e3e7e0cff8cda7489695d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 3 Dec 2021 15:26:45 +0100 Subject: [PATCH 0064/1704] Use the right config file name in ENS external test --- test/externalTests/ens.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index 9fed91be1f..c2deca5d2f 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -34,7 +34,7 @@ function ens_test { local repo="https://github.com/ensdomains/ens.git" local branch=master - local config_file="truffle-config.js" + local config_file="truffle.js" local min_optimizer_level=1 local max_optimizer_level=3 From 0edbd90f526d9792c381b10974dc9039e4b6724f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 3 Dec 2021 12:53:50 +0100 Subject: [PATCH 0065/1704] externalTests: Use fail() function to simplify error checks --- test/externalTests/common.sh | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 7e651d8c0b..4020fc7a1d 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -35,18 +35,12 @@ function print_optimizer_levels_or_exit function verify_input { - if [ ! -f "$1" ]; then - printError "Usage: $0 " - exit 1 - fi + [[ -f "$1" ]] || fail "Usage: $0 " } function verify_version_input { - if [ -z "$1" ] || [ ! -f "$1" ] || [ -z "$2" ]; then - printError "Usage: $0 " - exit 1 - fi + [[ $1 != "" && -f "$1" && $2 != "" ]] || fail "Usage: $0 " } function setup @@ -248,8 +242,7 @@ function optimizer_settings_for_level 2) echo "{enabled: true}" ;; 3) echo "{enabled: true, details: {yul: true}}" ;; *) - printError "Optimizer level not found. Please define OPTIMIZER_LEVEL=[1, 2, 3]" - exit 1 + fail "Optimizer level not found. Please define OPTIMIZER_LEVEL=[1, 2, 3]" ;; esac } @@ -356,10 +349,7 @@ function external_test echo "===========================" DIR=$(mktemp -d -t "ext-test-${name}-XXXXXX") ( - if [ -z "$main_fn" ]; then - printError "Test main function not defined." - exit 1 - fi + [[ "$main_fn" != "" ]] || fail "Test main function not defined." $main_fn ) rm -rf "$DIR" From 081b80ccb2170528e501ab451296407d5f434078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 3 Dec 2021 12:57:39 +0100 Subject: [PATCH 0066/1704] externalTests: Refactor setup and input verification --- test/externalTests.sh | 19 +++++------ test/externalTests/colony.sh | 6 ++-- test/externalTests/common.sh | 45 ++++++++++----------------- test/externalTests/ens.sh | 6 ++-- test/externalTests/gnosis-v2.sh | 7 ++--- test/externalTests/gnosis.sh | 6 ++-- test/externalTests/solc-js/solc-js.sh | 6 ++-- test/externalTests/zeppelin.sh | 8 ++--- 8 files changed, 44 insertions(+), 59 deletions(-) diff --git a/test/externalTests.sh b/test/externalTests.sh index 28af6f835a..c9b30d0fe4 100755 --- a/test/externalTests.sh +++ b/test/externalTests.sh @@ -28,25 +28,20 @@ set -e -if [ ! -f "$1" ] -then - echo "Usage: $0 " - exit 1 -fi - -SOLJSON="$1" REPO_ROOT="$(dirname "$0")" source scripts/common.sh source test/externalTests/common.sh +verify_input "$@" + printTask "Running external tests..." -"$REPO_ROOT/externalTests/zeppelin.sh" "$SOLJSON" -"$REPO_ROOT/externalTests/gnosis.sh" "$SOLJSON" -"$REPO_ROOT/externalTests/gnosis-v2.sh" "$SOLJSON" -"$REPO_ROOT/externalTests/colony.sh" "$SOLJSON" -"$REPO_ROOT/externalTests/ens.sh" "$SOLJSON" +"$REPO_ROOT/externalTests/zeppelin.sh" "$@" +"$REPO_ROOT/externalTests/gnosis.sh" "$@" +"$REPO_ROOT/externalTests/gnosis-v2.sh" "$@" +"$REPO_ROOT/externalTests/colony.sh" "$@" +"$REPO_ROOT/externalTests/ens.sh" "$@" # Disabled temporarily as it needs to be updated to latest Truffle first. #test_truffle Gnosis https://github.com/axic/pm-contracts.git solidity-050 diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index 3aaff44138..16c8594068 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -24,8 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh -verify_input "$1" -SOLJSON="$1" +verify_input "$@" +BINARY_PATH="$1" function compile_fn { yarn run provision:token:contracts; } function test_fn { yarn run test:contracts; } @@ -42,7 +42,7 @@ function colony_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$SOLJSON" + setup_solcjs "$DIR" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" neutralize_package_json_hooks diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 4020fc7a1d..5ee22873a9 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -35,52 +35,41 @@ function print_optimizer_levels_or_exit function verify_input { - [[ -f "$1" ]] || fail "Usage: $0 " -} + local binary_path="$1" -function verify_version_input -{ - [[ $1 != "" && -f "$1" && $2 != "" ]] || fail "Usage: $0 " + (( $# == 1 )) || fail "Usage: $0 " + [[ -f "$binary_path" ]] || fail "The compiler binary does not exist at '${binary_path}'" } -function setup -{ - local soljson="$1" - local branch="$2" - - setup_solcjs "$DIR" "$soljson" "$branch" "solc" - cd solc -} function setup_solcjs { - local dir="$1" - local soljson="$2" - local branch="${3:-master}" - local path="${4:-solc/}" + local test_dir="$1" + local binary_path="$2" + local solcjs_branch="${3:-master}" + local install_dir="${4:-solc/}" - cd "$dir" + cd "$test_dir" printLog "Setting up solc-js..." - git clone --depth 1 -b "$branch" https://github.com/ethereum/solc-js.git "$path" - - cd "$path" + git clone --depth 1 -b "$solcjs_branch" https://github.com/ethereum/solc-js.git "$install_dir" + pushd "$install_dir" npm install - cp "$soljson" soljson.js + cp "$binary_path" soljson.js SOLCVERSION=$(./solcjs --version) SOLCVERSION_SHORT=$(echo "$SOLCVERSION" | sed -En 's/^([0-9.]+).*\+commit\.[0-9a-f]+.*$/\1/p') - printLog "Using solcjs version $SOLCVERSION" - cd .. + printLog "Using compiler version $SOLCVERSION" + popd } function download_project { local repo="$1" - local branch="$2" - local dir="$3" + local solcjs_branch="$2" + local test_dir="$3" - printLog "Cloning $branch of $repo..." - git clone --depth 1 "$repo" -b "$branch" "$dir/ext" + printLog "Cloning $solcjs_branch of $repo..." + git clone --depth 1 "$repo" -b "$solcjs_branch" "$test_dir/ext" cd ext echo "Current commit hash: $(git rev-parse HEAD)" } diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index 9fed91be1f..45ff338fd0 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -24,8 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh -verify_input "$1" -export SOLJSON="$1" +verify_input "$@" +BINARY_PATH="$1" function compile_fn { npx truffle compile; } function test_fn { npm run test; } @@ -42,7 +42,7 @@ function ens_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$SOLJSON" + setup_solcjs "$DIR" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" # Use latest Truffle. Older versions crash on the output from 0.8.0. diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index 439a3dd91f..878a1f2778 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -24,10 +24,9 @@ set -e source scripts/common.sh source test/externalTests/common.sh -verify_input "$1" -SOLJSON="$1" +verify_input "$@" +BINARY_PATH="$1" -function install_fn { npm install --package-lock; } function compile_fn { npx truffle compile; } function test_fn { npm test; } @@ -43,7 +42,7 @@ function gnosis_safe_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$SOLJSON" + setup_solcjs "$DIR" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" sed -i 's|github:gnosis/mock-contract#sol_0_5_0|github:solidity-external-tests/mock-contract#master_080|g' package.json diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 32b76d9c90..c721ae8807 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -24,8 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh -verify_input "$1" -SOLJSON="$1" +verify_input "$@" +BINARY_PATH="$1" function compile_fn { npx truffle compile; } function test_fn { npm test; } @@ -42,7 +42,7 @@ function gnosis_safe_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$SOLJSON" + setup_solcjs "$DIR" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" sed -i 's|github:gnosis/mock-contract#sol_0_5_0|github:solidity-external-tests/mock-contract#master_080|g' package.json diff --git a/test/externalTests/solc-js/solc-js.sh b/test/externalTests/solc-js/solc-js.sh index a3b24db9ec..4ca6e3d008 100755 --- a/test/externalTests/solc-js/solc-js.sh +++ b/test/externalTests/solc-js/solc-js.sh @@ -24,10 +24,11 @@ set -e source scripts/common.sh source test/externalTests/common.sh -verify_version_input "$1" "$2" SOLJSON="$1" VERSION="$2" +[[ $SOLJSON != "" && -f "$SOLJSON" && $VERSION != "" ]] || fail "Usage: $0 " + function compile_fn { echo "Nothing to compile."; } function test_fn { npm test; } @@ -37,7 +38,8 @@ function solcjs_test SOLCJS_INPUT_DIR="$TEST_DIR"/test/externalTests/solc-js # set up solc-js on the branch specified - setup "$SOLJSON" master + setup_solcjs "$DIR" "$SOLJSON" master solc/ + cd solc/ printLog "Updating index.js file..." echo "require('./determinism.js');" >> test/index.js diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index cd290b860f..86530bcc3c 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -24,8 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh -verify_input "$1" -SOLJSON="$1" +verify_input "$@" +BINARY_PATH="$1" function compile_fn { npm run compile; } function test_fn { npm test; } @@ -42,11 +42,11 @@ function zeppelin_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$SOLJSON" + setup_solcjs "$DIR" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" neutralize_package_json_hooks - force_hardhat_compiler_binary "$config_file" "$SOLJSON" + force_hardhat_compiler_binary "$config_file" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$min_optimizer_level" npm install From 68ff073b3b165132790819720c4f626c53d0c159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 3 Dec 2021 13:44:03 +0100 Subject: [PATCH 0067/1704] externalTests.sh: Remove outdated commented-out command to run gnosis - A newer command is already enabled above it --- test/externalTests.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/externalTests.sh b/test/externalTests.sh index c9b30d0fe4..86f13401e9 100755 --- a/test/externalTests.sh +++ b/test/externalTests.sh @@ -42,6 +42,3 @@ printTask "Running external tests..." "$REPO_ROOT/externalTests/gnosis-v2.sh" "$@" "$REPO_ROOT/externalTests/colony.sh" "$@" "$REPO_ROOT/externalTests/ens.sh" "$@" - -# Disabled temporarily as it needs to be updated to latest Truffle first. -#test_truffle Gnosis https://github.com/axic/pm-contracts.git solidity-050 From eb8e304b47c8a9da2004e92d6ba2185bdee31825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 3 Dec 2021 14:51:05 +0100 Subject: [PATCH 0068/1704] externalTests: Add support for using a native binary --- .circleci/config.yml | 2 +- test/externalTests/colony.sh | 12 ++-- test/externalTests/common.sh | 89 +++++++++++++++++++-------- test/externalTests/ens.sh | 12 ++-- test/externalTests/gnosis-v2.sh | 12 ++-- test/externalTests/gnosis.sh | 12 ++-- test/externalTests/solc-js/solc-js.sh | 2 +- test/externalTests/zeppelin.sh | 7 ++- 8 files changed, 97 insertions(+), 51 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 312695ebf7..1013432223 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1044,7 +1044,7 @@ jobs: - run: name: External <> tests command: | - test/externalTests/<>.sh /tmp/workspace/soljson.js + test/externalTests/<>.sh solcjs /tmp/workspace/soljson.js - gitter_notify_failure_unless_pr b_win: &b_win diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index 16c8594068..dff745d683 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -25,7 +25,8 @@ source scripts/common.sh source test/externalTests/common.sh verify_input "$@" -BINARY_PATH="$1" +BINARY_TYPE="$1" +BINARY_PATH="$2" function compile_fn { yarn run provision:token:contracts; } function test_fn { yarn run test:contracts; } @@ -42,11 +43,12 @@ function colony_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$BINARY_PATH" + setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" + [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "${DIR}/solc" "$min_optimizer_level" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" yarn git submodule update --init @@ -56,10 +58,10 @@ function colony_test cd .. replace_version_pragmas - force_solc_modules "${DIR}/solc" + [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn + truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$level" compile_fn test_fn done } diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 5ee22873a9..b36861d07c 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -35,31 +35,43 @@ function print_optimizer_levels_or_exit function verify_input { - local binary_path="$1" + local binary_type="$1" + local binary_path="$2" - (( $# == 1 )) || fail "Usage: $0 " + (( $# == 2 )) || fail "Usage: $0 native|solcjs " + [[ $binary_type == native || $binary_type == solcjs ]] || fail "Invalid binary type: '${binary_type}'. Must be either 'native' or 'solcjs'." [[ -f "$binary_path" ]] || fail "The compiler binary does not exist at '${binary_path}'" } - -function setup_solcjs +function setup_solc { local test_dir="$1" - local binary_path="$2" - local solcjs_branch="${3:-master}" - local install_dir="${4:-solc/}" + local binary_type="$2" + local binary_path="$3" + local solcjs_branch="${4:-master}" + local install_dir="${5:-solc/}" + + [[ $binary_type == native || $binary_type == solcjs ]] || assertFail cd "$test_dir" - printLog "Setting up solc-js..." - git clone --depth 1 -b "$solcjs_branch" https://github.com/ethereum/solc-js.git "$install_dir" - pushd "$install_dir" - npm install - cp "$binary_path" soljson.js - SOLCVERSION=$(./solcjs --version) + if [[ $binary_type == solcjs ]] + then + printLog "Setting up solc-js..." + git clone --depth 1 -b "$solcjs_branch" https://github.com/ethereum/solc-js.git "$install_dir" + + pushd "$install_dir" + npm install + cp "$binary_path" soljson.js + SOLCVERSION=$(./solcjs --version) + popd + else + printLog "Setting up solc..." + SOLCVERSION=$("$binary_path" --version | tail -n 1 | sed -n -E 's/^Version: (.*)$/\1/p') + fi + SOLCVERSION_SHORT=$(echo "$SOLCVERSION" | sed -En 's/^([0-9.]+).*\+commit\.[0-9a-f]+.*$/\1/p') printLog "Using compiler version $SOLCVERSION" - popd } function download_project @@ -127,13 +139,19 @@ function force_solc_modules function force_truffle_compiler_settings { local config_file="$1" - local solc_path="$2" - local level="$3" - local evm_version="${4:-"$CURRENT_EVM_VERSION"}" + local binary_type="$2" + local solc_path="$3" + local level="$4" + local evm_version="${5:-"$CURRENT_EVM_VERSION"}" + + [[ $binary_type == native || $binary_type == solcjs ]] || assertFail + + [[ $binary_type == native ]] && local solc_path="native" printLog "Forcing Truffle compiler settings..." echo "-------------------------------------" echo "Config file: $config_file" + echo "Binary type: $binary_type" echo "Compiler path: $solc_path" echo "Optimization level: $level" echo "Optimizer settings: $(optimizer_settings_for_level "$level")" @@ -148,13 +166,15 @@ function force_truffle_compiler_settings function force_hardhat_compiler_binary { local config_file="$1" - local solc_path="$2" + local binary_type="$2" + local solc_path="$3" printLog "Configuring Hardhat..." echo "-------------------------------------" echo "Config file: ${config_file}" + echo "Binary type: ${binary_type}" echo "Compiler path: ${solc_path}" - hardhat_solc_build_subtask "$SOLCVERSION_SHORT" "$SOLCVERSION" "$solc_path" >> "$config_file" + hardhat_solc_build_subtask "$SOLCVERSION_SHORT" "$SOLCVERSION" "$binary_type" "$solc_path" >> "$config_file" } function force_hardhat_compiler_settings @@ -236,6 +256,16 @@ function optimizer_settings_for_level esac } +function replace_global_solc +{ + local solc_path="$1" + + [[ ! -e solc ]] || fail "A file named 'solc' already exists in '${PWD}'." + + ln -s "$solc_path" solc + export PATH="$PWD:$PATH" +} + function truffle_compiler_settings { local solc_path="$1" @@ -256,7 +286,13 @@ function truffle_compiler_settings function hardhat_solc_build_subtask { local solc_version="$1" local full_solc_version="$2" - local solc_path="$3" + local binary_type="$3" + local solc_path="$4" + + [[ $binary_type == native || $binary_type == solcjs ]] || assertFail + + [[ $binary_type == native ]] && local is_solcjs=false + [[ $binary_type == solcjs ]] && local is_solcjs=true echo "const {TASK_COMPILE_SOLIDITY_GET_SOLC_BUILD} = require('hardhat/builtin-tasks/task-names');" echo "const assert = require('assert');" @@ -265,7 +301,7 @@ function hardhat_solc_build_subtask { echo " assert(args.solcVersion == '${solc_version}', 'Unexpected solc version: ' + args.solcVersion)" echo " return {" echo " compilerPath: '$(realpath "$solc_path")'," - echo " isSolcJs: true," + echo " isSolcJs: ${is_solcjs}," echo " version: args.solcVersion," echo " longVersion: '${full_solc_version}'" echo " }" @@ -307,13 +343,14 @@ function compile_and_run_test function truffle_run_test { local config_file="$1" - local solc_path="$2" - local optimizer_level="$3" - local compile_fn="$4" - local test_fn="$5" + local binary_type="$2" + local solc_path="$3" + local optimizer_level="$4" + local compile_fn="$5" + local test_fn="$6" truffle_clean - force_truffle_compiler_settings "$config_file" "$solc_path" "$optimizer_level" + force_truffle_compiler_settings "$config_file" "$binary_type" "$solc_path" "$optimizer_level" compile_and_run_test compile_fn test_fn truffle_verify_compiler_version } diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index 45ff338fd0..5c7d582704 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -25,7 +25,8 @@ source scripts/common.sh source test/externalTests/common.sh verify_input "$@" -BINARY_PATH="$1" +BINARY_TYPE="$1" +BINARY_PATH="$2" function compile_fn { npx truffle compile; } function test_fn { npm run test; } @@ -42,22 +43,23 @@ function ens_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$BINARY_PATH" + setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" + [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" # Use latest Truffle. Older versions crash on the output from 0.8.0. force_truffle_version ^5.1.55 neutralize_package_lock neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "${DIR}/solc" "$min_optimizer_level" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" npm install replace_version_pragmas - force_solc_modules "${DIR}/solc" + [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn + truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$level" compile_fn test_fn done } diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index 878a1f2778..b2f6c4a830 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -25,7 +25,8 @@ source scripts/common.sh source test/externalTests/common.sh verify_input "$@" -BINARY_PATH="$1" +BINARY_TYPE="$1" +BINARY_PATH="$2" function compile_fn { npx truffle compile; } function test_fn { npm test; } @@ -42,22 +43,23 @@ function gnosis_safe_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$BINARY_PATH" + setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" + [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" sed -i 's|github:gnosis/mock-contract#sol_0_5_0|github:solidity-external-tests/mock-contract#master_080|g' package.json sed -i -E 's|"@gnosis.pm/util-contracts": "[^"]+"|"@gnosis.pm/util-contracts": "github:solidity-external-tests/util-contracts#solc-7_080"|g' package.json neutralize_package_lock neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "${DIR}/solc" "$min_optimizer_level" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" npm install --package-lock replace_version_pragmas - force_solc_modules "${DIR}/solc" + [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn + truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$level" compile_fn test_fn done } diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index c721ae8807..69d068474e 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -25,7 +25,8 @@ source scripts/common.sh source test/externalTests/common.sh verify_input "$@" -BINARY_PATH="$1" +BINARY_TYPE="$1" +BINARY_PATH="$2" function compile_fn { npx truffle compile; } function test_fn { npm test; } @@ -42,21 +43,22 @@ function gnosis_safe_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$BINARY_PATH" + setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" + [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" sed -i 's|github:gnosis/mock-contract#sol_0_5_0|github:solidity-external-tests/mock-contract#master_080|g' package.json neutralize_package_lock neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "${DIR}/solc" "$min_optimizer_level" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" npm install --package-lock replace_version_pragmas - force_solc_modules "${DIR}/solc" + [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "${DIR}/solc" "$level" compile_fn test_fn + truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$level" compile_fn test_fn done } diff --git a/test/externalTests/solc-js/solc-js.sh b/test/externalTests/solc-js/solc-js.sh index 4ca6e3d008..33b43e6430 100755 --- a/test/externalTests/solc-js/solc-js.sh +++ b/test/externalTests/solc-js/solc-js.sh @@ -38,7 +38,7 @@ function solcjs_test SOLCJS_INPUT_DIR="$TEST_DIR"/test/externalTests/solc-js # set up solc-js on the branch specified - setup_solcjs "$DIR" "$SOLJSON" master solc/ + setup_solc "$DIR" solcjs "$SOLJSON" master solc/ cd solc/ printLog "Updating index.js file..." diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 86530bcc3c..0759a3aec6 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -25,7 +25,8 @@ source scripts/common.sh source test/externalTests/common.sh verify_input "$@" -BINARY_PATH="$1" +BINARY_TYPE="$1" +BINARY_PATH="$2" function compile_fn { npm run compile; } function test_fn { npm test; } @@ -42,11 +43,11 @@ function zeppelin_test selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") print_optimizer_levels_or_exit "$selected_optimizer_levels" - setup_solcjs "$DIR" "$BINARY_PATH" + setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" neutralize_package_json_hooks - force_hardhat_compiler_binary "$config_file" "$BINARY_PATH" + force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$min_optimizer_level" npm install From f5830c451625bad5e667293ec41564ce287b6889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 7 Dec 2021 16:30:25 +0100 Subject: [PATCH 0069/1704] CI: Extend t_ems job to allow using both emscripten and native binaries --- .circleci/config.yml | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1013432223..6c60be470e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1015,6 +1015,11 @@ jobs: parameters: project: type: string + binary_type: + type: enum + enum: + - solcjs + - native compile_only: type: integer default: 0 @@ -1037,14 +1042,26 @@ jobs: - attach_workspace: at: /tmp/workspace - run: - name: Install dependencies + name: Install lsof command: | # lsof is used by Colony in its stop-blockchain-client.sh script - sudo apt-get -qy install lsof - - run: - name: External <> tests - command: | - test/externalTests/<>.sh solcjs /tmp/workspace/soljson.js + sudo apt-get --quiet --assume-yes --no-install-recommends install lsof + - when: + condition: + equal: [<< parameters.binary_type >>, "solcjs"] + steps: + - run: + name: External <> tests (solcjs) + command: | + test/externalTests/<>.sh solcjs /tmp/workspace/soljson.js + - when: + condition: + equal: [<< parameters.binary_type >>, "native"] + steps: + - run: + name: External <> tests (native) + command: | + test/externalTests/<>.sh native /tmp/workspace/solc/solc - gitter_notify_failure_unless_pr b_win: &b_win @@ -1282,12 +1299,14 @@ workflows: <<: *workflow_emscripten name: t_ems_compile_ext_colony project: colony + binary_type: solcjs compile_only: 1 nodejs_version: '14' - t_ems_ext: <<: *workflow_emscripten name: t_ems_compile_ext_gnosis project: gnosis + binary_type: solcjs compile_only: 1 nodejs_version: '14' @@ -1297,18 +1316,21 @@ workflows: # <<: *workflow_emscripten # name: t_ems_test_ext_gnosis # project: gnosis + # binary_type: solcjs # # NOTE: Tests do not start on node.js 14 ("ganache-cli exited early with code 1"). # nodejs_version: '12' - t_ems_ext: <<: *workflow_emscripten name: t_ems_test_ext_gnosis_v2 project: gnosis-v2 + binary_type: solcjs # NOTE: Tests do not start on node.js 14 ("ganache-cli exited early with code 1"). nodejs_version: '12' - t_ems_ext: <<: *workflow_emscripten name: t_ems_test_ext_zeppelin project: zeppelin + binary_type: solcjs # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' resource_class: large @@ -1316,6 +1338,7 @@ workflows: <<: *workflow_emscripten name: t_ems_test_ext_ens project: ens + binary_type: solcjs # NOTE: One of the dependencies (fsevents) fails to build its native extension on node.js 12+. nodejs_version: '10' @@ -1382,4 +1405,5 @@ workflows: <<: *workflow_emscripten name: t_ems_test_ext_colony project: colony + binary_type: solcjs resource_class: medium From 3649103e4209351e18d9ca99763349d888224640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 7 Dec 2021 16:34:07 +0100 Subject: [PATCH 0070/1704] Switch most external tests to use native compiler built by b_ubu_static --- .circleci/config.yml | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6c60be470e..4798c11669 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -396,6 +396,11 @@ defaults: requires: - b_ubu_release + - workflow_ubuntu2004_static: &workflow_ubuntu2004_static + <<: *workflow_trigger_on_tags + requires: + - b_ubu_static + - workflow_archlinux: &workflow_archlinux <<: *workflow_trigger_on_tags requires: @@ -666,10 +671,11 @@ jobs: MAKEFLAGS: -j 10 b_ubu_static: - # Runs 2x faster on large and 3x on xlarge but no other jobs depend on it we can live with medium. - <<: *base_ubuntu2004 + # On large runs 2x faster than on medium. 3x on xlarge. + <<: *base_ubuntu2004_xlarge environment: - MAKEFLAGS: -j 5 + TERM: xterm + MAKEFLAGS: -j 10 CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON steps: - checkout @@ -678,6 +684,7 @@ jobs: name: strip binary command: strip build/solc/solc - store_artifacts: *artifacts_solc + - persist_to_workspace: *artifacts_executables - gitter_notify_failure_unless_pr b_ubu_codecov: @@ -1303,10 +1310,10 @@ workflows: compile_only: 1 nodejs_version: '14' - t_ems_ext: - <<: *workflow_emscripten - name: t_ems_compile_ext_gnosis + <<: *workflow_ubuntu2004_static + name: t_native_compile_ext_gnosis project: gnosis - binary_type: solcjs + binary_type: native compile_only: 1 nodejs_version: '14' @@ -1314,31 +1321,31 @@ workflows: # and there are also other less frequent problems. See https://github.com/gnosis/safe-contracts/issues/216. #- t_ems_ext: # <<: *workflow_emscripten - # name: t_ems_test_ext_gnosis + # name: t_native_test_ext_gnosis # project: gnosis - # binary_type: solcjs + # binary_type: native # # NOTE: Tests do not start on node.js 14 ("ganache-cli exited early with code 1"). # nodejs_version: '12' - t_ems_ext: - <<: *workflow_emscripten - name: t_ems_test_ext_gnosis_v2 + <<: *workflow_ubuntu2004_static + name: t_native_test_ext_gnosis_v2 project: gnosis-v2 - binary_type: solcjs + binary_type: native # NOTE: Tests do not start on node.js 14 ("ganache-cli exited early with code 1"). nodejs_version: '12' - t_ems_ext: - <<: *workflow_emscripten - name: t_ems_test_ext_zeppelin + <<: *workflow_ubuntu2004_static + name: t_native_test_ext_zeppelin project: zeppelin - binary_type: solcjs + binary_type: native # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' resource_class: large - t_ems_ext: - <<: *workflow_emscripten - name: t_ems_test_ext_ens + <<: *workflow_ubuntu2004_static + name: t_native_test_ext_ens project: ens - binary_type: solcjs + binary_type: native # NOTE: One of the dependencies (fsevents) fails to build its native extension on node.js 12+. nodejs_version: '10' From 01d45a195226f0d6c0dd252582dd154857b621e8 Mon Sep 17 00:00:00 2001 From: Omkar Nikhal <69253915+gitpushOmnik@users.noreply.github.com> Date: Thu, 9 Dec 2021 23:42:07 +0530 Subject: [PATCH 0071/1704] Remove redundant typo --- docs/brand-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/brand-guide.rst b/docs/brand-guide.rst index fc03f35d93..5601b16a8e 100644 --- a/docs/brand-guide.rst +++ b/docs/brand-guide.rst @@ -59,7 +59,7 @@ Under the following terms: - **Attribution** — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any - reasonable manner, but not in any way that suggests the the Solidity + reasonable manner, but not in any way that suggests that the Solidity core team endorses you or your use. When using the Solidity logo, please respect the Solidity logo guidelines. From 6afb63200c704ec019ec0f7c3e8d5b1db30cbba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 9 Dec 2021 16:36:09 +0100 Subject: [PATCH 0072/1704] externalTests: Use `yarn install` instead of `yarn` in colony ext test to avoid compiling contracts twice --- test/externalTests/colony.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index dff745d683..65e4e42561 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -49,7 +49,7 @@ function colony_test neutralize_package_json_hooks force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" - yarn + yarn install git submodule update --init cd lib From f0aadcf577bd543ba20e3688ca088b233f28f557 Mon Sep 17 00:00:00 2001 From: dinah Date: Thu, 9 Dec 2021 20:18:28 -0600 Subject: [PATCH 0073/1704] Remove stale link. --- docs/introduction-to-smart-contracts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index c448d7671d..aab0faf7c5 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -313,7 +313,7 @@ likely it will be. since it is not up to the submitter of a transaction, but up to the miners to determine in which block the transaction is included. If you want to schedule future calls of your contract, you can use - the `alarm clock `_ or a similar oracle service. + a smart contract automation tool or an oracle service. .. _the-ethereum-virtual-machine: From e6179d5356d532bad82b15c2ffa80b8e65fae2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Dec 2021 14:59:13 +0100 Subject: [PATCH 0074/1704] CI: Run `t_ems_test_ext_colony` on nodejs 14 - Otherwise it seems to require python, which is not available in CI. We could install it but we'll probably run into other issues on latest node and the switch to latest was not intentional anyway. --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4798c11669..512b46a78b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1413,4 +1413,5 @@ workflows: name: t_ems_test_ext_colony project: colony binary_type: solcjs + nodejs_version: '14' resource_class: medium From 0e6388a90769783fc0cd1d4455fc5c58fec172f0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 13 Dec 2021 14:52:17 +0100 Subject: [PATCH 0075/1704] Clarify FileReader interface. --- libsolidity/interface/FileReader.cpp | 4 ++-- libsolidity/interface/FileReader.h | 15 +++++++------- solc/CommandLineInterface.cpp | 30 ++++++++++++++-------------- test/solc/CommandLineInterface.cpp | 28 +++++++++++++------------- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index cfd1feb338..65cf70e5a4 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -84,7 +84,7 @@ void FileReader::allowDirectory(boost::filesystem::path _path) m_allowedDirectories.insert(std::move(_path)); } -void FileReader::setSource(boost::filesystem::path const& _path, SourceCode _source) +void FileReader::addOrUpdateFile(boost::filesystem::path const& _path, SourceCode _source) { m_sourceCodes[cliPathToSourceUnitName(_path)] = std::move(_source); } @@ -94,7 +94,7 @@ void FileReader::setStdin(SourceCode _source) m_sourceCodes[""] = std::move(_source); } -void FileReader::setSources(StringMap _sources) +void FileReader::setSourceUnits(StringMap _sources) { m_sourceCodes = std::move(_sources); } diff --git a/libsolidity/interface/FileReader.h b/libsolidity/interface/FileReader.h index 71f5819df6..71ca5fc5d1 100644 --- a/libsolidity/interface/FileReader.h +++ b/libsolidity/interface/FileReader.h @@ -61,18 +61,17 @@ class FileReader void allowDirectory(boost::filesystem::path _path); FileSystemPathSet const& allowedDirectories() const noexcept { return m_allowedDirectories; } - StringMap const& sourceCodes() const noexcept { return m_sourceCodes; } - - /// Retrieves the source code for a given source unit name. - SourceCode const& sourceCode(SourceUnitName const& _sourceUnitName) const { return m_sourceCodes.at(_sourceUnitName); } + /// @returns all sources by their internal source unit names. + StringMap const& sourceUnits() const noexcept { return m_sourceCodes; } /// Resets all sources to the given map of source unit name to source codes. /// Does not enforce @a allowedDirectories(). - void setSources(StringMap _sources); + void setSourceUnits(StringMap _sources); - /// Adds the source code under a source unit name created by normalizing the file path. + /// Adds the source code under a source unit name created by normalizing the file path + /// or changes an existing source. /// Does not enforce @a allowedDirectories(). - void setSource(boost::filesystem::path const& _path, SourceCode _source); + void addOrUpdateFile(boost::filesystem::path const& _path, SourceCode _source); /// Adds the source code under the source unit name of @a . /// Does not enforce @a allowedDirectories(). @@ -83,7 +82,7 @@ class FileReader /// The read will only succeed if the canonical path of the file is within one of the @a allowedDirectories(). /// @param _kind must be equal to "source". Other values are not supported. /// @return Content of the loaded file or an error message. If the operation succeeds, a copy of - /// the content is retained in @a sourceCodes() under the key of @a _sourceUnitName. If the key + /// the content is retained in @a sourceUnits() under the key of @a _sourceUnitName. If the key /// already exists, previous content is discarded. frontend::ReadCallback::Result readFile(std::string const& _kind, std::string const& _sourceUnitName); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 4610741020..94bfd8a68b 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -483,7 +483,7 @@ void CommandLineInterface::readInputFiles() } else { - m_fileReader.setSource(infile, move(fileContent)); + m_fileReader.addOrUpdateFile(infile, move(fileContent)); m_fileReader.allowDirectory(boost::filesystem::canonical(infile).remove_filename()); } } @@ -499,7 +499,7 @@ void CommandLineInterface::readInputFiles() m_fileReader.setStdin(readUntilEnd(m_sin)); } - if (m_fileReader.sourceCodes().empty() && !m_standardJsonInput.has_value()) + if (m_fileReader.sourceUnits().empty() && !m_standardJsonInput.has_value()) solThrow(CommandLineValidationError, "All specified input files either do not exist or are not regular files."); } @@ -510,7 +510,7 @@ map CommandLineInterface::parseAstFromInput() map sourceJsons; map tmpSources; - for (SourceCode const& sourceCode: m_fileReader.sourceCodes() | ranges::views::values) + for (SourceCode const& sourceCode: m_fileReader.sourceUnits() | ranges::views::values) { Json::Value ast; astAssert(jsonParseStrict(sourceCode, ast), "Input file could not be parsed to JSON"); @@ -528,7 +528,7 @@ map CommandLineInterface::parseAstFromInput() } } - m_fileReader.setSources(tmpSources); + m_fileReader.setSourceUnits(tmpSources); return sourceJsons; } @@ -721,7 +721,7 @@ void CommandLineInterface::compile() } else { - m_compiler->setSources(m_fileReader.sourceCodes()); + m_compiler->setSources(m_fileReader.sourceUnits()); m_compiler->setParserErrorRecovery(m_options.input.errorRecovery); } @@ -835,7 +835,7 @@ void CommandLineInterface::handleCombinedJSON() if (m_options.compiler.combinedJsonRequests->ast) { output[g_strSources] = Json::Value(Json::objectValue); - for (auto const& sourceCode: m_fileReader.sourceCodes()) + for (auto const& sourceCode: m_fileReader.sourceUnits()) { ASTJsonConverter converter(m_compiler->state(), m_compiler->sourceIndices()); output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue); @@ -858,12 +858,12 @@ void CommandLineInterface::handleAst() return; vector asts; - for (auto const& sourceCode: m_fileReader.sourceCodes()) + for (auto const& sourceCode: m_fileReader.sourceUnits()) asts.push_back(&m_compiler->ast(sourceCode.first)); if (!m_options.output.dir.empty()) { - for (auto const& sourceCode: m_fileReader.sourceCodes()) + for (auto const& sourceCode: m_fileReader.sourceUnits()) { stringstream data; string postfix = ""; @@ -876,7 +876,7 @@ void CommandLineInterface::handleAst() else { sout() << "JSON AST (compact format):" << endl << endl; - for (auto const& sourceCode: m_fileReader.sourceCodes()) + for (auto const& sourceCode: m_fileReader.sourceUnits()) { sout() << endl << "======= " << sourceCode.first << " =======" << endl; ASTJsonConverter(m_compiler->state(), m_compiler->sourceIndices()).print(sout(), m_compiler->ast(sourceCode.first)); @@ -908,7 +908,7 @@ void CommandLineInterface::link() librariesReplacements[replacement] = library.second; } - FileReader::StringMap sourceCodes = m_fileReader.sourceCodes(); + FileReader::StringMap sourceCodes = m_fileReader.sourceUnits(); for (auto& src: sourceCodes) { auto end = src.second.end(); @@ -944,14 +944,14 @@ void CommandLineInterface::link() while (!src.second.empty() && *prev(src.second.end()) == '\n') src.second.resize(src.second.size() - 1); } - m_fileReader.setSources(move(sourceCodes)); + m_fileReader.setSourceUnits(move(sourceCodes)); } void CommandLineInterface::writeLinkedFiles() { solAssert(m_options.input.mode == InputMode::Linker, ""); - for (auto const& src: m_fileReader.sourceCodes()) + for (auto const& src: m_fileReader.sourceUnits()) if (src.first == g_stdinFileName) sout() << src.second << endl; else @@ -989,7 +989,7 @@ void CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul: bool successful = true; map assemblyStacks; - for (auto const& src: m_fileReader.sourceCodes()) + for (auto const& src: m_fileReader.sourceUnits()) { // --no-optimize-yul option is not accepted in assembly mode. solAssert(!m_options.optimizer.noOptimizeYul, ""); @@ -1029,7 +1029,7 @@ void CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul: solThrow(CommandLineExecutionError, ""); } - for (auto const& src: m_fileReader.sourceCodes()) + for (auto const& src: m_fileReader.sourceUnits()) { string machine = _targetMachine == yul::AssemblyStack::Machine::EVM ? "EVM" : @@ -1118,7 +1118,7 @@ void CommandLineInterface::outputCompilationResults() if (m_options.compiler.outputs.asmJson) ret = jsonPrettyPrint(removeNullMembers(m_compiler->assemblyJSON(contract))); else - ret = m_compiler->assemblyString(contract, m_fileReader.sourceCodes()); + ret = m_compiler->assemblyString(contract, m_fileReader.sourceUnits()); if (!m_options.output.dir.empty()) createFile(m_compiler->filesystemFriendlyName(contract) + (m_options.compiler.outputs.asmJson ? "_evm.json" : ".evm"), ret); diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index dbffc47889..494dbbd94d 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -213,7 +213,7 @@ BOOST_AUTO_TEST_CASE(cli_input) BOOST_TEST(result.options.input.mode == InputMode::Compiler); BOOST_TEST(result.options.input.addStdin); BOOST_CHECK_EQUAL(result.options.input.remappings, expectedRemappings); - BOOST_CHECK_EQUAL(result.reader.sourceCodes(), expectedSources); + BOOST_CHECK_EQUAL(result.reader.sourceUnits(), expectedSources); BOOST_CHECK_EQUAL(result.reader.allowedDirectories(), expectedAllowedPaths); } @@ -240,7 +240,7 @@ BOOST_AUTO_TEST_CASE(cli_ignore_missing_some_files_exist) BOOST_TEST(result.stderrContent == "\"" + (tempDir2.path() / "input2.sol").string() + "\" is not found. Skipping.\n"); BOOST_TEST(result.options.input.mode == InputMode::Compiler); BOOST_TEST(!result.options.input.addStdin); - BOOST_CHECK_EQUAL(result.reader.sourceCodes(), expectedSources); + BOOST_CHECK_EQUAL(result.reader.sourceUnits(), expectedSources); BOOST_CHECK_EQUAL(result.reader.allowedDirectories(), expectedAllowedPaths); } @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(standard_json_base_path) BOOST_TEST(result.options.input.mode == InputMode::StandardJson); BOOST_TEST(result.options.input.addStdin); BOOST_TEST(result.options.input.paths.empty()); - BOOST_TEST(result.reader.sourceCodes().empty()); + BOOST_TEST(result.reader.sourceUnits().empty()); BOOST_TEST(result.reader.allowedDirectories().empty()); BOOST_TEST(result.reader.basePath() == "/" / tempDir.path().relative_path()); } @@ -304,7 +304,7 @@ BOOST_AUTO_TEST_CASE(standard_json_no_input_file) BOOST_TEST(result.options.input.mode == InputMode::StandardJson); BOOST_TEST(result.options.input.addStdin); BOOST_TEST(result.options.input.paths.empty()); - BOOST_TEST(result.reader.sourceCodes().empty()); + BOOST_TEST(result.reader.sourceUnits().empty()); BOOST_TEST(result.reader.allowedDirectories().empty()); } @@ -315,7 +315,7 @@ BOOST_AUTO_TEST_CASE(standard_json_dash) BOOST_TEST(result.stderrContent == ""); BOOST_TEST(result.options.input.mode == InputMode::StandardJson); BOOST_TEST(result.options.input.addStdin); - BOOST_TEST(result.reader.sourceCodes().empty()); + BOOST_TEST(result.reader.sourceUnits().empty()); BOOST_TEST(result.reader.allowedDirectories().empty()); } @@ -446,7 +446,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_no_base_path) BOOST_TEST(result.stdoutContent == ""); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == ""); } @@ -508,7 +508,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_base_path_same_as_work_dir) BOOST_TEST(result.stdoutContent == ""); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == expectedWorkDir); } @@ -581,7 +581,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_base_path_different_from_wor BOOST_TEST(result.stdoutContent == ""); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == expectedBaseDir); } @@ -650,7 +650,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_relative_base_path) BOOST_TEST(result.stdoutContent == ""); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == expectedWorkDir / "base"); } @@ -817,7 +817,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_normalization_and_weird_name BOOST_TEST(result.stdoutContent == ""); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == expectedOptions.input.basePath); } @@ -874,7 +874,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_symlinks) BOOST_TEST(result.stdoutContent == ""); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == expectedWorkDir / "sym/z/"); } @@ -906,7 +906,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_base_path_and_stdin) BOOST_TEST(result.stdoutContent == ""); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == expectedWorkDir / "base"); } @@ -1009,7 +1009,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths) BOOST_TEST(result.stdoutContent == ""); BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.includePaths() == expectedIncludePaths); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == expectedWorkDir / "base/"); @@ -1105,7 +1105,7 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths) BOOST_REQUIRE(result.success); BOOST_TEST(result.options == expectedOptions); - BOOST_TEST(result.reader.sourceCodes() == expectedSources); + BOOST_TEST(result.reader.sourceUnits() == expectedSources); BOOST_TEST(result.reader.includePaths() == expectedIncludePaths); BOOST_TEST(result.reader.allowedDirectories() == expectedAllowedDirectories); BOOST_TEST(result.reader.basePath() == expectedWorkDir / "base/"); From c0b41cfcdd4673e6bff4c0d7b48b3ed4b7a23002 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 13 Dec 2021 17:33:48 +0100 Subject: [PATCH 0076/1704] Add const and file name. --- libsolidity/interface/CompilerStack.cpp | 2 +- libsolidity/interface/FileReader.cpp | 4 ++-- libsolidity/interface/FileReader.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 4b7faf4966..5292d5329f 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1447,7 +1447,7 @@ CompilerStack::Source const& CompilerStack::source(string const& _sourceName) co { auto it = m_sources.find(_sourceName); if (it == m_sources.end()) - solThrow(CompilerError, "Given source file not found."); + solThrow(CompilerError, "Given source file not found: " + _sourceName); return it->second; } diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 65cf70e5a4..47f4d2b5aa 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -172,7 +172,7 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so } } -string FileReader::cliPathToSourceUnitName(boost::filesystem::path const& _cliPath) +string FileReader::cliPathToSourceUnitName(boost::filesystem::path const& _cliPath) const { vector prefixes = {m_basePath.empty() ? normalizeCLIPathForVFS(".") : m_basePath}; prefixes += m_includePaths; @@ -189,7 +189,7 @@ string FileReader::cliPathToSourceUnitName(boost::filesystem::path const& _cliPa return normalizedPath.generic_string(); } -map FileReader::detectSourceUnitNameCollisions(FileSystemPathSet const& _cliPaths) +map FileReader::detectSourceUnitNameCollisions(FileSystemPathSet const& _cliPaths) const { map nameToPaths; for (boost::filesystem::path const& cliPath: _cliPaths) diff --git a/libsolidity/interface/FileReader.h b/libsolidity/interface/FileReader.h index 71ca5fc5d1..3892e98263 100644 --- a/libsolidity/interface/FileReader.h +++ b/libsolidity/interface/FileReader.h @@ -93,14 +93,14 @@ class FileReader /// Creates a source unit name by normalizing a path given on the command line and, if possible, /// making it relative to base path or one of the include directories. - std::string cliPathToSourceUnitName(boost::filesystem::path const& _cliPath); + std::string cliPathToSourceUnitName(boost::filesystem::path const& _cliPath) const; /// Checks if a set contains any paths that lead to different files but would receive identical /// source unit names. Files are considered the same if their paths are exactly the same after /// normalization (without following symlinks). /// @returns a map containing all the conflicting source unit names and the paths that would /// receive them. The returned paths are normalized. - std::map detectSourceUnitNameCollisions(FileSystemPathSet const& _cliPaths); + std::map detectSourceUnitNameCollisions(FileSystemPathSet const& _cliPaths) const; /// Normalizes a filesystem path to make it include all components up to the filesystem root, /// remove small, inconsequential differences that do not affect the meaning and make it look From d17f7206ad7ac3e40fc253fa3ece8c3a5eaba718 Mon Sep 17 00:00:00 2001 From: Alessandro Coglio Date: Tue, 7 Dec 2021 23:07:19 -0800 Subject: [PATCH 0077/1704] Improve description of break/continue restrictions. This is as discussed on Element, with enhancements discussed with @cameel. --- docs/yul.rst | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/yul.rst b/docs/yul.rst index 219905cd5f..60a2da5b94 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -541,10 +541,24 @@ evaluate to zero values. In all other situations, expressions have to evaluate to exactly one value. -The ``continue`` and ``break`` statements can only be used inside loop bodies -and have to be in the same function as the loop (or both have to be at the -top level). The ``continue`` and ``break`` statements cannot be used -in other parts of a loop, not even when it is scoped inside a second loop's body. +A ``continue`` or ``break`` statement can only be used inside the body of a for-loop, as follows. +Consider the innermost loop that contains the statement. +The loop and the statement must be in the same function, or both must be at the top level. +The statement must be in the loop's body block; +it cannot be in the loop's initialization block or update block. +It is worth emphasizing that this restriction applies just +to the innermost loop that contains the ``continue`` or ``break`` statement: +this innermost loop, and therefore the ``continue`` or ``break`` statement, +may appear anywhere in an outer loop, possibly in an outer loop's initialization block or update block. +For example, the following is legal, +because the ``break`` occurs in the body block of the inner loop, +despite also occurring in the update block of the outer loop: + +.. code-block:: yul + + for {} true { for {} true {} { break } } + { + } The condition part of the for-loop has to evaluate to exactly one value. From 316be7206fa5256443e422cde0de59944fe4d9e7 Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Mon, 13 Dec 2021 22:27:04 +0100 Subject: [PATCH 0078/1704] Fix soundness of storage/memory pointers that were not erasing enough knowledge --- Changelog.md | 1 + libsolidity/formal/SMTEncoder.cpp | 39 +++++++++---------- .../smtCheckerTests/file_level/import.sol | 4 +- .../struct_aliasing_parameter_memory_1.sol | 21 ++++++++++ .../struct_aliasing_parameter_memory_2.sol | 26 +++++++++++++ .../struct_aliasing_parameter_memory_3.sol | 26 +++++++++++++ .../struct_aliasing_parameter_storage_1.sol | 24 ++++++++++++ .../struct_aliasing_parameter_storage_2.sol | 23 +++++++++++ .../struct_aliasing_parameter_storage_3.sol | 29 ++++++++++++++ .../struct_aliasing_parameter_storage_4.sol | 29 ++++++++++++++ .../types/struct/struct_aliasing_storage.sol | 3 +- 11 files changed, 202 insertions(+), 23 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_1.sol create mode 100644 test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_2.sol create mode 100644 test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_3.sol create mode 100644 test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_1.sol create mode 100644 test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_2.sol create mode 100644 test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_3.sol create mode 100644 test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_4.sol diff --git a/Changelog.md b/Changelog.md index c5b0481420..f9d7552742 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: Bugfixes: * Code Generator: Fix a crash when using ``@use-src`` and compiling from Yul to ewasm. * SMTChecker: Fix internal error when an unsafe target is solved more than once and the counterexample messages are different. + * SMTChecker: Fix soundness of assigned storage/memory local pointers that were not erasing enough knowledge. * Fix internal error when a function has a calldata struct argument with an internal type inside. diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 11ac5ab7aa..8326b6b2f8 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -32,6 +32,8 @@ #include +#include + #include #include @@ -2371,28 +2373,25 @@ void SMTEncoder::resetReferences(Type const* _type) bool SMTEncoder::sameTypeOrSubtype(Type const* _a, Type const* _b) { - Type const* prefix = _a; - while ( - prefix->category() == Type::Category::Mapping || - prefix->category() == Type::Category::Array - ) - { - if (*typeWithoutPointer(_b) == *typeWithoutPointer(prefix)) - return true; - if (prefix->category() == Type::Category::Mapping) - { - auto mapPrefix = dynamic_cast(prefix); - solAssert(mapPrefix, ""); - prefix = mapPrefix->valueType(); - } - else + bool foundSame = false; + + solidity::util::BreadthFirstSearch bfs{{_a}}; + bfs.run([&](auto _type, auto&& _addChild) { + if (*typeWithoutPointer(_b) == *typeWithoutPointer(_type)) { - auto arrayPrefix = dynamic_cast(prefix); - solAssert(arrayPrefix, ""); - prefix = arrayPrefix->baseType(); + foundSame = true; + bfs.abort(); } - } - return false; + if (auto const* mapType = dynamic_cast(_type)) + _addChild(mapType->valueType()); + else if (auto const* arrayType = dynamic_cast(_type)) + _addChild(arrayType->baseType()); + else if (auto const* structType = dynamic_cast(_type)) + for (auto const& member: structType->nativeMembers(nullptr)) + _addChild(member.type); + }); + + return foundSame; } bool SMTEncoder::isSupportedType(Type const& _type) const diff --git a/test/libsolidity/smtCheckerTests/file_level/import.sol b/test/libsolidity/smtCheckerTests/file_level/import.sol index a67ee4eb6c..85ae712930 100644 --- a/test/libsolidity/smtCheckerTests/file_level/import.sol +++ b/test/libsolidity/smtCheckerTests/file_level/import.sol @@ -22,5 +22,5 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (B:238-252): CHC: Assertion violation happens here.\nCounterexample:\ndata = {x: 0}\nx = 0\ny = 0\n\nTransaction trace:\nC.constructor()\nState: data = {x: 0}\nC.g()\n C.f(7) -- internal call\n A:set({x: 0}, 7) -- internal call\n A:set({x: 0}, 8) -- internal call -// Warning 6328: (B:308-322): CHC: Assertion violation happens here.\nCounterexample:\ndata = {x: 0}\nx = 0\ny = 0\n\nTransaction trace:\nC.constructor()\nState: data = {x: 0}\nC.g()\n C.f(7) -- internal call\n A:set({x: 0}, 7) -- internal call\n A:set({x: 0}, 8) -- internal call +// Warning 6328: (B:238-252): CHC: Assertion violation happens here.\nCounterexample:\ndata = {x: 21238}\nx = 8\ny = 21238\n\nTransaction trace:\nC.constructor()\nState: data = {x: 0}\nC.g()\n C.f(7) -- internal call\n A:set({x: 0}, 7) -- internal call\n A:set({x: 8}, 8) -- internal call +// Warning 6328: (B:308-322): CHC: Assertion violation happens here.\nCounterexample:\ndata = {x: 6}\nx = 0\ny = 6\n\nTransaction trace:\nC.constructor()\nState: data = {x: 0}\nC.g()\n C.f(7) -- internal call\n A:set({x: 0}, 7) -- internal call\n A:set({x: 0}, 8) -- internal call diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_1.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_1.sol new file mode 100644 index 0000000000..edb1e1b40b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_1.sol @@ -0,0 +1,21 @@ +contract C { + struct S { + uint sum; + uint[] a; + } + + function f(S memory m, uint v) internal pure { + m.sum = v; + m.a = new uint[](2); + } + + constructor(uint amt) { + S memory s; + f(s, amt); + assert(s.a.length == 2); // should hold but no aliasing support means it fails for now + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (201-224): CHC: Assertion violation happens here.\nCounterexample:\n\namt = 0\ns = {sum: 0, a: []}\n\nTransaction trace:\nC.constructor(0) diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_2.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_2.sol new file mode 100644 index 0000000000..28da837006 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_2.sol @@ -0,0 +1,26 @@ +contract C { + struct S { + uint sum; + uint[] a; + } + + struct T { + S s; + uint x; + } + + function f(S memory m, uint v) internal pure { + m.sum = v; + m.a = new uint[](2); + } + + constructor(uint amt) { + T memory t; + f(t.s, amt); + assert(t.s.a.length == 2); // should hold but no aliasing support means it fails for now + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (236-261): CHC: Assertion violation happens here.\nCounterexample:\n\namt = 0\nt = {s: {sum: 0, a: []}, x: 0}\n\nTransaction trace:\nC.constructor(0) diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_3.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_3.sol new file mode 100644 index 0000000000..36890f03eb --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_memory_3.sol @@ -0,0 +1,26 @@ +contract C { + struct S { + uint sum; + uint[] a; + } + + struct T { + S s; + uint x; + } + + function f(T memory m, uint v) internal pure { + m.s.sum = v; + m.s.a = new uint[](2); + } + + constructor(uint amt) { + T memory t; + f(t, amt); + assert(t.s.a.length == 2); // should hold but no aliasing support means it fails for now + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (238-263): CHC: Assertion violation happens here.\nCounterexample:\n\namt = 0\nt = {s: {sum: 0, a: []}, x: 0}\n\nTransaction trace:\nC.constructor(0) diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_1.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_1.sol new file mode 100644 index 0000000000..3fd0c0d873 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_1.sol @@ -0,0 +1,24 @@ +contract C { + struct S { + mapping(address => uint) innerM; + uint sum; + } + + function f(S storage m, address i, uint v) internal { + m.innerM[i] = v; + m.sum += v; + } + + S s; + + constructor(uint amt) { + f(s, msg.sender, amt); + } + function g() public view { + assert(s.sum == 0); // should hold but no aliasing support means it fails for now + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (270-288): CHC: Assertion violation happens here.\nCounterexample:\ns = {innerM, sum: 21239}\n\nTransaction trace:\nC.constructor(0){ msg.sender: 0x6dc4 }\nState: s = {innerM, sum: 21239}\nC.g() diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_2.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_2.sol new file mode 100644 index 0000000000..9d4623ae09 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_2.sol @@ -0,0 +1,23 @@ +contract C { + struct S { + mapping(address => uint) innerM; + uint sum; + } + + function f(mapping(address => uint) storage innerM, address i, uint v) internal { + innerM[i] = v; + } + + S s; + + constructor(uint amt) { + f(s.innerM, msg.sender, amt); + } + function g() public view { + assert(s.innerM[msg.sender] == 0); // should hold but no aliasing support means it fails for now + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (289-322): CHC: Assertion violation happens here.\nCounterexample:\ns = {innerM, sum: 10}\n\nTransaction trace:\nC.constructor(0){ msg.sender: 0x6dc4 }\nState: s = {innerM, sum: 10}\nC.g(){ msg.sender: 0x0985 } diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_3.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_3.sol new file mode 100644 index 0000000000..8779cd0959 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_3.sol @@ -0,0 +1,29 @@ +contract C { + struct S { + mapping(address => uint) innerM; + uint sum; + } + + struct T { + uint x; + S s; + } + + function f(T storage m, address i, uint v) internal { + m.s.innerM[i] = v; + m.s.sum += v; + } + + T t; + + constructor(uint amt) { + f(t, msg.sender, amt); + } + function g() public view { + assert(t.s.sum == 0); // should hold but no aliasing support means it fails for now + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (307-327): CHC: Assertion violation happens here.\nCounterexample:\nt = {x: 10, s: {innerM, sum: 21239}}\n\nTransaction trace:\nC.constructor(0){ msg.sender: 0x6dc4 }\nState: t = {x: 10, s: {innerM, sum: 21239}}\nC.g() diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_4.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_4.sol new file mode 100644 index 0000000000..957c72c120 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_parameter_storage_4.sol @@ -0,0 +1,29 @@ +contract C { + struct S { + mapping(address => uint) innerM; + uint sum; + } + + struct T { + uint x; + S s; + } + + function f(S storage m, address i, uint v) internal { + m.innerM[i] = v; + m.sum += v; + } + + T t; + + constructor(uint amt) { + f(t.s, msg.sender, amt); + } + function g() public view { + assert(t.s.sum == 0); // should hold but no aliasing support means it fails for now + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (305-325): CHC: Assertion violation happens here.\nCounterexample:\nt = {x: 10, s: {innerM, sum: 21239}}\n\nTransaction trace:\nC.constructor(0){ msg.sender: 0x6dc4 }\nState: t = {x: 10, s: {innerM, sum: 21239}}\nC.g() diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_storage.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_storage.sol index 4c13699e2f..e5d9d60abe 100644 --- a/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_storage.sol +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_aliasing_storage.sol @@ -25,5 +25,6 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreCex: yes // ---- -// Warning 6328: (369-405): CHC: Assertion violation happens here.\nCounterexample:\ns1 = {x: 0, a: []}, s2 = {x: 0, a: []}\nb = false\ns3 = {x: 42, a: []}\n\nTransaction trace:\nC.constructor()\nState: s1 = {x: 0, a: []}, s2 = {x: 0, a: []}\nC.f(false) +// Warning 6328: (369-405): CHC: Assertion violation happens here. From 91ee0ed4ef07f0f376b0c0cc74050925dc9b5942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 9 Dec 2021 14:10:14 +0100 Subject: [PATCH 0079/1704] scripts/common.sh: Add first_word() helper --- scripts/common.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/common.sh b/scripts/common.sh index 3e67c4f566..ab7d82d875 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -226,7 +226,16 @@ function circleci_step_selected { local selected_steps="$1" local step="$2" + (( $# == 2 )) || assertFail [[ $step != *" "* ]] || assertFail "Step names must not contain spaces." [[ " $selected_steps " == *" $step "* ]] || return 1 } + +function first_word +{ + local words="$1" + (( $# == 1 )) || assertFail + + echo "$words" | cut -d " " -f 1 +} From adfa51c01c89fd406a8b1ab8c24a606bcec48d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 29 Nov 2021 14:20:42 +0100 Subject: [PATCH 0080/1704] externalTests: Measure compilation time --- test/externalTests/common.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 80a9dec32c..0f5bbc0b11 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -236,7 +236,7 @@ function run_test replace_version_pragmas printLog "Running compile function..." - $compile_fn + time $compile_fn printLog "Running test function..." $test_fn @@ -329,7 +329,7 @@ function compile_and_run_test local verify_fn="$3" printLog "Running compile function..." - $compile_fn + time $compile_fn $verify_fn "$SOLCVERSION_SHORT" "$SOLCVERSION" if [[ "$COMPILE_ONLY" == 1 ]]; then From d304c8443218753acabd16535ee883ab92e0a88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 9 Dec 2021 14:37:21 +0100 Subject: [PATCH 0081/1704] externalTests: Replace optimizer levels with named presets --- scripts/common.sh | 7 ++++ test/externalTests/colony.sh | 20 ++++++----- test/externalTests/common.sh | 63 ++++++++++++++++----------------- test/externalTests/ens.sh | 19 +++++----- test/externalTests/gnosis-v2.sh | 20 ++++++----- test/externalTests/gnosis.sh | 20 ++++++----- test/externalTests/zeppelin.sh | 19 +++++----- 7 files changed, 92 insertions(+), 76 deletions(-) diff --git a/scripts/common.sh b/scripts/common.sh index ab7d82d875..4a98c00726 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -211,6 +211,7 @@ function safe_kill function circleci_select_steps { + # We expect multiple lines in $all_steps, one step per line local all_steps="$1" (( $# == 1 )) || assertFail @@ -222,6 +223,12 @@ function circleci_select_steps fi } +function circleci_select_steps_multiarg +{ + # We expect multiple arguments, one step per argument. + circleci_select_steps "$(printf '%s\n' "$@")" +} + function circleci_step_selected { local selected_steps="$1" diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index 65a2183bcc..7326f90bc7 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -36,20 +36,22 @@ function colony_test local repo="https://github.com/solidity-external-tests/colonyNetwork.git" local branch=develop_080 local config_file="truffle.js" - # On levels 1 and 2 it compiles but tests run out of gas - local min_optimizer_level=3 - local max_optimizer_level=3 + local settings_presets=( + #legacy-no-optimize # Compiles but tests run out of gas + #legacy-optimize-evm-only # Compiles but tests run out of gas + legacy-optimize-evm+yul + ) - local selected_optimizer_levels - selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") - print_optimizer_levels_or_exit "$selected_optimizer_levels" + local selected_optimizer_presets + selected_optimizer_presets=$(circleci_select_steps_multiarg "${settings_presets[@]}") + print_optimizer_presets_or_exit "$selected_optimizer_presets" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$(first_word "$selected_optimizer_presets")" yarn install git submodule update --init @@ -61,8 +63,8 @@ function colony_test replace_version_pragmas [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" - for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$level" compile_fn test_fn + for preset in $selected_optimizer_presets; do + truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$preset" compile_fn test_fn done } diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 0f5bbc0b11..93484b16b3 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -24,13 +24,13 @@ set -e CURRENT_EVM_VERSION=london -function print_optimizer_levels_or_exit +function print_optimizer_presets_or_exit { - local selected_levels="$1" + local selected_presets="$1" - [[ $selected_levels != "" ]] || { printWarning "No steps to run. Exiting."; exit 0; } + [[ $selected_presets != "" ]] || { printWarning "No presets to run. Exiting."; exit 0; } - printLog "Selected optimizer levels: ${selected_levels}" + printLog "Selected settings presets: ${selected_presets}" } function verify_input @@ -141,7 +141,7 @@ function force_truffle_compiler_settings local config_file="$1" local binary_type="$2" local solc_path="$3" - local level="$4" + local preset="$4" local evm_version="${5:-"$CURRENT_EVM_VERSION"}" [[ $binary_type == native || $binary_type == solcjs ]] || assertFail @@ -153,14 +153,16 @@ function force_truffle_compiler_settings echo "Config file: $config_file" echo "Binary type: $binary_type" echo "Compiler path: $solc_path" - echo "Optimization level: $level" - echo "Optimizer settings: $(optimizer_settings_for_level "$level")" + echo "Settings preset: ${preset}" + echo "Settings: $(settings_from_preset "$preset" "$evm_version")" echo "EVM version: $evm_version" + echo "Compiler version: ${SOLCVERSION_SHORT}" + echo "Compiler version (full): ${SOLCVERSION}" echo "-------------------------------------" # Forcing the settings should always work by just overwriting the solc object. Forcing them by using a # dedicated settings objects should only be the fallback. - echo "module.exports['compilers'] = $(truffle_compiler_settings "$solc_path" "$level" "$evm_version");" >> "$config_file" + echo "module.exports['compilers'] = $(truffle_compiler_settings "$solc_path" "$preset" "$evm_version");" >> "$config_file" } function force_hardhat_compiler_binary @@ -180,14 +182,14 @@ function force_hardhat_compiler_binary function force_hardhat_compiler_settings { local config_file="$1" - local level="$2" + local preset="$2" local evm_version="${3:-"$CURRENT_EVM_VERSION"}" printLog "Configuring Hardhat..." echo "-------------------------------------" echo "Config file: ${config_file}" - echo "Optimization level: ${level}" - echo "Optimizer settings: $(optimizer_settings_for_level "$level")" + echo "Settings preset: ${preset}" + echo "Settings: $(settings_from_preset "$preset" "$evm_version")" echo "EVM version: ${evm_version}" echo "Compiler version: ${SOLCVERSION_SHORT}" echo "Compiler version (full): ${SOLCVERSION}" @@ -195,7 +197,7 @@ function force_hardhat_compiler_settings { echo -n 'module.exports["solidity"] = ' - hardhat_compiler_settings "$SOLCVERSION_SHORT" "$level" "$evm_version" + hardhat_compiler_settings "$SOLCVERSION_SHORT" "$preset" "$evm_version" } >> "$config_file" } @@ -242,16 +244,17 @@ function run_test $test_fn } -function optimizer_settings_for_level +function settings_from_preset { - local level="$1" + local preset="$1" + local evm_version="$2" - case "$level" in - 1) echo "{enabled: false}" ;; - 2) echo "{enabled: true, details: {yul: false}}" ;; - 3) echo "{enabled: true, details: {yul: true}}" ;; + case "$preset" in + legacy-no-optimize) echo "{evmVersion: '${evm_version}', optimizer: {enabled: false}}" ;; + legacy-optimize-evm-only) echo "{evmVersion: '${evm_version}', optimizer: {enabled: true, details: {yul: false}}}" ;; + legacy-optimize-evm+yul) echo "{evmVersion: '${evm_version}', optimizer: {enabled: true, details: {yul: true}}}" ;; *) - fail "Optimizer level not found. Please define OPTIMIZER_LEVEL=[1, 2, 3]" + fail "Unknown settings preset: '${preset}'." ;; esac } @@ -269,16 +272,13 @@ function replace_global_solc function truffle_compiler_settings { local solc_path="$1" - local level="$2" + local preset="$2" local evm_version="$3" echo "{" echo " solc: {" echo " version: \"${solc_path}\"," - echo " settings: {" - echo " optimizer: $(optimizer_settings_for_level "$level")," - echo " evmVersion: \"${evm_version}\"" - echo " }" + echo " settings: $(settings_from_preset "$preset" "$evm_version")" echo " }" echo "}" } @@ -310,15 +310,12 @@ function hardhat_solc_build_subtask { function hardhat_compiler_settings { local solc_version="$1" - local level="$2" + local preset="$2" local evm_version="$3" echo "{" echo " version: '${solc_version}'," - echo " settings: {" - echo " optimizer: $(optimizer_settings_for_level "$level")," - echo " evmVersion: '${evm_version}'" - echo " }" + echo " settings: $(settings_from_preset "$preset" "$evm_version")" echo "}" } @@ -345,24 +342,24 @@ function truffle_run_test local config_file="$1" local binary_type="$2" local solc_path="$3" - local optimizer_level="$4" + local preset="$4" local compile_fn="$5" local test_fn="$6" truffle_clean - force_truffle_compiler_settings "$config_file" "$binary_type" "$solc_path" "$optimizer_level" + force_truffle_compiler_settings "$config_file" "$binary_type" "$solc_path" "$preset" compile_and_run_test compile_fn test_fn truffle_verify_compiler_version } function hardhat_run_test { local config_file="$1" - local optimizer_level="$2" + local preset="$2" local compile_fn="$3" local test_fn="$4" hardhat_clean - force_hardhat_compiler_settings "$config_file" "$optimizer_level" + force_hardhat_compiler_settings "$config_file" "$preset" compile_and_run_test compile_fn test_fn hardhat_verify_compiler_version } diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index 7b354acde6..de05454312 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -36,12 +36,15 @@ function ens_test local repo="https://github.com/ensdomains/ens.git" local branch=master local config_file="truffle.js" - local min_optimizer_level=1 - local max_optimizer_level=3 + local settings_presets=( + legacy-no-optimize + legacy-optimize-evm-only + legacy-optimize-evm+yul + ) - local selected_optimizer_levels - selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") - print_optimizer_levels_or_exit "$selected_optimizer_levels" + local selected_optimizer_presets + selected_optimizer_presets=$(circleci_select_steps_multiarg "${settings_presets[@]}") + print_optimizer_presets_or_exit "$selected_optimizer_presets" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" @@ -52,14 +55,14 @@ function ens_test neutralize_package_lock neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$(first_word "$selected_optimizer_presets")" npm install replace_version_pragmas [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" - for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$level" compile_fn test_fn + for preset in $selected_optimizer_presets; do + truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$preset" compile_fn test_fn done } diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index b71749a065..443d5583cb 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -36,13 +36,15 @@ function gnosis_safe_test local repo="https://github.com/solidity-external-tests/safe-contracts.git" local branch=v2_080 local config_file="truffle-config.js" - # level 1: "Error: while migrating GnosisSafe: Returned error: base fee exceeds gas limit" - local min_optimizer_level=2 - local max_optimizer_level=3 + local settings_presets=( + #legacy-no-optimize # "Error: while migrating GnosisSafe: Returned error: base fee exceeds gas limit" + legacy-optimize-evm-only + legacy-optimize-evm+yul + ) - local selected_optimizer_levels - selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") - print_optimizer_levels_or_exit "$selected_optimizer_levels" + local selected_optimizer_presets + selected_optimizer_presets=$(circleci_select_steps_multiarg "${settings_presets[@]}") + print_optimizer_presets_or_exit "$selected_optimizer_presets" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" @@ -53,14 +55,14 @@ function gnosis_safe_test neutralize_package_lock neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$(first_word "$selected_optimizer_presets")" npm install --package-lock replace_version_pragmas [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" - for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$level" compile_fn test_fn + for preset in $selected_optimizer_presets; do + truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$preset" compile_fn test_fn done } diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 97208660bc..9f0d356b6c 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -36,13 +36,15 @@ function gnosis_safe_test local repo="https://github.com/solidity-external-tests/safe-contracts.git" local branch=development_080 local config_file="truffle-config.js" - # levels 1 and 2: "Stack too deep" error - local min_optimizer_level=3 - local max_optimizer_level=3 + local settings_presets=( + #legacy-no-optimize # "Stack too deep" error + #legacy-optimize-evm-only # "Stack too deep" error + legacy-optimize-evm+yul + ) - local selected_optimizer_levels - selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") - print_optimizer_levels_or_exit "$selected_optimizer_levels" + local selected_optimizer_presets + selected_optimizer_presets=$(circleci_select_steps_multiarg "${settings_presets[@]}") + print_optimizer_presets_or_exit "$selected_optimizer_presets" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" @@ -52,14 +54,14 @@ function gnosis_safe_test neutralize_package_lock neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$min_optimizer_level" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$(first_word "$selected_optimizer_presets")" npm install --package-lock replace_version_pragmas [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" - for level in $selected_optimizer_levels; do - truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$level" compile_fn test_fn + for preset in $selected_optimizer_presets; do + truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$preset" compile_fn test_fn done } diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 0759a3aec6..280c9ffeba 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -36,25 +36,28 @@ function zeppelin_test local repo="https://github.com/OpenZeppelin/openzeppelin-contracts.git" local branch=master local config_file="hardhat.config.js" - local min_optimizer_level=1 - local max_optimizer_level=3 + local settings_presets=( + legacy-no-optimize + legacy-optimize-evm-only + legacy-optimize-evm+yul + ) - local selected_optimizer_levels - selected_optimizer_levels=$(circleci_select_steps "$(seq "$min_optimizer_level" "$max_optimizer_level")") - print_optimizer_levels_or_exit "$selected_optimizer_levels" + local selected_optimizer_presets + selected_optimizer_presets=$(circleci_select_steps_multiarg "${settings_presets[@]}") + print_optimizer_presets_or_exit "$selected_optimizer_presets" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$branch" "$DIR" neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" - force_hardhat_compiler_settings "$config_file" "$min_optimizer_level" + force_hardhat_compiler_settings "$config_file" "$(first_word "$selected_optimizer_presets")" npm install replace_version_pragmas - for level in $selected_optimizer_levels; do - hardhat_run_test "$config_file" "$level" compile_fn test_fn + for preset in $selected_optimizer_presets; do + hardhat_run_test "$config_file" "$preset" compile_fn test_fn done } From 3ec05d02b5abeac390bc074b523f2c77c3aafa81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 9 Dec 2021 15:35:16 +0100 Subject: [PATCH 0082/1704] externalTests: Add extra viaIR runs --- .circleci/config.yml | 5 +++-- test/externalTests/colony.sh | 3 +++ test/externalTests/common.sh | 10 +++++++--- test/externalTests/ens.sh | 3 +++ test/externalTests/gnosis-v2.sh | 3 +++ test/externalTests/gnosis.sh | 3 +++ test/externalTests/zeppelin.sh | 3 +++ 7 files changed, 25 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cda6e58909..20d06662d8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1037,8 +1037,9 @@ jobs: docker: - image: circleci/node:<> resource_class: <> - # NOTE: Each external test does 3 separate compile&test runs - parallelism: 3 + # NOTE: Each external test runs up to 6 independent settings presets. If parallelism is higher than + # actual preset count, some runs will exit immediately. If it's lower, some runs will get more than one preset. + parallelism: 6 environment: TERM: xterm COMPILE_ONLY: <> diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index 7326f90bc7..d5b57f024a 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -37,6 +37,9 @@ function colony_test local branch=develop_080 local config_file="truffle.js" local settings_presets=( + #ir-no-optimize # Compiles but tests run out of gas + #ir-optimize-evm-only # Compiles but tests run out of gas + ir-optimize-evm+yul #legacy-no-optimize # Compiles but tests run out of gas #legacy-optimize-evm-only # Compiles but tests run out of gas legacy-optimize-evm+yul diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 93484b16b3..012a21b2f7 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -250,9 +250,13 @@ function settings_from_preset local evm_version="$2" case "$preset" in - legacy-no-optimize) echo "{evmVersion: '${evm_version}', optimizer: {enabled: false}}" ;; - legacy-optimize-evm-only) echo "{evmVersion: '${evm_version}', optimizer: {enabled: true, details: {yul: false}}}" ;; - legacy-optimize-evm+yul) echo "{evmVersion: '${evm_version}', optimizer: {enabled: true, details: {yul: true}}}" ;; + # NOTE: Remember to update `parallelism` of `t_ems_ext` job in CI config if you add/remove presets + legacy-no-optimize) echo "{evmVersion: '${evm_version}', viaIR: false, optimizer: {enabled: false}}" ;; + ir-no-optimize) echo "{evmVersion: '${evm_version}', viaIR: true, optimizer: {enabled: false}}" ;; + legacy-optimize-evm-only) echo "{evmVersion: '${evm_version}', viaIR: false, optimizer: {enabled: true, details: {yul: false}}}" ;; + ir-optimize-evm-only) echo "{evmVersion: '${evm_version}', viaIR: true, optimizer: {enabled: true, details: {yul: false}}}" ;; + legacy-optimize-evm+yul) echo "{evmVersion: '${evm_version}', viaIR: false, optimizer: {enabled: true, details: {yul: true}}}" ;; + ir-optimize-evm+yul) echo "{evmVersion: '${evm_version}', viaIR: true, optimizer: {enabled: true, details: {yul: true}}}" ;; *) fail "Unknown settings preset: '${preset}'." ;; diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index de05454312..c0bc4b558c 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -37,6 +37,9 @@ function ens_test local branch=master local config_file="truffle.js" local settings_presets=( + #ir-no-optimize # "YulException: Variable var_ttl_236 is 1 slot(s) too deep inside the stack." + #ir-optimize-evm-only # "YulException: Variable var_ttl_236 is 1 slot(s) too deep inside the stack." + ir-optimize-evm+yul legacy-no-optimize legacy-optimize-evm-only legacy-optimize-evm+yul diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index 443d5583cb..bae0f0f1e6 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -37,6 +37,9 @@ function gnosis_safe_test local branch=v2_080 local config_file="truffle-config.js" local settings_presets=( + #ir-no-optimize # "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+yul #legacy-no-optimize # "Error: while migrating GnosisSafe: Returned error: base fee exceeds gas limit" legacy-optimize-evm-only legacy-optimize-evm+yul diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 9f0d356b6c..562ab156f6 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -37,6 +37,9 @@ function gnosis_safe_test local branch=development_080 local config_file="truffle-config.js" local settings_presets=( + #ir-no-optimize # "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+yul #legacy-no-optimize # "Stack too deep" error #legacy-optimize-evm-only # "Stack too deep" error legacy-optimize-evm+yul diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 280c9ffeba..89f3d6b423 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -37,6 +37,9 @@ function zeppelin_test local branch=master local config_file="hardhat.config.js" local settings_presets=( + #ir-no-optimize # "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+yul # Compiles but tests fail. See https://github.com/nomiclabs/hardhat/issues/2115 legacy-no-optimize legacy-optimize-evm-only legacy-optimize-evm+yul From c15ef45d2969c6a53216c27126294b940e761583 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 6 Dec 2021 15:52:50 +0100 Subject: [PATCH 0083/1704] Explanation about operators. --- docs/types/operators.rst | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/docs/types/operators.rst b/docs/types/operators.rst index 29962588fe..450963e11d 100644 --- a/docs/types/operators.rst +++ b/docs/types/operators.rst @@ -1,7 +1,35 @@ -.. index:: assignment, ! delete, lvalue +.. index:: ! operator -Operators Involving LValues -=========================== +Operators +========= + +Arithmetic and bit operators can be applied even if the two operands do not have the same type. +For example, you can compute ``y = x + z``, where ``x`` is a ``uint8`` and ``z`` has +the type ``int32``. In these cases, the following mechanism will be used to determine +the type in which the operation is computed (this is important in case of overflow) +and the type of the operator's result: + +1. If the type of the right operand can be implicitly converted to the type of the left + operand, use the type of the left operand, +2. if the type of the left operand can be implicitly converted to the type of the right + operand, use the type of the right operand, +3. otherwise, the operation is not allowed. + +In case one of the operands is a :ref:`literal number ` it is first converted to its +"mobile type", which is the smallest type that can hold the value +(unsigned types of the same bit-width are considered "smaller" than the signed types). +If both are literal numbers, the operation is computed with arbitrary precision. + +The operator's result type is the same as the type the operation is performed in, +except for comparison operators where the result is always ``bool``. + +The operators ``**`` (exponentiation), ``<<`` and ``>>`` use the type of the +left operand for the operation and the result. + +.. index:: assignment, lvalue, ! compound operators + +Compound and Increment/Decrement Operators +------------------------------------------ If ``a`` is an LValue (i.e. a variable or something that can be assigned to), the following operators are available as shorthands: @@ -12,6 +40,8 @@ to ``a += 1`` / ``a -= 1`` but the expression itself still has the previous valu of ``a``. In contrast, ``--a`` and ``++a`` have the same effect on ``a`` but return the value after the change. +.. index:: !delete + .. _delete: delete From 9b55d4788e5e008905af060b26f44cac7e45d98e Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Mon, 6 Dec 2021 18:01:27 +0530 Subject: [PATCH 0084/1704] Added sameType check for fromType and toType in YulUtilFunctions.cpp and relevant tests in semanticTests --- Changelog.md | 2 +- libsolidity/codegen/YulUtilFunctions.cpp | 11 ++++- ...on_external_storage_to_storage_dynamic.sol | 43 ++++++++++++++++++ ...o_storage_dynamic_different_mutability.sol | 45 +++++++++++++++++++ ... copy_function_internal_storage_array.sol} | 2 +- .../copy_storage_arrays_of_function_type.sol | 9 ++++ 6 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol create mode 100644 test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol rename test/libsolidity/semanticTests/array/copying/{copy_function_storage_array.sol => copy_function_internal_storage_array.sol} (94%) create mode 100644 test/libsolidity/syntaxTests/array/copy_storage_arrays_of_function_type.sol diff --git a/Changelog.md b/Changelog.md index f9d7552742..c4b67e935b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,7 +11,7 @@ Bugfixes: * SMTChecker: Fix internal error when an unsafe target is solved more than once and the counterexample messages are different. * SMTChecker: Fix soundness of assigned storage/memory local pointers that were not erasing enough knowledge. * Fix internal error when a function has a calldata struct argument with an internal type inside. - + * IR Generator: Fix IR syntax error when copying storage arrays of functions. ### 0.8.10 (2021-11-09) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 1ad9aafa7f..106ad260f9 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -2057,7 +2057,7 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& solAssert(!_fromType.isValueType(), ""); templ("functionName", functionName); templ("resizeArray", resizeArrayFunction(_toType)); - templ("arrayLength",arrayLengthFunction(_fromType)); + templ("arrayLength", arrayLengthFunction(_fromType)); templ("panic", panicFunction(PanicCode::ResourceError)); templ("srcDataLocation", arrayDataAreaFunction(_fromType)); templ("dstDataLocation", arrayDataAreaFunction(_toType)); @@ -2065,7 +2065,14 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& unsigned itemsPerSlot = 32 / _toType.storageStride(); templ("itemsPerSlot", to_string(itemsPerSlot)); templ("multipleItemsPerSlotDst", itemsPerSlot > 1); - bool sameType = _fromType.baseType() == _toType.baseType(); + bool sameType = *_fromType.baseType() == *_toType.baseType(); + if (auto functionType = dynamic_cast(_fromType.baseType())) + { + solAssert(functionType->equalExcludingStateMutability( + dynamic_cast(*_toType.baseType()) + )); + sameType = true; + } templ("sameType", sameType); if (sameType) { diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol new file mode 100644 index 0000000000..543342dfde --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol @@ -0,0 +1,43 @@ +contract C { + function testFunction1() public {} + function testFunction2() public {} + function testFunction3() public {} + + + function() external [3] externalArray0; + function() external [3] externalArray1 = [ + this.testFunction1, + this.testFunction2, + this.testFunction3 + ]; + + function copyExternalStorageArrayOfFunctionType() external returns (bool) { + assert(keccak256(abi.encode(externalArray0)) != keccak256(abi.encode(externalArray1))); + externalArray0 = externalArray1; + return keccak256(abi.encode(externalArray0)) == keccak256(abi.encode(externalArray1)); + } + + function() internal [3] internalArray0; + function() internal [3] internalArray1 = [ + testFunction1, + testFunction2, + testFunction3 + ]; + + function copyInternalArrayOfFunctionType() external returns (bool) { + internalArray0 = internalArray1; + assert(internalArray0.length == 3); + + return + internalArray0.length == internalArray1.length && + internalArray0[0] == internalArray1[0] && + internalArray0[1] == internalArray1[1] && + internalArray0[2] == internalArray1[2]; + } +} +// ==== +// compileViaYul: also +// ---- +// copyExternalStorageArrayOfFunctionType() -> true +// gas legacy: 103412 +// copyInternalArrayOfFunctionType() -> true diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol new file mode 100644 index 0000000000..0e356bce65 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol @@ -0,0 +1,45 @@ +contract C { + function testFunction1() public {} + function testFunction2() public view {} + function testFunction3() public pure {} + + function() external [3] externalArray0; + function() external [3] externalArray1 = [ + this.testFunction1, + this.testFunction2, + this.testFunction3 + ]; + + function copyExternalStorageArraysOfFunctionType() external returns (bool) + { + assert(keccak256(abi.encodePacked(externalArray0)) != keccak256(abi.encodePacked(externalArray1))); + externalArray0 = externalArray1; + return keccak256(abi.encodePacked(externalArray0)) == keccak256(abi.encodePacked(externalArray1)); + } + + function() internal [3] internalArray0; + function() internal [3] internalArray1 = [ + testFunction1, + testFunction2, + testFunction3 + ]; + + function copyInternalArrayOfFunctionType() external returns (bool) + { + internalArray0 = internalArray1; + assert(internalArray0.length == 3); + + return + internalArray0.length == internalArray1.length && + internalArray0[0] == internalArray1[0] && + internalArray0[1] == internalArray1[1] && + internalArray0[2] == internalArray1[2]; + } +} +// ==== +// compileViaYul: also +// ---- +// copyExternalStorageArraysOfFunctionType() -> true +// gas legacy: 103398 +// copyInternalArrayOfFunctionType() -> true +// gas legacy: 104178 diff --git a/test/libsolidity/semanticTests/array/copying/copy_function_storage_array.sol b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol similarity index 94% rename from test/libsolidity/semanticTests/array/copying/copy_function_storage_array.sol rename to test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol index 8448d2e69b..6f019c77c2 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_function_storage_array.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol @@ -18,6 +18,6 @@ contract C { // compileViaYul: also // ---- // test() -> 7 -// gas irOptimized: 126552 +// gas irOptimized: 124080 // gas legacy: 205196 // gas legacyOptimized: 204987 diff --git a/test/libsolidity/syntaxTests/array/copy_storage_arrays_of_function_type.sol b/test/libsolidity/syntaxTests/array/copy_storage_arrays_of_function_type.sol new file mode 100644 index 0000000000..44011bea45 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/copy_storage_arrays_of_function_type.sol @@ -0,0 +1,9 @@ +contract C { + function() external [] s0; + function() external view [] s1; + function copyStorageArrayOfFunctionType() public { + s1 = s0; + } +} +// ---- +// TypeError 7407: (148-150): Type function () external[] storage ref is not implicitly convertible to expected type function () view external[] storage ref. From fdeb9717084e7427100b7ec5778c8a1ab222f5f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Dec 2021 20:45:39 +0100 Subject: [PATCH 0085/1704] Add an appropriate label to each type of issue --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + .github/ISSUE_TEMPLATE/documentation_issue.md | 1 + .github/ISSUE_TEMPLATE/feature_request.md | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 571b97474c..0edc9f79f0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,7 @@ --- name: Bug Report about: Bug reports about the Solidity Compiler. +labels: ["bug :bug:"] --- ## Description diff --git a/.github/ISSUE_TEMPLATE/documentation_issue.md b/.github/ISSUE_TEMPLATE/documentation_issue.md index fc3dd77dbb..c5873f726c 100644 --- a/.github/ISSUE_TEMPLATE/documentation_issue.md +++ b/.github/ISSUE_TEMPLATE/documentation_issue.md @@ -6,18 +6,12 @@ labels: ["documentation :book:"] ## Page - + ## Abstract - + ## Pull request - + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 0b86a08f4f..7191414d43 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -9,40 +9,29 @@ labels: ["feature"] - First, many thanks for taking part in the community. We really appreciate that. - We realize there is a lot of data requested here. We ask only that you do your best to provide as much information as possible so we can better help you. - Support questions are better asked in one of the following locations: - - [Solidity chat](https://gitter.im/ethereum/solidity) - - [Stack Overflow](https://ethereum.stackexchange.com/) + - [Solidity chat](https://gitter.im/ethereum/solidity) + - [Stack Overflow](https://ethereum.stackexchange.com/) - Ensure the issue isn't already reported (check `feature` and `language design` labels). *Delete the above section and the instructions in the sections below before submitting* - --> ## Abstract - + ## Motivation - + ## Specification - + ## Backwards Compatibility \ No newline at end of file +--> From 6035e8c02a96653fa659b667a3dd2ba7705b4967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Dec 2021 21:07:08 +0100 Subject: [PATCH 0087/1704] Configure issue type selection screen to always select the "Solidity" project --- .github/ISSUE_TEMPLATE/config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..931bc8940e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Bug Report + url: https://github.com/ethereum/solidity/issues/new?template=bug_report.md&projects=ethereum/solidity/43 + - name: Documentation Issue + url: https://github.com/ethereum/solidity/issues/new?template=documentation_issue.md&projects=ethereum/solidity/43 + - name: Feature Request + url: https://github.com/ethereum/solidity/issues/new?template=feature_request.md&projects=ethereum/solidity/43 From b2a05a1bcfafa4fbe1344eba19e6e63ceecb6d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Dec 2021 21:07:28 +0100 Subject: [PATCH 0088/1704] Remove unused "general" issue template --- .github/ISSUE_TEMPLATE/general.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/general.md diff --git a/.github/ISSUE_TEMPLATE/general.md b/.github/ISSUE_TEMPLATE/general.md deleted file mode 100644 index e69de29bb2..0000000000 From 9a0821f2c30f9c51bb5d7e6ac4cc85cf42bd6c9b Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 16 Dec 2021 00:11:59 +0100 Subject: [PATCH 0089/1704] Fix warning about reference. --- libyul/backends/evm/StackLayoutGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 43a1d032ce..50dcee5dec 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -247,7 +247,7 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla // before the operation, i.e. if PreviousSlot{2} is at a position at which _post contains VariableSlot{"tmp"}, // then we want the variable tmp in the slot at offset 2 in the layout before the operation. vector> idealLayout(_post.size(), nullopt); - for (auto const& [slot, idealPosition]: ranges::zip_view(_post, layout)) + for (auto&& [slot, idealPosition]: ranges::zip_view(_post, layout)) if (PreviousSlot* previousSlot = std::get_if(&idealPosition)) idealLayout.at(previousSlot->slot) = slot; From 19a74506e39af9448590ce4fefee65fdd7f9c8eb Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Wed, 17 Nov 2021 00:17:37 +0530 Subject: [PATCH 0090/1704] trial test cases extracted from SoliidityEndToEndTest.cpp into .sol files. removed libevmone.so files from the directory trial test cases extracted from SoliidityEndToEndTest.cpp into .sol files. Corresponding code in the .cpp file has been commented instead of begin removed pending preliminary reviews removed libevmone files Added testcase packed_storage_structs_delete added test case invalid_enum_logged added test case enum_referencing added test case memory_types_initialisation added test case return string added test case constant_string_literal.sol removed extractable keyword from solidityEndtoEnd.cpp, moved copying_bytes_multiassigned.sol to array/copying folder, added recv() function to copying_bytes_multiassigned.sol but this test case is failing now change typo error in the name of test case library_staticcall_delegatecal.sol to library_staticcall_delegatecall.sol Added compileToEwasm:false to call_forward_bytes.sol test case and moved it to semanticTests/fallback added compileToEwasm:false line to library_call_in_homestead added compileToEwasm: false line to copying_bytes_multiassign, copy_from_calldata_removes_bytes, enum_referencing, library_call_in_homestead, struct_referencing Added test case internal_types_in_library Added test case mapping_arguments_in_library Added test case mapping_returns_in_library Added test case mapping_returns_in_library_named Added test case using_library_mappings_public Added test case library_function_external Added test case library_stray_values added test case using_library_mappings_return added test case using_library_structs Added test case using_for_function_on_struct and corrections to using_library_structs, using_library_mpapings_return, library_stray_values Added test case using_for_overload added test case using_for_by_name added test case bound_function_in_function added test case bound_function_in_var added test case bound_function_to_string added test case payable_function_calls_library added function call corrections to copying_bytes_multiassign and call_forward_bytes Made changes to the test cases as per comments on PR #12289 mentioned in Changelog.md : Extraced some test cases from SolEndToEnd.cpp --- test/libsolidity/SolidityEndToEndTest.cpp | 519 ------------------ .../copying/copying_bytes_multiassign.sol | 33 ++ .../copy_from_calldata_removes_bytes_data.sol | 19 + .../semanticTests/enums/enum_referencing.sol | 41 ++ .../fallback/call_forward_bytes.sol | 27 + .../bound_function_in_function.sol | 16 + .../functionCall/bound_function_in_var.sol | 16 + .../functionCall/bound_function_to_string.sol | 20 + .../libraries/internal_types_in_library.sol | 30 + .../libraries/library_call_in_homestead.sol | 15 + .../libraries/library_stray_values.sol | 14 + .../mapping_arguments_in_library.sol | 41 ++ .../libraries/mapping_returns_in_library.sol | 75 +++ .../mapping_returns_in_library_named.sol | 31 ++ .../payable_function_calls_library.sol | 14 + .../libraries/using_for_by_name.sol | 16 + .../libraries/using_for_overload.sol | 20 + .../using_library_mappings_public.sol | 27 + .../using_library_mappings_return.sol | 25 + .../libraries/using_library_structs.sol | 27 + .../structs/struct_referencing.sol | 61 ++ .../structs/using_for_function_on_struct.sol | 16 + 22 files changed, 584 insertions(+), 519 deletions(-) create mode 100644 test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol create mode 100644 test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol create mode 100644 test/libsolidity/semanticTests/enums/enum_referencing.sol create mode 100644 test/libsolidity/semanticTests/fallback/call_forward_bytes.sol create mode 100644 test/libsolidity/semanticTests/functionCall/bound_function_in_function.sol create mode 100644 test/libsolidity/semanticTests/functionCall/bound_function_in_var.sol create mode 100644 test/libsolidity/semanticTests/functionCall/bound_function_to_string.sol create mode 100644 test/libsolidity/semanticTests/libraries/internal_types_in_library.sol create mode 100644 test/libsolidity/semanticTests/libraries/library_call_in_homestead.sol create mode 100644 test/libsolidity/semanticTests/libraries/library_stray_values.sol create mode 100644 test/libsolidity/semanticTests/libraries/mapping_arguments_in_library.sol create mode 100644 test/libsolidity/semanticTests/libraries/mapping_returns_in_library.sol create mode 100644 test/libsolidity/semanticTests/libraries/mapping_returns_in_library_named.sol create mode 100644 test/libsolidity/semanticTests/libraries/payable_function_calls_library.sol create mode 100644 test/libsolidity/semanticTests/libraries/using_for_by_name.sol create mode 100644 test/libsolidity/semanticTests/libraries/using_for_overload.sol create mode 100644 test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol create mode 100644 test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol create mode 100644 test/libsolidity/semanticTests/libraries/using_library_structs.sol create mode 100644 test/libsolidity/semanticTests/structs/struct_referencing.sol create mode 100644 test/libsolidity/semanticTests/structs/using_for_function_on_struct.sol diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 4731149618..314d4283e0 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1551,26 +1551,6 @@ BOOST_AUTO_TEST_CASE(generic_staticcall) } } -BOOST_AUTO_TEST_CASE(library_call_in_homestead) -{ - char const* sourceCode = R"( - library Lib { function m() public returns (address) { return msg.sender; } } - contract Test { - address public sender; - function f() public { - sender = Lib.m(); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs()); - ABI_CHECK(callContractFunction("sender()"), encodeArgs(m_sender)); - ) -} - BOOST_AUTO_TEST_CASE(library_call_protection) { // This tests code that reverts a call if it is a direct call to a library @@ -1626,38 +1606,6 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) ); } -BOOST_AUTO_TEST_CASE(call_forward_bytes) -{ - char const* sourceCode = R"( - contract receiver { - uint public received; - function recv(uint x) public { received += x + 1; } - fallback() external { received = 0x80; } - } - contract sender { - constructor() { rec = new receiver(); } - fallback() external { savedData = msg.data; } - function forward() public returns (bool) { address(rec).call(savedData); return true; } - function clear() public returns (bool) { delete savedData; return true; } - function val() public returns (uint) { return rec.received(); } - receiver rec; - bytes savedData; - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN(); - compileAndRun(sourceCode, 0, "sender"); - ABI_CHECK(callContractFunction("recv(uint256)", 7), bytes()); - ABI_CHECK(callContractFunction("val()"), encodeArgs(0)); - ABI_CHECK(callContractFunction("forward()"), encodeArgs(true)); - ABI_CHECK(callContractFunction("val()"), encodeArgs(8)); - ABI_CHECK(callContractFunction("clear()"), encodeArgs(true)); - ABI_CHECK(callContractFunction("val()"), encodeArgs(8)); - ABI_CHECK(callContractFunction("forward()"), encodeArgs(true)); - ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80)); - ); -} - BOOST_AUTO_TEST_CASE(call_forward_bytes_length) { char const* sourceCode = R"( @@ -2576,254 +2524,6 @@ BOOST_AUTO_TEST_CASE(library_function_external) ) } -BOOST_AUTO_TEST_CASE(library_stray_values) -{ - char const* sourceCode = R"( - library Lib { function m(uint x, uint y) public returns (uint) { return x * y; } } - contract Test { - function f(uint x) public returns (uint) { - Lib; - Lib.m; - return x + 9; - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(42))); - ) -} - -BOOST_AUTO_TEST_CASE(internal_types_in_library) -{ - char const* sourceCode = R"( - library Lib { - function find(uint16[] storage _haystack, uint16 _needle) public view returns (uint) - { - for (uint i = 0; i < _haystack.length; ++i) - if (_haystack[i] == _needle) - return i; - return type(uint).max; - } - } - contract Test { - mapping(string => uint16[]) data; - function f() public returns (uint a, uint b) - { - while (data["abc"].length < 20) - data["abc"].push(); - data["abc"][4] = 9; - data["abc"][17] = 3; - a = Lib.find(data["abc"], 9); - b = Lib.find(data["abc"], 3); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4), u256(17))); - ) -} - -BOOST_AUTO_TEST_CASE(mapping_arguments_in_library) -{ - char const* sourceCode = R"( - library Lib { - function set(mapping(uint => uint) storage m, uint key, uint value) internal - { - m[key] = value; - } - function get(mapping(uint => uint) storage m, uint key) internal view returns (uint) - { - return m[key]; - } - } - contract Test { - mapping(uint => uint) m; - function set(uint256 key, uint256 value) public returns (uint) - { - uint oldValue = Lib.get(m, key); - Lib.set(m, key, value); - return oldValue; - } - function get(uint256 key) public view returns (uint) { - return Lib.get(m, key); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(42)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(84)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(7)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(84))); - ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(7))); - ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(21)), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(42)), encodeArgs(u256(84))); - ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(14)), encodeArgs(u256(7))); - ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(21))); - ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(14))); - ) -} - -BOOST_AUTO_TEST_CASE(mapping_returns_in_library) -{ - char const* sourceCode = R"( - library Lib { - function choose_mapping(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint=>uint) storage) - { - return c ? a : b; - } - } - contract Test { - mapping(uint => uint) a; - mapping(uint => uint) b; - function set(bool choice, uint256 key, uint256 value) public returns (uint) - { - mapping(uint => uint) storage m = Lib.choose_mapping(a, b, choice); - uint oldValue = m[key]; - m[key] = value; - return oldValue; - } - function get(bool choice, uint256 key) public view returns (uint) { - return Lib.choose_mapping(a, b, choice)[key]; - } - function get_a(uint256 key) public view returns (uint) { - return a[key]; - } - function get_b(uint256 key) public view returns (uint) { - return b[key]; - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(42)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(84)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(7)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(10)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(11)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(12)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(84))); - ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(7))); - ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(84))); - ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(7))); - ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(10))); - ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(11))); - ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(12))); - ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(10))); - ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(11))); - ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(12))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(21)), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(42)), encodeArgs(u256(84))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(14)), encodeArgs(u256(7))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(30)), encodeArgs(u256(10))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(31)), encodeArgs(u256(11))); - ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(32)), encodeArgs(u256(12))); - ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(21))); - ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(14))); - ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(21))); - ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(14))); - ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(30))); - ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(31))); - ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(32))); - ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(30))); - ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(31))); - ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(32))); - ) -} - -BOOST_AUTO_TEST_CASE(mapping_returns_in_library_named) -{ - char const* sourceCode = R"( - library Lib { - function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b) internal returns(mapping(uint=>uint) storage r) - { - r = a; - r[1] = 42; - r = b; - r[1] = 21; - } - } - contract Test { - mapping(uint => uint) a; - mapping(uint => uint) b; - function f() public returns (uint, uint, uint, uint, uint, uint) - { - Lib.f(a, b)[2] = 84; - return (a[0], a[1], a[2], b[0], b[1], b[2]); - } - function g() public returns (uint, uint, uint, uint, uint, uint) - { - mapping(uint => uint) storage m = Lib.f(a, b); - m[2] = 17; - return (a[0], a[1], a[2], b[0], b[1], b[2]); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(84))); - ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(17))); - ) -} - -BOOST_AUTO_TEST_CASE(using_library_mappings_public) -{ - char const* sourceCode = R"( - library Lib { - function set(mapping(uint => uint) storage m, uint key, uint value) public - { - m[key] = value; - } - } - contract Test { - mapping(uint => uint) m1; - mapping(uint => uint) m2; - function f() public returns (uint, uint, uint, uint, uint, uint) - { - Lib.set(m1, 0, 1); - Lib.set(m1, 2, 42); - Lib.set(m2, 0, 23); - Lib.set(m2, 2, 99); - return (m1[0], m1[1], m1[2], m2[0], m2[1], m2[2]); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(0), u256(42), u256(23), u256(0), u256(99))); - ) -} - BOOST_AUTO_TEST_CASE(using_library_mappings_external) { char const* libSourceCode = R"( @@ -2860,65 +2560,6 @@ BOOST_AUTO_TEST_CASE(using_library_mappings_external) } } -BOOST_AUTO_TEST_CASE(using_library_mappings_return) -{ - char const* sourceCode = R"( - library Lib { - function choose(mapping(uint => mapping(uint => uint)) storage m, uint key) external returns (mapping(uint => uint) storage) { - return m[key]; - } - } - contract Test { - mapping(uint => mapping(uint => uint)) m; - function f() public returns (uint, uint, uint, uint, uint, uint) - { - Lib.choose(m, 0)[0] = 1; - Lib.choose(m, 0)[2] = 42; - Lib.choose(m, 1)[0] = 23; - Lib.choose(m, 1)[2] = 99; - return (m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2]); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(0), u256(42), u256(23), u256(0), u256(99))); - ) -} - -BOOST_AUTO_TEST_CASE(using_library_structs) -{ - char const* sourceCode = R"( - library Lib { - struct Data { uint a; uint[] b; } - function set(Data storage _s) public - { - _s.a = 7; - while (_s.b.length < 20) - _s.b.push(); - _s.b[19] = 8; - } - } - contract Test { - mapping(string => Lib.Data) data; - function f() public returns (uint a, uint b) - { - Lib.set(data["abc"]); - a = data["abc"].a; - b = data["abc"].b[19]; - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "Lib"); - compileAndRun(sourceCode, 0, "Test", bytes(), map{{":Lib", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7), u256(8))); - ) -} - BOOST_AUTO_TEST_CASE(short_strings) { // This test verifies that the byte array encoding that combines length and data works @@ -3114,146 +2755,6 @@ BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size) } } -BOOST_AUTO_TEST_CASE(using_for_function_on_struct) -{ - char const* sourceCode = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } - contract C { - using D for D.s; - D.s public x; - function f(uint a) public returns (uint) { - x.a = 3; - return x.mul(a); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "D"); - compileAndRun(sourceCode, 0, "C", bytes(), map{{":D", m_contractAddress}}); - ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(3 * 7))); - ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(3 * 7))); - ) -} - -BOOST_AUTO_TEST_CASE(using_for_overload) -{ - char const* sourceCode = R"( - library D { - struct s { uint a; } - function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } - function mul(s storage self, bytes32 x) public returns (bytes32) { } - } - contract C { - using D for D.s; - D.s public x; - function f(uint a) public returns (uint) { - x.a = 6; - return x.mul(a); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "D"); - compileAndRun(sourceCode, 0, "C", bytes(), map{{":D", m_contractAddress}}); - ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); - ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); - ) -} - -BOOST_AUTO_TEST_CASE(using_for_by_name) -{ - char const* sourceCode = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } - contract C { - using D for D.s; - D.s public x; - function f(uint a) public returns (uint) { - x.a = 6; - return x.mul({x: a}); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "D"); - compileAndRun(sourceCode, 0, "C", bytes(), map{{":D", m_contractAddress}}); - ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); - ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); - ) -} - -BOOST_AUTO_TEST_CASE(bound_function_in_function) -{ - char const* sourceCode = R"( - library L { - function g(function() internal returns (uint) _t) internal returns (uint) { return _t(); } - } - contract C { - using L for *; - function f() public returns (uint) { - return t.g(); - } - function t() public pure returns (uint) { return 7; } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "L"); - compileAndRun(sourceCode, 0, "C", bytes(), map{{":L", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); - ) -} - -BOOST_AUTO_TEST_CASE(bound_function_in_var) -{ - char const* sourceCode = R"( - library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } - contract C { - using D for D.s; - D.s public x; - function f(uint a) public returns (uint) { - x.a = 6; - return (x.mul)({x: a}); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "D"); - compileAndRun(sourceCode, 0, "C", bytes(), map{{":D", m_contractAddress}}); - ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7))); - ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); - ) -} - -BOOST_AUTO_TEST_CASE(bound_function_to_string) -{ - char const* sourceCode = R"( - library D { function length(string memory self) public returns (uint) { return bytes(self).length; } } - contract C { - using D for string; - string x; - function f() public returns (uint) { - x = "abc"; - return x.length(); - } - function g() public returns (uint) { - string memory s = "abc"; - return s.length(); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "D"); - compileAndRun(sourceCode, 0, "C", bytes(), map{{":D", m_contractAddress}}); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(3))); - ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(3))); - ) -} - BOOST_AUTO_TEST_CASE(inline_long_string_return) { char const* sourceCode = R"( @@ -3406,26 +2907,6 @@ BOOST_AUTO_TEST_CASE(payable_function) BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27); } -BOOST_AUTO_TEST_CASE(payable_function_calls_library) -{ - char const* sourceCode = R"( - library L { - function f() public returns (uint) { return 7; } - } - contract C { - function f() public payable returns (uint) { - return L.f(); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - compileAndRun(sourceCode, 0, "L"); - compileAndRun(sourceCode, 0, "C", bytes(), map{{":L", m_contractAddress}}); - ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs(u256(7))); - ) -} - BOOST_AUTO_TEST_CASE(non_payable_throw) { char const* sourceCode = R"( diff --git a/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol b/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol new file mode 100644 index 0000000000..3583a752d1 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol @@ -0,0 +1,33 @@ +contract receiver { + uint public received; + function recv(uint x) public { received += x + 1; } + fallback() external { received = 0x80; } +} +contract sender { + constructor() { rec = new receiver(); } + fallback() external { savedData1 = savedData2 = msg.data; } + function forward(bool selector) public returns (bool) { + if (selector) { address(rec).call(savedData1); delete savedData1; } + else { address(rec).call(savedData2); delete savedData2; } + return true; + } + function val() public returns (uint) { return rec.received(); } + receiver rec; + bytes savedData1; + bytes savedData2; +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// (): 7 -> +// gas irOptimized: 110941 +// gas legacy: 111082 +// gas legacyOptimized: 111027 +// val() -> 0 +// forward(bool): true -> true +// val() -> 0x80 +// forward(bool): false -> true +// val() -> 0x80 +// forward(bool): true -> true +// val() -> 0x80 diff --git a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol new file mode 100644 index 0000000000..87067b77bc --- /dev/null +++ b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol @@ -0,0 +1,19 @@ +contract c { + function set() public returns (bool) { data = msg.data; return true; } + function checkIfDataIsEmpty() public returns (bool) { return data.length == 0; } + function sendMessage() public returns (bool, bytes memory) { bytes memory emptyData; return address(this).call(emptyData);} + fallback() external { data = msg.data; } + bytes data; +} +// ==== +// EVMVersion: >=byzantium +// compileToEwasm: false +// compileViaYul: also +// ---- +// (): 1, 2, 3, 4, 5 -> +// gas irOptimized: 155178 +// gas legacy: 155254 +// gas legacyOptimized: 155217 +// checkIfDataIsEmpty() -> false +// sendMessage() -> true, 0x40, 0 +// checkIfDataIsEmpty() -> true diff --git a/test/libsolidity/semanticTests/enums/enum_referencing.sol b/test/libsolidity/semanticTests/enums/enum_referencing.sol new file mode 100644 index 0000000000..537c05182b --- /dev/null +++ b/test/libsolidity/semanticTests/enums/enum_referencing.sol @@ -0,0 +1,41 @@ +interface I { + enum Direction { A, B, Left, Right } +} +library L { + enum Direction { Left, Right } + function f() public pure returns (Direction) { + return Direction.Right; + } + function g() public pure returns (I.Direction) { + return I.Direction.Right; + } +} +contract C is I { + function f() public pure returns (Direction) { + return Direction.Right; + } + function g() public pure returns (I.Direction) { + return I.Direction.Right; + } + function h() public pure returns (L.Direction) { + return L.Direction.Right; + } + function x() public pure returns (L.Direction) { + return L.f(); + } + function y() public pure returns (I.Direction) { + return L.g(); + } +} +// ==== +// compileViaYul: also +// compileToEwasm: false +// ---- +// library: L +// f() -> 3 +// g() -> 3 +// f() -> 3 +// g() -> 3 +// h() -> 1 +// x() -> 1 +// y() -> 3 diff --git a/test/libsolidity/semanticTests/fallback/call_forward_bytes.sol b/test/libsolidity/semanticTests/fallback/call_forward_bytes.sol new file mode 100644 index 0000000000..39122e7574 --- /dev/null +++ b/test/libsolidity/semanticTests/fallback/call_forward_bytes.sol @@ -0,0 +1,27 @@ +contract receiver { + uint256 public received; + function recv(uint256 x) public { received += x + 1; } + fallback() external { received = 0x80; } +} +contract sender { + constructor() { rec = new receiver();} + fallback() external { savedData = msg.data; } + function forward() public returns (bool) { address(rec).call(savedData); return true; } + function clear() public returns (bool) { delete savedData; return true; } + function val() public returns (uint) { return rec.received(); } + receiver rec; + bytes savedData; +} +// ==== +// allowNonExistingFunctions: true +// compileToEwasm: false +// compileViaYul: also +// ---- +// recv(uint256): 7 -> +// val() -> 0 +// forward() -> true +// val() -> 8 +// clear() -> true +// val() -> 8 +// forward() -> true +// val() -> 0x80 diff --git a/test/libsolidity/semanticTests/functionCall/bound_function_in_function.sol b/test/libsolidity/semanticTests/functionCall/bound_function_in_function.sol new file mode 100644 index 0000000000..983de5e3ce --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/bound_function_in_function.sol @@ -0,0 +1,16 @@ +library L { + function g(function() internal returns (uint) _t) internal returns (uint) { return _t(); } +} +contract C { + using L for *; + function f() public returns (uint) { + return t.g(); + } + function t() public pure returns (uint) { return 7; } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: L +// f() -> 7 diff --git a/test/libsolidity/semanticTests/functionCall/bound_function_in_var.sol b/test/libsolidity/semanticTests/functionCall/bound_function_in_var.sol new file mode 100644 index 0000000000..ad80241270 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/bound_function_in_var.sol @@ -0,0 +1,16 @@ +library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } +contract C { + using D for D.s; + D.s public x; + function f(uint a) public returns (uint) { + x.a = 6; + return (x.mul)({x: a}); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: D +// f(uint256): 7 -> 0x2a +// x() -> 0x2a diff --git a/test/libsolidity/semanticTests/functionCall/bound_function_to_string.sol b/test/libsolidity/semanticTests/functionCall/bound_function_to_string.sol new file mode 100644 index 0000000000..376768b86d --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/bound_function_to_string.sol @@ -0,0 +1,20 @@ +library D { function length(string memory self) public returns (uint) { return bytes(self).length; } } +contract C { + using D for string; + string x; + function f() public returns (uint) { + x = "abc"; + return x.length(); + } + function g() public returns (uint) { + string memory s = "abc"; + return s.length(); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: D +// f() -> 3 +// g() -> 3 diff --git a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol new file mode 100644 index 0000000000..6b13ee09c3 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol @@ -0,0 +1,30 @@ +library Lib { + function find(uint16[] storage _haystack, uint16 _needle) public view returns (uint) + { + for (uint i = 0; i < _haystack.length; ++i) + if (_haystack[i] == _needle) + return i; + return type(uint).max; + } +} +contract Test { + mapping(string => uint16[]) data; + function f() public returns (uint a, uint b) + { + while (data["abc"].length < 20) + data["abc"].push(); + data["abc"][4] = 9; + data["abc"][17] = 3; + a = Lib.find(data["abc"], 9); + b = Lib.find(data["abc"], 3); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: Lib +// f() -> 4, 0x11 +// gas irOptimized: 115822 +// gas legacy: 135952 +// gas legacyOptimized: 119643 diff --git a/test/libsolidity/semanticTests/libraries/library_call_in_homestead.sol b/test/libsolidity/semanticTests/libraries/library_call_in_homestead.sol new file mode 100644 index 0000000000..6841221f41 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/library_call_in_homestead.sol @@ -0,0 +1,15 @@ +library Lib { function m() public returns (address) { return msg.sender; } } +contract Test { + address public sender; + function f() public { + sender = Lib.m(); + } +} +// ==== +// compileViaYul: also +// compileToEwasm: false +// EVMVersion: >=homestead +// ---- +// library: Lib +// f() -> +// sender() -> 0x1212121212121212121212121212120000000012 diff --git a/test/libsolidity/semanticTests/libraries/library_stray_values.sol b/test/libsolidity/semanticTests/libraries/library_stray_values.sol new file mode 100644 index 0000000000..1692b018a7 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/library_stray_values.sol @@ -0,0 +1,14 @@ +library Lib { function m(uint x, uint y) public returns (uint) { return x * y; } } +contract Test { + function f(uint x) public returns (uint) { + Lib; + Lib.m; + return x + 9; + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: Lib +// f(uint256): 33 -> 0x2a diff --git a/test/libsolidity/semanticTests/libraries/mapping_arguments_in_library.sol b/test/libsolidity/semanticTests/libraries/mapping_arguments_in_library.sol new file mode 100644 index 0000000000..06cfd6e1a1 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/mapping_arguments_in_library.sol @@ -0,0 +1,41 @@ +library Lib { + function set(mapping(uint => uint) storage m, uint key, uint value) internal + { + m[key] = value; + } + function get(mapping(uint => uint) storage m, uint key) internal view returns (uint) + { + return m[key]; + } +} +contract Test { + mapping(uint => uint) m; + function set(uint256 key, uint256 value) public returns (uint) + { + uint oldValue = Lib.get(m, key); + Lib.set(m, key, value); + return oldValue; + } + function get(uint256 key) public view returns (uint) { + return Lib.get(m, key); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: Lib +// set(uint256,uint256): 1, 42 -> 0 +// set(uint256,uint256): 2, 84 -> 0 +// set(uint256,uint256): 21, 7 -> 0 +// get(uint256): 0 -> 0 +// get(uint256): 1 -> 0x2a +// get(uint256): 2 -> 0x54 +// get(uint256): 21 -> 7 +// set(uint256,uint256): 1, 21 -> 0x2a +// set(uint256,uint256): 2, 42 -> 0x54 +// set(uint256,uint256): 21, 14 -> 7 +// get(uint256): 0 -> 0 +// get(uint256): 1 -> 0x15 +// get(uint256): 2 -> 0x2a +// get(uint256): 21 -> 14 diff --git a/test/libsolidity/semanticTests/libraries/mapping_returns_in_library.sol b/test/libsolidity/semanticTests/libraries/mapping_returns_in_library.sol new file mode 100644 index 0000000000..dd2b2953fa --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/mapping_returns_in_library.sol @@ -0,0 +1,75 @@ +library Lib { + function choose_mapping(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint=>uint) storage) + { + return c ? a : b; + } +} +contract Test { + mapping(uint => uint) a; + mapping(uint => uint) b; + function set(bool choice, uint256 key, uint256 value) public returns (uint) + { + mapping(uint => uint) storage m = Lib.choose_mapping(a, b, choice); + uint oldValue = m[key]; + m[key] = value; + return oldValue; + } + function get(bool choice, uint256 key) public view returns (uint) { + return Lib.choose_mapping(a, b, choice)[key]; + } + function get_a(uint256 key) public view returns (uint) { + return a[key]; + } + function get_b(uint256 key) public view returns (uint) { + return b[key]; + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: Lib +// set(bool,uint256,uint256): true, 1, 42 -> 0 +// set(bool,uint256,uint256): true, 2, 84 -> 0 +// set(bool,uint256,uint256): true, 21, 7 -> 0 +// set(bool,uint256,uint256): false, 1, 10 -> 0 +// set(bool,uint256,uint256): false, 2, 11 -> 0 +// set(bool,uint256,uint256): false, 21, 12 -> 0 +// get(bool,uint256): true, 0 -> 0 +// get(bool,uint256): true, 1 -> 0x2a +// get(bool,uint256): true, 2 -> 0x54 +// get(bool,uint256): true, 21 -> 7 +// get_a(uint256): 0 -> 0 +// get_a(uint256): 1 -> 0x2a +// get_a(uint256): 2 -> 0x54 +// get_a(uint256): 21 -> 7 +// get(bool,uint256): false, 0 -> 0 +// get(bool,uint256): false, 1 -> 10 +// get(bool,uint256): false, 2 -> 11 +// get(bool,uint256): false, 21 -> 12 +// get_b(uint256): 0 -> 0 +// get_b(uint256): 1 -> 10 +// get_b(uint256): 2 -> 11 +// get_b(uint256): 21 -> 12 +// set(bool,uint256,uint256): true, 1, 21 -> 0x2a +// set(bool,uint256,uint256): true, 2, 42 -> 0x54 +// set(bool,uint256,uint256): true, 21, 14 -> 7 +// set(bool,uint256,uint256): false, 1, 30 -> 10 +// set(bool,uint256,uint256): false, 2, 31 -> 11 +// set(bool,uint256,uint256): false, 21, 32 -> 12 +// get_a(uint256): 0 -> 0 +// get_a(uint256): 1 -> 0x15 +// get_a(uint256): 2 -> 0x2a +// get_a(uint256): 21 -> 14 +// get(bool,uint256): true, 0 -> 0 +// get(bool,uint256): true, 1 -> 0x15 +// get(bool,uint256): true, 2 -> 0x2a +// get(bool,uint256): true, 21 -> 14 +// get_b(uint256): 0 -> 0 +// get_b(uint256): 1 -> 0x1e +// get_b(uint256): 2 -> 0x1f +// get_b(uint256): 21 -> 0x20 +// get(bool,uint256): false, 0 -> 0 +// get(bool,uint256): false, 1 -> 0x1e +// get(bool,uint256): false, 2 -> 0x1f +// get(bool,uint256): false, 21 -> 0x20 diff --git a/test/libsolidity/semanticTests/libraries/mapping_returns_in_library_named.sol b/test/libsolidity/semanticTests/libraries/mapping_returns_in_library_named.sol new file mode 100644 index 0000000000..23f851279a --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/mapping_returns_in_library_named.sol @@ -0,0 +1,31 @@ +library Lib { + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b) internal returns(mapping(uint=>uint) storage r) + { + r = a; + r[1] = 42; + r = b; + r[1] = 21; + } +} +contract Test { + mapping(uint => uint) a; + mapping(uint => uint) b; + function f() public returns (uint, uint, uint, uint, uint, uint) + { + Lib.f(a, b)[2] = 84; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + function g() public returns (uint, uint, uint, uint, uint, uint) + { + mapping(uint => uint) storage m = Lib.f(a, b); + m[2] = 17; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: Lib +// f() -> 0, 0x2a, 0, 0, 0x15, 0x54 +// g() -> 0, 0x2a, 0, 0, 0x15, 0x11 diff --git a/test/libsolidity/semanticTests/libraries/payable_function_calls_library.sol b/test/libsolidity/semanticTests/libraries/payable_function_calls_library.sol new file mode 100644 index 0000000000..6b0488f06f --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/payable_function_calls_library.sol @@ -0,0 +1,14 @@ +library L { + function f() public returns (uint) { return 7; } +} +contract C { + function f() public payable returns (uint) { + return L.f(); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: L +// f(): 27 -> 7 diff --git a/test/libsolidity/semanticTests/libraries/using_for_by_name.sol b/test/libsolidity/semanticTests/libraries/using_for_by_name.sol new file mode 100644 index 0000000000..8a84c8aaac --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/using_for_by_name.sol @@ -0,0 +1,16 @@ +library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } +contract C { + using D for D.s; + D.s public x; + function f(uint a) public returns (uint) { + x.a = 6; + return x.mul({x: a}); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: D +// f(uint256): 7 -> 0x2a +// x() -> 0x2a diff --git a/test/libsolidity/semanticTests/libraries/using_for_overload.sol b/test/libsolidity/semanticTests/libraries/using_for_overload.sol new file mode 100644 index 0000000000..54cfe0ce10 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/using_for_overload.sol @@ -0,0 +1,20 @@ +library D { + struct s { uint a; } + function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } + function mul(s storage self, bytes32 x) public returns (bytes32) { } +} +contract C { + using D for D.s; + D.s public x; + function f(uint a) public returns (uint) { + x.a = 6; + return x.mul(a); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: D +// f(uint256): 7 -> 0x2a +// x() -> 0x2a diff --git a/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol b/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol new file mode 100644 index 0000000000..d85f906949 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol @@ -0,0 +1,27 @@ +library Lib { + function set(mapping(uint => uint) storage m, uint key, uint value) public + { + m[key] = value; + } +} +contract Test { + mapping(uint => uint) m1; + mapping(uint => uint) m2; + function f() public returns (uint, uint, uint, uint, uint, uint) + { + Lib.set(m1, 0, 1); + Lib.set(m1, 2, 42); + Lib.set(m2, 0, 23); + Lib.set(m2, 2, 99); + return (m1[0], m1[1], m1[2], m2[0], m2[1], m2[2]); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: Lib +// f() -> 1, 0, 0x2a, 0x17, 0, 0x63 +// gas irOptimized: 119757 +// gas legacy: 124793 +// gas legacyOptimized: 119694 diff --git a/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol b/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol new file mode 100644 index 0000000000..9192fdfe31 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol @@ -0,0 +1,25 @@ +library Lib { + function choose(mapping(uint => mapping(uint => uint)) storage m, uint key) external returns (mapping(uint => uint) storage) { + return m[key]; + } +} +contract Test { + mapping(uint => mapping(uint => uint)) m; + function f() public returns (uint, uint, uint, uint, uint, uint) + { + Lib.choose(m, 0)[0] = 1; + Lib.choose(m, 0)[2] = 42; + Lib.choose(m, 1)[0] = 23; + Lib.choose(m, 1)[2] = 99; + return (m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2]); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: Lib +// f() -> 1, 0, 0x2a, 0x17, 0, 0x63 +// gas irOptimized: 120471 +// gas legacy: 125245 +// gas legacyOptimized: 120153 diff --git a/test/libsolidity/semanticTests/libraries/using_library_structs.sol b/test/libsolidity/semanticTests/libraries/using_library_structs.sol new file mode 100644 index 0000000000..4348c377c7 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/using_library_structs.sol @@ -0,0 +1,27 @@ +library Lib { + struct Data { uint a; uint[] b; } + function set(Data storage _s) public + { + _s.a = 7; + while (_s.b.length < 20) + _s.b.push(); + _s.b[19] = 8; + } +} +contract Test { + mapping(string => Lib.Data) data; + function f() public returns (uint a, uint b) + { + Lib.set(data["abc"]); + a = data["abc"].a; + b = data["abc"].b[19]; + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: Lib +// f() -> 7, 8 +// gas irOptimized: 101869 +// gas legacy: 101504 diff --git a/test/libsolidity/semanticTests/structs/struct_referencing.sol b/test/libsolidity/semanticTests/structs/struct_referencing.sol new file mode 100644 index 0000000000..af2357a23e --- /dev/null +++ b/test/libsolidity/semanticTests/structs/struct_referencing.sol @@ -0,0 +1,61 @@ +pragma abicoder v2; +interface I { + struct S { uint a; } +} + +library L { + struct S { uint b; uint a; } + function f() public pure returns (S memory) { + S memory s; + s.a = 3; + return s; + } + function g() public pure returns (I.S memory) { + I.S memory s; + s.a = 4; + return s; + } + // argument-dependant lookup tests + function a(I.S memory) public pure returns (uint) { return 1; } + function a(S memory) public pure returns (uint) { return 2; } +} + +contract C is I { + function f() public pure returns (S memory) { + S memory s; + s.a = 1; + return s; + } + function g() public pure returns (I.S memory) { + I.S memory s; + s.a = 2; + return s; + } + function h() public pure returns (L.S memory) { + L.S memory s; + s.a = 5; + return s; + } + function x() public pure returns (L.S memory) { + return L.f(); + } + function y() public pure returns (I.S memory) { + return L.g(); + } + function a1() public pure returns (uint) { S memory s; return L.a(s); } + function a2() public pure returns (uint) { L.S memory s; return L.a(s); } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: L +// f() -> 1 +// g() -> 2 +// f() -> 1 +// g() -> 2 +// h() -> 0, 5 +// x() -> 0, 3 +// y() -> 4 +// a1() -> 1 +// a2() -> 2 diff --git a/test/libsolidity/semanticTests/structs/using_for_function_on_struct.sol b/test/libsolidity/semanticTests/structs/using_for_function_on_struct.sol new file mode 100644 index 0000000000..347aeb5951 --- /dev/null +++ b/test/libsolidity/semanticTests/structs/using_for_function_on_struct.sol @@ -0,0 +1,16 @@ +library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } } +contract C { + using D for D.s; + D.s public x; + function f(uint a) public returns (uint) { + x.a = 3; + return x.mul(a); + } +} +// ==== +// compileToEwasm: false +// compileViaYul: also +// ---- +// library: D +// f(uint256): 7 -> 0x15 +// x() -> 0x15 From 7cc7a0f1839c95607c8e2eb4a80bb5a8d82229fd Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Mon, 6 Dec 2021 18:01:27 +0530 Subject: [PATCH 0091/1704] Added sameType check for fromType and toType in YulUtilFunctions.cpp and relevant tests in semanticTests --- ...on_external_storage_to_storage_dynamic.sol | 46 +++++++++++------- ...o_storage_dynamic_different_mutability.sol | 48 ++++++++++++------- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol index 543342dfde..8bd9ee42c2 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol @@ -4,12 +4,27 @@ contract C { function testFunction3() public {} - function() external [3] externalArray0; - function() external [3] externalArray1 = [ - this.testFunction1, - this.testFunction2, - this.testFunction3 - ]; + function() external [] externalArray0; + function() external [] externalArray1; + + function() internal [] internalArray0; + function() internal [] internalArray1; + + constructor() { + externalArray0 = new function() external[] (3); + externalArray1 = [ + this.testFunction1, + this.testFunction2, + this.testFunction3 + ]; + + internalArray0 = new function() internal[] (3); + internalArray1 = [ + testFunction1, + testFunction2, + testFunction3 + ]; + } function copyExternalStorageArrayOfFunctionType() external returns (bool) { assert(keccak256(abi.encode(externalArray0)) != keccak256(abi.encode(externalArray1))); @@ -17,27 +32,22 @@ contract C { return keccak256(abi.encode(externalArray0)) == keccak256(abi.encode(externalArray1)); } - function() internal [3] internalArray0; - function() internal [3] internalArray1 = [ - testFunction1, - testFunction2, - testFunction3 - ]; - function copyInternalArrayOfFunctionType() external returns (bool) { internalArray0 = internalArray1; assert(internalArray0.length == 3); return - internalArray0.length == internalArray1.length && - internalArray0[0] == internalArray1[0] && - internalArray0[1] == internalArray1[1] && - internalArray0[2] == internalArray1[2]; + internalArray0.length == internalArray1.length && + internalArray0[0] == internalArray1[0] && + internalArray0[1] == internalArray1[1] && + internalArray0[2] == internalArray1[2]; } } // ==== // compileViaYul: also // ---- // copyExternalStorageArrayOfFunctionType() -> true -// gas legacy: 103412 +// gas irOptimized: 104701 +// gas legacy: 108725 +// gas legacyOptimized: 102441 // copyInternalArrayOfFunctionType() -> true diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol index 0e356bce65..63236ed774 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol @@ -3,12 +3,29 @@ contract C { function testFunction2() public view {} function testFunction3() public pure {} - function() external [3] externalArray0; - function() external [3] externalArray1 = [ - this.testFunction1, - this.testFunction2, - this.testFunction3 - ]; + + function() external [] externalArray0; + function() external [] externalArray1; + + function() internal [] internalArray0; + function() internal [] internalArray1; + + constructor() { + externalArray0 = new function() external[] (3); + externalArray1 = [ + this.testFunction1, + this.testFunction2, + this.testFunction3 + ]; + + internalArray0 = new function() internal[] (3); + internalArray1 = [ + testFunction1, + testFunction2, + testFunction3 + ]; + } + function copyExternalStorageArraysOfFunctionType() external returns (bool) { @@ -17,29 +34,24 @@ contract C { return keccak256(abi.encodePacked(externalArray0)) == keccak256(abi.encodePacked(externalArray1)); } - function() internal [3] internalArray0; - function() internal [3] internalArray1 = [ - testFunction1, - testFunction2, - testFunction3 - ]; - function copyInternalArrayOfFunctionType() external returns (bool) { internalArray0 = internalArray1; assert(internalArray0.length == 3); return - internalArray0.length == internalArray1.length && - internalArray0[0] == internalArray1[0] && - internalArray0[1] == internalArray1[1] && - internalArray0[2] == internalArray1[2]; + internalArray0.length == internalArray1.length && + internalArray0[0] == internalArray1[0] && + internalArray0[1] == internalArray1[1] && + internalArray0[2] == internalArray1[2]; } } // ==== // compileViaYul: also // ---- // copyExternalStorageArraysOfFunctionType() -> true -// gas legacy: 103398 +// gas irOptimized: 104372 +// gas legacy: 108462 +// gas legacyOptimized: 102174 // copyInternalArrayOfFunctionType() -> true // gas legacy: 104178 From 7a96953e78cc2083db182db1628ad68da785d03c Mon Sep 17 00:00:00 2001 From: Marenz Date: Thu, 11 Nov 2021 16:21:23 +0100 Subject: [PATCH 0092/1704] Implement typechecked abi.encodeCall() --- Changelog.md | 1 + docs/cheatsheet.rst | 2 + docs/units-and-global-variables.rst | 1 + libsolidity/analysis/TypeChecker.cpp | 113 ++++++++++++++++++ libsolidity/analysis/TypeChecker.h | 3 + libsolidity/analysis/ViewPureChecker.cpp | 1 + libsolidity/ast/Types.cpp | 11 ++ libsolidity/ast/Types.h | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 56 ++++++--- .../codegen/ir/IRGeneratorForStatements.cpp | 48 ++++++-- libsolidity/formal/SMTEncoder.cpp | 2 + libsolidity/formal/SymbolicState.cpp | 9 ++ .../abiencodedecode/abi_encode_call.sol | 51 ++++++++ .../abi_encode_call_is_consistent.sol | 63 ++++++++++ .../abi_encode_call_memory.sol | 28 +++++ .../abi_encode_call_special_args.sol | 48 ++++++++ .../abi_encode_with_signaturev2.sol | 1 - .../abi/abi_encode_call_simple.sol | 26 ++++ .../specialFunctions/encodeCall.sol | 82 +++++++++++++ .../encodeCall_nested_tuple.sol | 9 ++ .../encodeCall_tuple_incomplete.sol | 8 ++ 21 files changed, 538 insertions(+), 26 deletions(-) create mode 100644 test/libsolidity/semanticTests/abiencodedecode/abi_encode_call.sol create mode 100644 test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_is_consistent.sol create mode 100644 test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_memory.sol create mode 100644 test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_special_args.sol create mode 100644 test/libsolidity/smtCheckerTests/abi/abi_encode_call_simple.sol create mode 100644 test/libsolidity/syntaxTests/specialFunctions/encodeCall.sol create mode 100644 test/libsolidity/syntaxTests/specialFunctions/encodeCall_nested_tuple.sol create mode 100644 test/libsolidity/syntaxTests/specialFunctions/encodeCall_tuple_incomplete.sol diff --git a/Changelog.md b/Changelog.md index c4b67e935b..577bc40643 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.11 (unreleased) Language Features: + * General: New builtin function ``abi.encodeCall(functionPointer, (arg1, arg2, ...))`` that type-checks the arguments and returns the ABI-encoded function call data. Compiler Features: diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 17537914ac..1aa8f24ef3 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -80,6 +80,8 @@ Global Variables the given arguments. Note that this encoding can be ambiguous! - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: :ref:`ABI `-encodes the given arguments starting from the second and prepends the given four-byte selector +- ``abi.encodeCall(function functionPointer, (...)) returns (bytes memory)``: ABI-encodes a call to ``functionPointer`` with the arguments found in the + tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, (...))`` - ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)`` - ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index ac11e08067..70125636c2 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -136,6 +136,7 @@ ABI Encoding and Decoding Functions - ``abi.encodePacked(...) returns (bytes memory)``: Performs :ref:`packed encoding ` of the given arguments. Note that packed encoding can be ambiguous! - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: ABI-encodes the given arguments starting from the second and prepends the given four-byte selector - ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`` +- ``abi.encodeCall(function functionPointer, (...)) returns (bytes memory)``: ABI-encodes a call to ``functionPointer`` with the arguments found in the tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, (...))`` .. note:: These encoding functions can be used to craft data for external function calls without actually diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 5cc208d698..aacd233a2a 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1996,6 +1996,7 @@ void TypeChecker::typeCheckABIEncodeFunctions( _functionType->kind() == FunctionType::Kind::ABIEncode || _functionType->kind() == FunctionType::Kind::ABIEncodePacked || _functionType->kind() == FunctionType::Kind::ABIEncodeWithSelector || + _functionType->kind() == FunctionType::Kind::ABIEncodeCall || _functionType->kind() == FunctionType::Kind::ABIEncodeWithSignature, "ABI function has unexpected FunctionType::Kind." ); @@ -2020,6 +2021,13 @@ void TypeChecker::typeCheckABIEncodeFunctions( // Perform standard function call type checking typeCheckFunctionGeneralChecks(_functionCall, _functionType); + // No further generic checks needed as we do a precise check for ABIEncodeCall + if (_functionType->kind() == FunctionType::Kind::ABIEncodeCall) + { + typeCheckABIEncodeCallFunction(_functionCall); + return; + } + // Check additional arguments for variadic functions vector> const& arguments = _functionCall.arguments(); for (size_t i = 0; i < arguments.size(); ++i) @@ -2078,6 +2086,110 @@ void TypeChecker::typeCheckABIEncodeFunctions( } } +void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCall) +{ + vector> const& arguments = _functionCall.arguments(); + + // Expecting first argument to be the function pointer and second to be a tuple. + if (arguments.size() != 2) + { + m_errorReporter.typeError( + 6219_error, + _functionCall.location(), + "Expected two arguments: a function pointer followed by a tuple." + ); + return; + } + + auto const functionPointerType = dynamic_cast(type(*arguments.front())); + + if (!functionPointerType) + { + m_errorReporter.typeError( + 5511_error, + arguments.front()->location(), + "Expected first argument to be a function pointer, not \"" + + type(*arguments.front())->canonicalName() + + "\"." + ); + return; + } + + if (functionPointerType->kind() != FunctionType::Kind::External) + { + string msg = "Function must be \"public\" or \"external\"."; + SecondarySourceLocation ssl{}; + + if (functionPointerType->hasDeclaration()) + { + ssl.append("Function is declared here:", functionPointerType->declaration().location()); + if (functionPointerType->declaration().scope() == m_currentContract) + msg += " Did you forget to prefix \"this.\"?"; + } + + m_errorReporter.typeError(3509_error, arguments[0]->location(), ssl, msg); + return; + } + + solAssert(!functionPointerType->takesArbitraryParameters(), "Function must have fixed parameters."); + + // Tuples with only one component become that component + vector> callArguments; + + auto const* tupleType = dynamic_cast(type(*arguments[1])); + if (tupleType) + { + auto const& argumentTuple = dynamic_cast(*arguments[1].get()); + callArguments = decltype(callArguments){argumentTuple.components().begin(), argumentTuple.components().end()}; + } + else + callArguments.push_back(arguments[1]); + + if (functionPointerType->parameterTypes().size() != callArguments.size()) + { + if (tupleType) + m_errorReporter.typeError( + 7788_error, + _functionCall.location(), + "Expected " + + to_string(functionPointerType->parameterTypes().size()) + + " instead of " + + to_string(callArguments.size()) + + " components for the tuple parameter." + ); + else + m_errorReporter.typeError( + 7515_error, + _functionCall.location(), + "Expected a tuple with " + + to_string(functionPointerType->parameterTypes().size()) + + " components instead of a single non-tuple parameter." + ); + } + + // Use min() to check as much as we can before failing fatally + size_t const numParameters = min(callArguments.size(), functionPointerType->parameterTypes().size()); + + for (size_t i = 0; i < numParameters; i++) + { + Type const& argType = *type(*callArguments[i]); + BoolResult result = argType.isImplicitlyConvertibleTo(*functionPointerType->parameterTypes()[i]); + if (!result) + m_errorReporter.typeError( + 5407_error, + callArguments[i]->location(), + "Cannot implicitly convert component at position " + + to_string(i) + + " from \"" + + argType.canonicalName() + + "\" to \"" + + functionPointerType->parameterTypes()[i]->canonicalName() + + "\"" + + (result.message().empty() ? "." : ": " + result.message()) + ); + } +} + void TypeChecker::typeCheckBytesConcatFunction( FunctionCall const& _functionCall, FunctionType const* _functionType @@ -2507,6 +2619,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) case FunctionType::Kind::ABIEncodePacked: case FunctionType::Kind::ABIEncodeWithSelector: case FunctionType::Kind::ABIEncodeWithSignature: + case FunctionType::Kind::ABIEncodeCall: { typeCheckABIEncodeFunctions(_functionCall, functionType); returnTypes = functionType->returnParameterTypes(); diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index ba445ffbb0..7586f9d151 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -110,6 +110,9 @@ class TypeChecker: private ASTConstVisitor FunctionTypePointer _functionType ); + /// Performs checks specific to the ABI encode functions of type ABIEncodeCall + void typeCheckABIEncodeCallFunction(FunctionCall const& _functionCall); + /// Performs general checks and checks specific to bytes concat function call void typeCheckBytesConcatFunction( FunctionCall const& _functionCall, diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 81f755cec0..252210a129 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -367,6 +367,7 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess) {MagicType::Kind::ABI, "encode"}, {MagicType::Kind::ABI, "encodePacked"}, {MagicType::Kind::ABI, "encodeWithSelector"}, + {MagicType::Kind::ABI, "encodeCall"}, {MagicType::Kind::ABI, "encodeWithSignature"}, {MagicType::Kind::Message, "data"}, {MagicType::Kind::Message, "sig"}, diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index fe0ac8ef86..aa1d5820f0 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2935,6 +2935,7 @@ string FunctionType::richIdentifier() const case Kind::ABIEncode: id += "abiencode"; break; case Kind::ABIEncodePacked: id += "abiencodepacked"; break; case Kind::ABIEncodeWithSelector: id += "abiencodewithselector"; break; + case Kind::ABIEncodeCall: id += "abiencodecall"; break; case Kind::ABIEncodeWithSignature: id += "abiencodewithsignature"; break; case Kind::ABIDecode: id += "abidecode"; break; case Kind::MetaType: id += "metatype"; break; @@ -3499,6 +3500,7 @@ bool FunctionType::isPure() const m_kind == Kind::ABIEncode || m_kind == Kind::ABIEncodePacked || m_kind == Kind::ABIEncodeWithSelector || + m_kind == Kind::ABIEncodeCall || m_kind == Kind::ABIEncodeWithSignature || m_kind == Kind::ABIDecode || m_kind == Kind::MetaType || @@ -4001,6 +4003,15 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const true, StateMutability::Pure )}, + {"encodeCall", TypeProvider::function( + TypePointers{}, + TypePointers{TypeProvider::array(DataLocation::Memory)}, + strings{}, + strings{1, ""}, + FunctionType::Kind::ABIEncodeCall, + true, + StateMutability::Pure + )}, {"encodeWithSignature", TypeProvider::function( TypePointers{TypeProvider::array(DataLocation::Memory, true)}, TypePointers{TypeProvider::array(DataLocation::Memory)}, diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index b08694820b..8b3826ca06 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1237,6 +1237,7 @@ class FunctionType: public Type ABIEncode, ABIEncodePacked, ABIEncodeWithSelector, + ABIEncodeCall, ABIEncodeWithSignature, ABIDecode, GasLeft, ///< gasleft() diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 07d37c4c58..5a633d2e66 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1236,28 +1236,47 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) case FunctionType::Kind::ABIEncode: case FunctionType::Kind::ABIEncodePacked: case FunctionType::Kind::ABIEncodeWithSelector: + case FunctionType::Kind::ABIEncodeCall: case FunctionType::Kind::ABIEncodeWithSignature: { bool const isPacked = function.kind() == FunctionType::Kind::ABIEncodePacked; bool const hasSelectorOrSignature = function.kind() == FunctionType::Kind::ABIEncodeWithSelector || + function.kind() == FunctionType::Kind::ABIEncodeCall || function.kind() == FunctionType::Kind::ABIEncodeWithSignature; TypePointers argumentTypes; - TypePointers targetTypes; - for (unsigned i = 0; i < arguments.size(); ++i) + + ASTNode::listAccept(arguments, *this); + + if (function.kind() == FunctionType::Kind::ABIEncodeCall) { - arguments[i]->accept(*this); - // Do not keep the selector as part of the ABI encoded args - if (!hasSelectorOrSignature || i > 0) - argumentTypes.push_back(arguments[i]->annotation().type); + solAssert(arguments.size() == 2); + + auto const functionPtr = dynamic_cast(arguments[0]->annotation().type); + solAssert(functionPtr); + solAssert(functionPtr->sizeOnStack() == 2); + + // Account for tuples with one component which become that component + if (auto const tupleType = dynamic_cast(arguments[1]->annotation().type)) + argumentTypes = tupleType->components(); + else + argumentTypes.emplace_back(arguments[1]->annotation().type); } + else + for (unsigned i = 0; i < arguments.size(); ++i) + { + // Do not keep the selector as part of the ABI encoded args + if (!hasSelectorOrSignature || i > 0) + argumentTypes.push_back(arguments[i]->annotation().type); + } + utils().fetchFreeMemoryPointer(); - // stack now: [] .. + // stack now: [] .. // adjust by 32(+4) bytes to accommodate the length(+selector) m_context << u256(32 + (hasSelectorOrSignature ? 4 : 0)) << Instruction::ADD; - // stack now: [] .. + // stack now: [] .. if (isPacked) { @@ -1270,7 +1289,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().abiEncode(argumentTypes, TypePointers()); } utils().fetchFreeMemoryPointer(); - // stack: [] + // stack: [] // size is end minus start minus length slot m_context.appendInlineAssembly(R"({ @@ -1278,16 +1297,17 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) })", {"mem_end", "mem_ptr"}); m_context << Instruction::SWAP1; utils().storeFreeMemoryPointer(); - // stack: [] + // stack: [] if (hasSelectorOrSignature) { - // stack: + // stack: solAssert(arguments.size() >= 1, ""); Type const* selectorType = arguments[0]->annotation().type; utils().moveIntoStack(selectorType->sizeOnStack()); Type const* dataOnStack = selectorType; - // stack: + + // stack: if (function.kind() == FunctionType::Kind::ABIEncodeWithSignature) { // hash the signature @@ -1299,7 +1319,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) else { utils().fetchFreeMemoryPointer(); - // stack: + // stack: utils().packedEncode(TypePointers{selectorType}, TypePointers()); utils().toSizeAfterFreeMemoryPointer(); m_context << Instruction::KECCAK256; @@ -1308,10 +1328,16 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) dataOnStack = TypeProvider::fixedBytes(32); } } - else + else if (function.kind() == FunctionType::Kind::ABIEncodeCall) { - solAssert(function.kind() == FunctionType::Kind::ABIEncodeWithSelector, ""); + // stack: + // Extract selector from the stack + m_context << Instruction::SWAP1 << Instruction::POP; + // Conversion will be done below + dataOnStack = TypeProvider::uint(32); } + else + solAssert(function.kind() == FunctionType::Kind::ABIEncodeWithSelector, ""); utils().convertType(*dataOnStack, FixedBytesType(4), true); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 85b21bbdcd..179b3e739b 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1104,29 +1104,57 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) case FunctionType::Kind::ABIEncode: case FunctionType::Kind::ABIEncodePacked: case FunctionType::Kind::ABIEncodeWithSelector: + case FunctionType::Kind::ABIEncodeCall: case FunctionType::Kind::ABIEncodeWithSignature: { bool const isPacked = functionType->kind() == FunctionType::Kind::ABIEncodePacked; solAssert(functionType->padArguments() != isPacked, ""); bool const hasSelectorOrSignature = functionType->kind() == FunctionType::Kind::ABIEncodeWithSelector || + functionType->kind() == FunctionType::Kind::ABIEncodeCall || functionType->kind() == FunctionType::Kind::ABIEncodeWithSignature; TypePointers argumentTypes; TypePointers targetTypes; vector argumentVars; - for (size_t i = 0; i < arguments.size(); ++i) + string selector; + vector> argumentsOfEncodeFunction; + + if (functionType->kind() == FunctionType::Kind::ABIEncodeCall) { - // ignore selector - if (hasSelectorOrSignature && i == 0) - continue; - argumentTypes.emplace_back(&type(*arguments[i])); - targetTypes.emplace_back(type(*arguments[i]).fullEncodingType(false, true, isPacked)); - argumentVars += IRVariable(*arguments[i]).stackSlots(); + solAssert(arguments.size() == 2, ""); + // Account for tuples with one component which become that component + if (type(*arguments[1]).category() == Type::Category::Tuple) + { + auto const& tupleExpression = dynamic_cast(*arguments[1]); + for (auto component: tupleExpression.components()) + argumentsOfEncodeFunction.push_back(component); + } + else + argumentsOfEncodeFunction.push_back(arguments[1]); } + else + for (size_t i = 0; i < arguments.size(); ++i) + { + // ignore selector + if (hasSelectorOrSignature && i == 0) + continue; + argumentsOfEncodeFunction.push_back(arguments[i]); + } - string selector; - if (functionType->kind() == FunctionType::Kind::ABIEncodeWithSignature) + for (auto const& argument: argumentsOfEncodeFunction) + { + argumentTypes.emplace_back(&type(*argument)); + targetTypes.emplace_back(type(*argument).fullEncodingType(false, true, isPacked)); + argumentVars += IRVariable(*argument).stackSlots(); + } + + if (functionType->kind() == FunctionType::Kind::ABIEncodeCall) + selector = convert( + IRVariable(*arguments[0]).part("functionSelector"), + *TypeProvider::fixedBytes(4) + ).name(); + else if (functionType->kind() == FunctionType::Kind::ABIEncodeWithSignature) { // hash the signature Type const& selectorType = type(*arguments.front()); @@ -1833,7 +1861,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) define(_memberAccess) << requestedValue << "\n"; } - else if (set{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}.count(member)) + else if (set{"encode", "encodePacked", "encodeWithSelector", "encodeCall", "encodeWithSignature", "decode"}.count(member)) { // no-op } diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 8326b6b2f8..68545f4f6b 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -637,6 +637,7 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::ABIEncode: case FunctionType::Kind::ABIEncodePacked: case FunctionType::Kind::ABIEncodeWithSelector: + case FunctionType::Kind::ABIEncodeCall: case FunctionType::Kind::ABIEncodeWithSignature: visitABIFunction(_funCall); break; @@ -3041,6 +3042,7 @@ set SMTEncoder::collectABICalls(ASTNode const* _node) case FunctionType::Kind::ABIEncode: case FunctionType::Kind::ABIEncodePacked: case FunctionType::Kind::ABIEncodeWithSelector: + case FunctionType::Kind::ABIEncodeCall: case FunctionType::Kind::ABIEncodeWithSignature: case FunctionType::Kind::ABIDecode: abiCalls.insert(&_funCall); diff --git a/libsolidity/formal/SymbolicState.cpp b/libsolidity/formal/SymbolicState.cpp index e136f347db..6612723d06 100644 --- a/libsolidity/formal/SymbolicState.cpp +++ b/libsolidity/formal/SymbolicState.cpp @@ -236,6 +236,15 @@ void SymbolicState::buildABIFunctions(set const& _abiFuncti else solAssert(false, "Unexpected argument of abi.decode"); } + else if (t->kind() == FunctionType::Kind::ABIEncodeCall) + { + // abi.encodeCall : (functionPointer, tuple_of_args_or_one_non_tuple_arg(arguments)) -> bytes + solAssert(args.size() == 2, "Unexpected number of arguments for abi.encodeCall"); + + outTypes.emplace_back(TypeProvider::bytesMemory()); + inTypes.emplace_back(args.at(0)->annotation().type); + inTypes.emplace_back(args.at(1)->annotation().type); + } else { outTypes = returnTypes; diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call.sol new file mode 100644 index 0000000000..dc6ead60b2 --- /dev/null +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call.sol @@ -0,0 +1,51 @@ +pragma abicoder v2; +contract C { + type UnsignedNumber is uint256; + enum Enum { First, Second, Third } + + struct Struct { + UnsignedNumber[] dynamicArray; + uint256 justAnInt; + string name; + bytes someBytes; + Enum theEnum; + } + + function callMeMaybe(Struct calldata _data, int256 _intVal, string memory _nameVal) external pure { + assert(_data.dynamicArray.length == 3); + assert(UnsignedNumber.unwrap(_data.dynamicArray[0]) == 0); + assert(UnsignedNumber.unwrap(_data.dynamicArray[1]) == 1); + assert(UnsignedNumber.unwrap(_data.dynamicArray[2]) == 2); + assert(_data.justAnInt == 6); + assert(keccak256(bytes(_data.name)) == keccak256("StructName")); + assert(keccak256(_data.someBytes) == keccak256(bytes("1234"))); + assert(_data.theEnum == Enum.Second); + assert(_intVal == 5); + assert(keccak256(bytes(_nameVal)) == keccak256("TestName")); + } + + function callExternal() public returns (bool) { + Struct memory structToSend; + structToSend.dynamicArray = new UnsignedNumber[](3); + structToSend.dynamicArray[0] = UnsignedNumber.wrap(0); + structToSend.dynamicArray[1] = UnsignedNumber.wrap(1); + structToSend.dynamicArray[2] = UnsignedNumber.wrap(2); + structToSend.justAnInt = 6; + structToSend.name = "StructName"; + structToSend.someBytes = bytes("1234"); + structToSend.theEnum = Enum.Second; + + (bool success,) = address(this).call(abi.encodeCall(this.callMeMaybe, ( + structToSend, + 5, + "TestName" + ))); + + return success; + } +} + +// ==== +// compileViaYul: also +// ---- +// callExternal() -> true diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_is_consistent.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_is_consistent.sol new file mode 100644 index 0000000000..3c053e38a4 --- /dev/null +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_is_consistent.sol @@ -0,0 +1,63 @@ +pragma abicoder v2; + +contract C { + bool sideEffectRan = false; + + function(uint256, string memory) external fPointer; + function fExternal(uint256 p, string memory t) external {} + string xstor; + function getExternalFunctionPointer() public returns (function(uint256, string memory) external) { + sideEffectRan = true; + return this.fExternal; + } + + function fSignatureFromLiteral() public pure returns (bytes memory) { + return abi.encodeWithSignature("fExternal(uint256,string)", 1, "123"); + } + function fSignatureFromLiteralCall() public view returns (bytes memory) { + return abi.encodeCall(this.fExternal, (1, "123")); + } + function fSignatureFromMemory() public pure returns (bytes memory) { + string memory x = "fExternal(uint256,string)"; + return abi.encodeWithSignature(x, 1, "123"); + } + function fSignatureFromMemoryCall() public view returns (bytes memory) { + return abi.encodeCall(this.fExternal, (1,"123")); + } + function fSignatureFromMemorys() public returns (bytes memory) { + xstor = "fExternal(uint256,string)"; + return abi.encodeWithSignature(xstor, 1, "123"); + } + function fPointerCall() public returns(bytes memory) { + fPointer = this.fExternal; + return abi.encodeCall(fPointer, (1, "123")); + } + function fLocalPointerCall() public returns(bytes memory) { + function(uint256, string memory) external localFunctionPointer = this.fExternal; + return abi.encodeCall(localFunctionPointer, (1, "123")); + } + function fReturnedFunctionPointer() public returns (bytes memory) { + return abi.encodeCall(getExternalFunctionPointer(), (1, "123")); + } + + function assertConsistentSelectors() public { + assert(keccak256(fSignatureFromLiteral()) == keccak256(fSignatureFromLiteralCall())); + assert(keccak256(fSignatureFromMemory()) == keccak256(fSignatureFromMemoryCall())); + assert(keccak256(fSignatureFromMemoryCall()) == keccak256(fSignatureFromMemorys())); + assert(keccak256(fPointerCall()) == keccak256(fSignatureFromLiteral())); + assert(keccak256(fLocalPointerCall()) == keccak256(fSignatureFromLiteral())); + assert(keccak256(fReturnedFunctionPointer()) == keccak256(fSignatureFromLiteral())); + } +} +// ==== +// compileViaYul: also +// ---- +// assertConsistentSelectors() -> +// fSignatureFromLiteral() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0 +// fSignatureFromLiteralCall() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0 +// fSignatureFromMemory() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0 +// fSignatureFromMemoryCall() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0 +// fSignatureFromMemorys() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0 +// fPointerCall() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0 +// fLocalPointerCall() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0 +// fReturnedFunctionPointer() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0 diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_memory.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_memory.sol new file mode 100644 index 0000000000..781a6684f4 --- /dev/null +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_memory.sol @@ -0,0 +1,28 @@ +pragma abicoder v2; + +contract D { + function something() external pure {} +} + +contract C { + function something() external pure {} + function test() external returns (bytes4) { + function() external[2] memory x; + x[0] = this.something; + x[1] = (new D()).something; + function() external f = x[1]; + bytes memory a = abi.encodeCall(x[0], ()); + bytes memory b = abi.encodeCall(x[1], ()); + bytes memory c = abi.encodeCall(f, ()); + assert(a.length == 4 && b.length == 4 && c.length == 4); + assert(bytes4(a) == bytes4(b)); + assert(bytes4(a) == bytes4(c)); + assert(bytes4(a) == f.selector); + return bytes4(a); + } +} + +// ==== +// compileViaYul: also +// ---- +// test() -> 0xa7a0d53700000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_special_args.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_special_args.sol new file mode 100644 index 0000000000..24e6d065f9 --- /dev/null +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_special_args.sol @@ -0,0 +1,48 @@ +pragma abicoder v2; + +contract C { + bool sideEffectRan = false; + + function fNoArgs() external {} + function fArray(uint[] memory x) external {} + function fUint(uint x, uint y) external returns (uint a, uint b) {} + + function fSignatureFromLiteralNoArgs() public pure returns (bytes memory) { + return abi.encodeWithSignature("fNoArgs()"); + } + function fPointerNoArgs() public view returns (bytes memory) { + return abi.encodeCall(this.fNoArgs, ()); + } + + function fSignatureFromLiteralArray() public pure returns (bytes memory) { + uint[] memory x; + return abi.encodeWithSignature("fArray(uint256[])", x); + } + function fPointerArray() public view returns (bytes memory) { + uint[] memory x; + return abi.encodeCall(this.fArray, x); + } + + function fSignatureFromLiteralUint() public pure returns (bytes memory) { + return abi.encodeWithSignature("fUint(uint256,uint256)", 12, 13); + } + function fPointerUint() public view returns (bytes memory) { + return abi.encodeCall(this.fUint, (12,13)); + } + + function assertConsistentSelectors() public view { + assert(keccak256(fSignatureFromLiteralNoArgs()) == keccak256(fPointerNoArgs())); + assert(keccak256(fSignatureFromLiteralArray()) == keccak256(fPointerArray())); + assert(keccak256(fSignatureFromLiteralUint()) == keccak256(fPointerUint())); + } +} +// ==== +// compileViaYul: also +// ---- +// assertConsistentSelectors() -> +// fSignatureFromLiteralNoArgs() -> 0x20, 0x04, 12200448252684243758085936796735499259670113115893304444050964496075123064832 +// fPointerNoArgs() -> 0x20, 4, 12200448252684243758085936796735499259670113115893304444050964496075123064832 +// fSignatureFromLiteralArray() -> 0x20, 0x44, 4612216551196396486909126966576324289294165774260092952932219511233230929920, 862718293348820473429344482784628181556388621521298319395315527974912, 0 +// fPointerArray() -> 0x20, 0x44, 4612216551196396486909126966576324289294165774260092952932219511233230929920, 862718293348820473429344482784628181556388621521298319395315527974912, 0 +// fPointerUint() -> 0x20, 0x44, 30372892641494467502622535050667754357470287521126424526399600764424271429632, 323519360005807677536004181044235568083645733070486869773243322990592, 350479306672958317330671196131255198757282877493027442254346933239808 +// fSignatureFromLiteralUint() -> 0x20, 0x44, 30372892641494467502622535050667754357470287521126424526399600764424271429632, 323519360005807677536004181044235568083645733070486869773243322990592, 350479306672958317330671196131255198757282877493027442254346933239808 diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol index f6333a9476..1968a76a83 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol @@ -26,7 +26,6 @@ contract C { } struct S { uint a; string b; uint16 c; } function f4() public pure returns (bytes memory) { - bytes4 x = 0x12345678; S memory s; s.a = 0x1234567; s.b = "Lorem ipsum dolor sit ethereum........"; diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_call_simple.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_call_simple.sol new file mode 100644 index 0000000000..72fd4290c3 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_call_simple.sol @@ -0,0 +1,26 @@ +contract C { + function callMeMaybe(uint a, uint b, uint[] memory c) external {} + + function abiEncodeSimple(uint x, uint y, uint z, uint[] memory a, uint[] memory b) public view { + require(x == y); + bytes memory b1 = abi.encodeCall(this.callMeMaybe, (x, z, a)); + bytes memory b2 = abi.encodeCall(this.callMeMaybe, (y, z, a)); + assert(b1.length == b2.length); + + bytes memory b3 = abi.encodeCall(this.callMeMaybe, (y, z, b)); + assert(b1.length == b3.length); // should fail + } +} +// ==== +// SMTEngine: all +// SMTIgnoreCex: yes +// ---- +// Warning 6031: (233-249): Internal error: Expression undefined for SMT solver. +// Warning 6031: (298-314): Internal error: Expression undefined for SMT solver. +// Warning 6031: (398-414): Internal error: Expression undefined for SMT solver. +// Warning 1218: (330-360): CHC: Error trying to invoke SMT solver. +// Warning 1218: (430-460): CHC: Error trying to invoke SMT solver. +// Warning 6328: (330-360): CHC: Assertion violation might happen here. +// Warning 6328: (430-460): CHC: Assertion violation might happen here. +// Warning 4661: (330-360): BMC: Assertion violation happens here. +// Warning 4661: (430-460): BMC: Assertion violation happens here. diff --git a/test/libsolidity/syntaxTests/specialFunctions/encodeCall.sol b/test/libsolidity/syntaxTests/specialFunctions/encodeCall.sol new file mode 100644 index 0000000000..41b8f16ccb --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/encodeCall.sol @@ -0,0 +1,82 @@ +interface I { + function fExternal(uint256 p, string memory t) external; +} + +library L { + function fExternal(uint256 p, string memory t) external {} +} + +contract C { + using L for uint256; + + function f(int a) public {} + function f2(int a, string memory b) public {} + function f3(int a, int b) public {} + function f4() public {} + function fInternal(uint256 p, string memory t) internal {} + + function failFunctionArgsWrongType() public returns(bytes memory) { + return abi.encodeCall(this.f, ("test")); + } + function failFunctionArgsTooMany() public returns(bytes memory) { + return abi.encodeCall(this.f, (1, 2)); + } + function failFunctionArgsTooFew0() public returns(bytes memory) { + return abi.encodeCall(this.f, ()); + } + function failFunctionArgsTooFew1() public returns(bytes memory) { + return abi.encodeCall(this.f); + } + function failFunctionPtrMissing() public returns(bytes memory) { + return abi.encodeCall(1, this.f); + } + function failFunctionPtrWrongType() public returns(bytes memory) { + return abi.encodeCall(abi.encodeCall, (1, 2, 3, "test")); + } + function failFunctionInternal() public returns(bytes memory) { + return abi.encodeCall(fInternal, (1, "123")); + } + function failFunctionInternalFromVariable() public returns(bytes memory) { + function(uint256, string memory) internal localFunctionPointer = fInternal; + return abi.encodeCall(localFunctionPointer, (1, "123")); + } + function failFunctionArgsArrayLiteral() public returns(bytes memory) { + return abi.encodeCall(this.f3, [1, 2]); + } + function failLibraryPointerCall() public returns (bytes memory) { + return abi.encodeCall(L.fExternal, (1, "123")); + } + function failBoundLibraryPointerCall() public returns (bytes memory) { + uint256 x = 1; + return abi.encodeCall(x.fExternal, (1, "123")); + } + function failInterfacePointerCall() public returns (bytes memory) { + return abi.encodeCall(I.fExternal, (1, "123")); + } + function successFunctionArgsIntLiteralTuple() public returns(bytes memory) { + return abi.encodeCall(this.f, (1)); + } + function successFunctionArgsIntLiteral() public returns(bytes memory) { + return abi.encodeCall(this.f, 1); + } + function successFunctionArgsLiteralTuple() public returns(bytes memory) { + return abi.encodeCall(this.f2, (1, "test")); + } + function successFunctionArgsEmptyTuple() public returns(bytes memory) { + return abi.encodeCall(this.f4, ()); + } +} +// ---- +// TypeError 5407: (486-494): Cannot implicitly convert component at position 0 from "literal_string "test"" to "int256". +// TypeError 7788: (576-606): Expected 1 instead of 2 components for the tuple parameter. +// TypeError 7788: (687-713): Expected 1 instead of 0 components for the tuple parameter. +// TypeError 6219: (794-816): Expected two arguments: a function pointer followed by a tuple. +// TypeError 5511: (911-912): Expected first argument to be a function pointer, not "int_const 1". +// TypeError 3509: (1018-1032): Function must be "public" or "external". +// TypeError 3509: (1145-1154): Function must be "public" or "external". Did you forget to prefix "this."? +// TypeError 3509: (1350-1370): Function must be "public" or "external". +// TypeError 7515: (1469-1500): Expected a tuple with 2 components instead of a single non-tuple parameter. +// TypeError 5407: (1493-1499): Cannot implicitly convert component at position 0 from "uint8[2]" to "int256". +// TypeError 3509: (1596-1607): Function must be "public" or "external". +// TypeError 3509: (1738-1749): Function must be "public" or "external". +// TypeError 3509: (1860-1871): Function must be "public" or "external". diff --git a/test/libsolidity/syntaxTests/specialFunctions/encodeCall_nested_tuple.sol b/test/libsolidity/syntaxTests/specialFunctions/encodeCall_nested_tuple.sol new file mode 100644 index 0000000000..c27f61d687 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/encodeCall_nested_tuple.sol @@ -0,0 +1,9 @@ +contract C { + function f(int a, int b) public {} + function failFunctionArgsIntLiteralNestedTuple() public returns(bytes memory) { + return abi.encodeCall(this.f, ((1,2))); + } +} +// ---- +// TypeError 7788: (139-170): Expected 2 instead of 1 components for the tuple parameter. +// TypeError 5407: (163-168): Cannot implicitly convert component at position 0 from "tuple(int_const 1,int_const 2)" to "int256". diff --git a/test/libsolidity/syntaxTests/specialFunctions/encodeCall_tuple_incomplete.sol b/test/libsolidity/syntaxTests/specialFunctions/encodeCall_tuple_incomplete.sol new file mode 100644 index 0000000000..7f69995d5e --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/encodeCall_tuple_incomplete.sol @@ -0,0 +1,8 @@ +contract C { + function f(int a) public {} + function failFunctionArgsIntLiteralTuple() public returns(bytes memory) { + return abi.encodeCall(this.f, (1,)); + } +} +// ---- +// TypeError 8381: (149-153): Tuple component cannot be empty. From fc88226376b97a53f39a1c70956fe138f13a0a1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 16 Dec 2021 17:47:43 +0100 Subject: [PATCH 0093/1704] Move `about` field from issue templates to `config.yml` --- .github/ISSUE_TEMPLATE/bug_report.md | 1 - .github/ISSUE_TEMPLATE/config.yml | 3 +++ .github/ISSUE_TEMPLATE/documentation_issue.md | 1 - .github/ISSUE_TEMPLATE/feature_request.md | 1 - 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 261f78fdc1..7be77f4226 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,5 @@ --- name: Bug Report -about: Bug reports about the Solidity Compiler. labels: ["bug :bug:"] --- diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 931bc8940e..139c117874 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,7 +2,10 @@ blank_issues_enabled: false contact_links: - name: Bug Report url: https://github.com/ethereum/solidity/issues/new?template=bug_report.md&projects=ethereum/solidity/43 + about: Bug reports about the Solidity Compiler. - name: Documentation Issue url: https://github.com/ethereum/solidity/issues/new?template=documentation_issue.md&projects=ethereum/solidity/43 + about: Solidity documentation. - name: Feature Request url: https://github.com/ethereum/solidity/issues/new?template=feature_request.md&projects=ethereum/solidity/43 + about: Solidity language or infrastructure feature requests. diff --git a/.github/ISSUE_TEMPLATE/documentation_issue.md b/.github/ISSUE_TEMPLATE/documentation_issue.md index c5873f726c..9e58b88684 100644 --- a/.github/ISSUE_TEMPLATE/documentation_issue.md +++ b/.github/ISSUE_TEMPLATE/documentation_issue.md @@ -1,6 +1,5 @@ --- name: Documentation Issue -about: Solidity documentation. labels: ["documentation :book:"] --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 7191414d43..0b5bfbd4af 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,6 +1,5 @@ --- name: Feature Request -about: Solidity language or infrastructure feature requests. labels: ["feature"] --- From 927b24df1f37cdffc794a74081cfb37d01d47c17 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Mon, 13 Dec 2021 14:53:40 +0100 Subject: [PATCH 0094/1704] Initial implementation of Language Server --- .circleci/config.yml | 20 +- Changelog.md | 1 + libsolidity/CMakeLists.txt | 6 + libsolidity/lsp/FileRepository.cpp | 64 ++ libsolidity/lsp/FileRepository.h | 53 ++ libsolidity/lsp/LanguageServer.cpp | 402 ++++++++ libsolidity/lsp/LanguageServer.h | 110 +++ libsolidity/lsp/Transport.cpp | 141 +++ libsolidity/lsp/Transport.h | 101 ++ scripts/tests.sh | 3 + solc/CommandLineInterface.cpp | 19 +- solc/CommandLineInterface.h | 1 + solc/CommandLineParser.cpp | 14 + solc/CommandLineParser.h | 1 + test/libsolidity/lsp/didChange_template.sol | 6 + test/libsolidity/lsp/didOpen_with_import.sol | 12 + test/libsolidity/lsp/lib.sol | 15 + .../libsolidity/lsp/publish_diagnostics_1.sol | 18 + .../libsolidity/lsp/publish_diagnostics_2.sol | 21 + .../libsolidity/lsp/publish_diagnostics_3.sol | 10 + test/lsp.py | 874 ++++++++++++++++++ test/solc/CommandLineInterface.cpp | 2 +- 22 files changed, 1891 insertions(+), 3 deletions(-) create mode 100644 libsolidity/lsp/FileRepository.cpp create mode 100644 libsolidity/lsp/FileRepository.h create mode 100644 libsolidity/lsp/LanguageServer.cpp create mode 100644 libsolidity/lsp/LanguageServer.h create mode 100644 libsolidity/lsp/Transport.cpp create mode 100644 libsolidity/lsp/Transport.h create mode 100644 test/libsolidity/lsp/didChange_template.sol create mode 100644 test/libsolidity/lsp/didOpen_with_import.sol create mode 100644 test/libsolidity/lsp/lib.sol create mode 100644 test/libsolidity/lsp/publish_diagnostics_1.sol create mode 100644 test/libsolidity/lsp/publish_diagnostics_2.sol create mode 100644 test/libsolidity/lsp/publish_diagnostics_3.sol create mode 100755 test/lsp.py diff --git a/.circleci/config.yml b/.circleci/config.yml index cda6e58909..8123fefe84 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -198,6 +198,19 @@ defaults: - store_artifacts: *artifacts_test_results - gitter_notify_failure_unless_pr + - steps_test_lsp: &steps_test_lsp + steps: + - checkout + - attach_workspace: + at: build + - run: + name: Install dependencies + command: pip install --user deepdiff colorama + - run: + name: Executing solc LSP test suite + command: ./test/lsp.py ./build/solc/solc + - gitter_notify_failure_unless_pr + - steps_soltest_all: &steps_soltest_all steps: - checkout @@ -519,7 +532,7 @@ jobs: command: apt -q update && apt install -y python3-pip - run: name: Install pylint - command: python3 -m pip install pylint z3-solver pygments-lexer-solidity parsec tabulate + command: python3 -m pip install pylint z3-solver pygments-lexer-solidity parsec tabulate deepdiff colorama # also z3-solver, parsec and tabulate to make sure pylint knows about this module, pygments-lexer-solidity for docs - run: name: Linting Python Scripts @@ -887,6 +900,10 @@ jobs: parallelism: 15 # 7 EVM versions, each with/without optimization + 1 ABIv1/@nooptions run <<: *steps_soltest_all + t_ubu_lsp: &t_ubu_lsp + <<: *base_ubuntu2004_small + <<: *steps_test_lsp + t_archlinux_soltest: &t_archlinux_soltest <<: *base_archlinux environment: @@ -1288,6 +1305,7 @@ workflows: - t_ubu_soltest_enforce_yul: *workflow_ubuntu2004 - b_ubu_clang: *workflow_trigger_on_tags - t_ubu_clang_soltest: *workflow_ubuntu2004_clang + - t_ubu_lsp: *workflow_ubuntu2004 # Ubuntu fake release build and tests - b_ubu_release: *workflow_trigger_on_tags diff --git a/Changelog.md b/Changelog.md index c4b67e935b..9e3526fab8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * Commandline Interface: Add ``--lsp`` option to get ``solc`` to act as a Language Server (LSP) communicating over stdio. Bugfixes: diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 7e3791eab0..ff82cd9fb5 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -155,6 +155,12 @@ set(sources interface/StorageLayout.h interface/Version.cpp interface/Version.h + lsp/LanguageServer.cpp + lsp/LanguageServer.h + lsp/FileRepository.cpp + lsp/FileRepository.h + lsp/Transport.cpp + lsp/Transport.h parsing/DocStringParser.cpp parsing/DocStringParser.h parsing/Parser.cpp diff --git a/libsolidity/lsp/FileRepository.cpp b/libsolidity/lsp/FileRepository.cpp new file mode 100644 index 0000000000..9c7f72e0c4 --- /dev/null +++ b/libsolidity/lsp/FileRepository.cpp @@ -0,0 +1,64 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#include + +using namespace std; +using namespace solidity; +using namespace solidity::lsp; + +namespace +{ + +string stripFilePrefix(string const& _path) +{ + if (_path.find("file://") == 0) + return _path.substr(7); + else + return _path; +} + +} + +string FileRepository::sourceUnitNameToClientPath(string const& _sourceUnitName) const +{ + if (m_sourceUnitNamesToClientPaths.count(_sourceUnitName)) + return m_sourceUnitNamesToClientPaths.at(_sourceUnitName); + else if (_sourceUnitName.find("file://") == 0) + return _sourceUnitName; + else + return "file://" + (m_fileReader.basePath() / _sourceUnitName).generic_string(); +} + +string FileRepository::clientPathToSourceUnitName(string const& _path) const +{ + return m_fileReader.cliPathToSourceUnitName(stripFilePrefix(_path)); +} + +map const& FileRepository::sourceUnits() const +{ + return m_fileReader.sourceUnits(); +} + +void FileRepository::setSourceByClientPath(string const& _uri, string _text) +{ + // This is needed for uris outside the base path. It can lead to collisions, + // but we need to mostly rewrite this in a future version anyway. + m_sourceUnitNamesToClientPaths.emplace(clientPathToSourceUnitName(_uri), _uri); + m_fileReader.addOrUpdateFile(stripFilePrefix(_uri), move(_text)); +} diff --git a/libsolidity/lsp/FileRepository.h b/libsolidity/lsp/FileRepository.h new file mode 100644 index 0000000000..b6aa5ee085 --- /dev/null +++ b/libsolidity/lsp/FileRepository.h @@ -0,0 +1,53 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +#pragma once + +#include + +#include +#include + +namespace solidity::lsp +{ + +class FileRepository +{ +public: + explicit FileRepository(boost::filesystem::path const& _basePath): + m_fileReader(_basePath) {} + + boost::filesystem::path const& basePath() const { return m_fileReader.basePath(); } + + /// Translates a compiler-internal source unit name to an LSP client path. + std::string sourceUnitNameToClientPath(std::string const& _sourceUnitName) const; + /// Translates an LSP client path into a compiler-internal source unit name. + std::string clientPathToSourceUnitName(std::string const& _uri) const; + + /// @returns all sources by their compiler-internal source unit name. + std::map const& sourceUnits() const; + /// Changes the source identified by the LSP client path _uri to _text. + void setSourceByClientPath(std::string const& _uri, std::string _text); + + frontend::ReadCallback::Callback reader() { return m_fileReader.reader(); } + +private: + std::map m_sourceUnitNamesToClientPaths; + frontend::FileReader m_fileReader; +}; + +} diff --git a/libsolidity/lsp/LanguageServer.cpp b/libsolidity/lsp/LanguageServer.cpp new file mode 100644 index 0000000000..586220df11 --- /dev/null +++ b/libsolidity/lsp/LanguageServer.cpp @@ -0,0 +1,402 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +using namespace std; +using namespace std::placeholders; + +using namespace solidity::lsp; +using namespace solidity::langutil; +using namespace solidity::frontend; + +namespace +{ + +Json::Value toJson(LineColumn _pos) +{ + Json::Value json = Json::objectValue; + json["line"] = max(_pos.line, 0); + json["character"] = max(_pos.column, 0); + + return json; +} + +Json::Value toJsonRange(LineColumn const& _start, LineColumn const& _end) +{ + Json::Value json; + json["start"] = toJson(_start); + json["end"] = toJson(_end); + return json; +} + +optional parseLineColumn(Json::Value const& _lineColumn) +{ + if (_lineColumn.isObject() && _lineColumn["line"].isInt() && _lineColumn["character"].isInt()) + return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()}; + else + return nullopt; +} + +constexpr int toDiagnosticSeverity(Error::Type _errorType) +{ + // 1=Error, 2=Warning, 3=Info, 4=Hint + switch (Error::errorSeverity(_errorType)) + { + case Error::Severity::Error: return 1; + case Error::Severity::Warning: return 2; + case Error::Severity::Info: return 3; + } + solAssert(false); + return -1; +} + +} + +LanguageServer::LanguageServer(Transport& _transport): + m_client{_transport}, + m_handlers{ + {"$/cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}}, + {"cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}}, + {"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }}, + {"initialize", bind(&LanguageServer::handleInitialize, this, _1, _2)}, + {"initialized", [](auto, auto) {}}, + {"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }}, + {"textDocument/didOpen", bind(&LanguageServer::handleTextDocumentDidOpen, this, _1, _2)}, + {"textDocument/didChange", bind(&LanguageServer::handleTextDocumentDidChange, this, _1, _2)}, + {"textDocument/didClose", bind(&LanguageServer::handleTextDocumentDidClose, this, _1, _2)}, + {"workspace/didChangeConfiguration", bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _1, _2)}, + }, + m_fileRepository("/" /* basePath */), + m_compilerStack{m_fileRepository.reader()} +{ +} + +optional LanguageServer::parsePosition( + string const& _sourceUnitName, + Json::Value const& _position +) const +{ + if (!m_fileRepository.sourceUnits().count(_sourceUnitName)) + return nullopt; + + if (optional lineColumn = parseLineColumn(_position)) + if (optional const offset = CharStream::translateLineColumnToPosition( + m_fileRepository.sourceUnits().at(_sourceUnitName), + *lineColumn + )) + return SourceLocation{*offset, *offset, make_shared(_sourceUnitName)}; + return nullopt; +} + +optional LanguageServer::parseRange(string const& _sourceUnitName, Json::Value const& _range) const +{ + if (!_range.isObject()) + return nullopt; + optional start = parsePosition(_sourceUnitName, _range["start"]); + optional end = parsePosition(_sourceUnitName, _range["end"]); + if (!start || !end) + return nullopt; + solAssert(*start->sourceName == *end->sourceName); + start->end = end->end; + return start; +} + +Json::Value LanguageServer::toRange(SourceLocation const& _location) const +{ + if (!_location.hasText()) + return toJsonRange({}, {}); + + solAssert(_location.sourceName, ""); + CharStream const& stream = m_compilerStack.charStream(*_location.sourceName); + LineColumn start = stream.translatePositionToLineColumn(_location.start); + LineColumn end = stream.translatePositionToLineColumn(_location.end); + return toJsonRange(start, end); +} + +Json::Value LanguageServer::toJson(SourceLocation const& _location) const +{ + solAssert(_location.sourceName); + Json::Value item = Json::objectValue; + item["uri"] = m_fileRepository.sourceUnitNameToClientPath(*_location.sourceName); + item["range"] = toRange(_location); + return item; +} + +void LanguageServer::changeConfiguration(Json::Value const& _settings) +{ + m_settingsObject = _settings; +} + +void LanguageServer::compile() +{ + // For files that are not open, we have to take changes on disk into account, + // so we just remove all non-open files. + + FileRepository oldRepository(m_fileRepository.basePath()); + swap(oldRepository, m_fileRepository); + + for (string const& fileName: m_openFiles) + m_fileRepository.setSourceByClientPath( + fileName, + oldRepository.sourceUnits().at(oldRepository.clientPathToSourceUnitName(fileName)) + ); + + // TODO: optimize! do not recompile if nothing has changed (file(s) not flagged dirty). + + m_compilerStack.reset(false); + m_compilerStack.setSources(m_fileRepository.sourceUnits()); + m_compilerStack.compile(CompilerStack::State::AnalysisPerformed); +} + +void LanguageServer::compileAndUpdateDiagnostics() +{ + compile(); + + // These are the source units we will sent diagnostics to the client for sure, + // even if it is just to clear previous diagnostics. + map diagnosticsBySourceUnit; + for (string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys) + diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; + for (string const& sourceUnitName: m_nonemptyDiagnostics) + diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; + + for (shared_ptr const& error: m_compilerStack.errors()) + { + SourceLocation const* location = error->sourceLocation(); + if (!location || !location->sourceName) + // LSP only has diagnostics applied to individual files. + continue; + + Json::Value jsonDiag; + jsonDiag["source"] = "solc"; + jsonDiag["severity"] = toDiagnosticSeverity(error->type()); + jsonDiag["code"] = Json::UInt64{error->errorId().error}; + string message = error->typeName() + ":"; + if (string const* comment = error->comment()) + message += " " + *comment; + jsonDiag["message"] = move(message); + jsonDiag["range"] = toRange(*location); + + if (auto const* secondary = error->secondarySourceLocation()) + for (auto&& [secondaryMessage, secondaryLocation]: secondary->infos) + { + Json::Value jsonRelated; + jsonRelated["message"] = secondaryMessage; + jsonRelated["location"] = toJson(secondaryLocation); + jsonDiag["relatedInformation"].append(jsonRelated); + } + + diagnosticsBySourceUnit[*location->sourceName].append(jsonDiag); + } + + m_nonemptyDiagnostics.clear(); + for (auto&& [sourceUnitName, diagnostics]: diagnosticsBySourceUnit) + { + Json::Value params; + params["uri"] = m_fileRepository.sourceUnitNameToClientPath(sourceUnitName); + if (!diagnostics.empty()) + m_nonemptyDiagnostics.insert(sourceUnitName); + params["diagnostics"] = move(diagnostics); + m_client.notify("textDocument/publishDiagnostics", move(params)); + } +} + +bool LanguageServer::run() +{ + while (m_state != State::ExitRequested && m_state != State::ExitWithoutShutdown && !m_client.closed()) + { + MessageID id; + try + { + optional const jsonMessage = m_client.receive(); + if (!jsonMessage) + continue; + + if ((*jsonMessage)["method"].isString()) + { + string const methodName = (*jsonMessage)["method"].asString(); + id = (*jsonMessage)["id"]; + + if (auto handler = valueOrDefault(m_handlers, methodName)) + handler(id, (*jsonMessage)["params"]); + else + m_client.error(id, ErrorCode::MethodNotFound, "Unknown method " + methodName); + } + else + m_client.error({}, ErrorCode::ParseError, "\"method\" has to be a string."); + } + catch (...) + { + m_client.error(id, ErrorCode::InternalError, "Unhandled exception: "s + boost::current_exception_diagnostic_information()); + } + } + return m_state == State::ExitRequested; +} + +bool LanguageServer::checkServerInitialized(MessageID _id) +{ + if (m_state != State::Initialized) + { + m_client.error(_id, ErrorCode::ServerNotInitialized, "Server is not properly initialized."); + return false; + } + else + return true; +} + +void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) +{ + if (m_state != State::Started) + { + m_client.error(_id, ErrorCode::RequestFailed, "Initialize called at the wrong time."); + return; + } + m_state = State::Initialized; + + // The default of FileReader is to use `.`, but the path from where the LSP was started + // should not matter. + string rootPath("/"); + if (Json::Value uri = _args["rootUri"]) + { + rootPath = uri.asString(); + if (!boost::starts_with(rootPath, "file://")) + { + m_client.error(_id, ErrorCode::InvalidParams, "rootUri only supports file URI scheme."); + return; + } + rootPath = rootPath.substr(7); + } + else if (Json::Value rootPath = _args["rootPath"]) + rootPath = rootPath.asString(); + + m_fileRepository = FileRepository(boost::filesystem::path(rootPath)); + if (_args["initializationOptions"].isObject()) + changeConfiguration(_args["initializationOptions"]); + + Json::Value replyArgs; + replyArgs["serverInfo"]["name"] = "solc"; + replyArgs["serverInfo"]["version"] = string(VersionNumber); + replyArgs["capabilities"]["textDocumentSync"]["openClose"] = true; + replyArgs["capabilities"]["textDocumentSync"]["change"] = 2; // 0=none, 1=full, 2=incremental + + m_client.reply(_id, move(replyArgs)); +} + + +void LanguageServer::handleWorkspaceDidChangeConfiguration(MessageID _id, Json::Value const& _args) +{ + if (!checkServerInitialized(_id)) + return; + + if (_args["settings"].isObject()) + changeConfiguration(_args["settings"]); +} + +void LanguageServer::handleTextDocumentDidOpen(MessageID _id, Json::Value const& _args) +{ + if (!checkServerInitialized(_id)) + return; + + if (!_args["textDocument"]) + m_client.error(_id, ErrorCode::RequestFailed, "Text document parameter missing."); + + string text = _args["textDocument"]["text"].asString(); + string uri = _args["textDocument"]["uri"].asString(); + m_openFiles.insert(uri); + m_fileRepository.setSourceByClientPath(uri, move(text)); + compileAndUpdateDiagnostics(); +} + +void LanguageServer::handleTextDocumentDidChange(MessageID _id, Json::Value const& _args) +{ + if (!checkServerInitialized(_id)) + return; + + string const uri = _args["textDocument"]["uri"].asString(); + + for (Json::Value jsonContentChange: _args["contentChanges"]) + { + if (!jsonContentChange.isObject()) + { + m_client.error(_id, ErrorCode::RequestFailed, "Invalid content reference."); + return; + } + + string const sourceUnitName = m_fileRepository.clientPathToSourceUnitName(uri); + if (!m_fileRepository.sourceUnits().count(sourceUnitName)) + { + m_client.error(_id, ErrorCode::RequestFailed, "Unknown file: " + uri); + return; + } + + string text = jsonContentChange["text"].asString(); + if (jsonContentChange["range"].isObject()) // otherwise full content update + { + optional change = parseRange(sourceUnitName, jsonContentChange["range"]); + if (!change || !change->hasText()) + { + m_client.error( + _id, + ErrorCode::RequestFailed, + "Invalid source range: " + jsonCompactPrint(jsonContentChange["range"]) + ); + return; + } + string buffer = m_fileRepository.sourceUnits().at(sourceUnitName); + buffer.replace(static_cast(change->start), static_cast(change->end - change->start), move(text)); + text = move(buffer); + } + m_fileRepository.setSourceByClientPath(uri, move(text)); + } + + compileAndUpdateDiagnostics(); +} + +void LanguageServer::handleTextDocumentDidClose(MessageID _id, Json::Value const& _args) +{ + if (!checkServerInitialized(_id)) + return; + + if (!_args["textDocument"]) + m_client.error(_id, ErrorCode::RequestFailed, "Text document parameter missing."); + + string uri = _args["textDocument"]["uri"].asString(); + m_openFiles.erase(uri); + + compileAndUpdateDiagnostics(); +} diff --git a/libsolidity/lsp/LanguageServer.h b/libsolidity/lsp/LanguageServer.h new file mode 100644 index 0000000000..802dd81989 --- /dev/null +++ b/libsolidity/lsp/LanguageServer.h @@ -0,0 +1,110 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace solidity::lsp +{ + +enum class ErrorCode; + +/** + * Solidity Language Server, managing one LSP client. + * This implements a subset of LSP version 3.16 that can be found at: + * https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/ + */ +class LanguageServer +{ +public: + /// @param _transport Customizable transport layer. + explicit LanguageServer(Transport& _transport); + + /// Re-compiles the project and updates the diagnostics pushed to the client. + void compileAndUpdateDiagnostics(); + + /// Loops over incoming messages via the transport layer until shutdown condition is met. + /// + /// The standard shutdown condition is when the maximum number of consecutive failures + /// has been exceeded. + /// + /// @return boolean indicating normal or abnormal termination. + bool run(); + +private: + /// Checks if the server is initialized (to be used by messages that need it to be initialized). + /// Reports an error and returns false if not. + bool checkServerInitialized(MessageID _id); + void handleInitialize(MessageID _id, Json::Value const& _args); + void handleWorkspaceDidChangeConfiguration(MessageID _id, Json::Value const& _args); + void handleTextDocumentDidOpen(MessageID _id, Json::Value const& _args); + void handleTextDocumentDidChange(MessageID _id, Json::Value const& _args); + void handleTextDocumentDidClose(MessageID _id, Json::Value const& _args); + + /// Invoked when the server user-supplied configuration changes (initiated by the client). + void changeConfiguration(Json::Value const&); + + /// Compile everything until after analysis phase. + void compile(); + + std::optional parsePosition( + std::string const& _sourceUnitName, + Json::Value const& _position + ) const; + /// @returns the source location given a source unit name and an LSP Range object, + /// or nullopt on failure. + std::optional parseRange( + std::string const& _sourceUnitName, + Json::Value const& _range + ) const; + Json::Value toRange(langutil::SourceLocation const& _location) const; + Json::Value toJson(langutil::SourceLocation const& _location) const; + + // LSP related member fields + using MessageHandler = std::function; + + enum class State { Started, Initialized, ShutdownRequested, ExitRequested, ExitWithoutShutdown }; + State m_state = State::Started; + + Transport& m_client; + std::map m_handlers; + + /// Set of files known to be open by the client. + std::set m_openFiles; + /// Set of source unit names for which we sent diagnostics to the client in the last iteration. + std::set m_nonemptyDiagnostics; + FileRepository m_fileRepository; + + frontend::CompilerStack m_compilerStack; + + /// User-supplied custom configuration settings (such as EVM version). + Json::Value m_settingsObject; +}; + +} diff --git a/libsolidity/lsp/Transport.cpp b/libsolidity/lsp/Transport.cpp new file mode 100644 index 0000000000..fcd3c82492 --- /dev/null +++ b/libsolidity/lsp/Transport.cpp @@ -0,0 +1,141 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +#include + +#include +#include +#include +#include + +#include + +#include +#include + +using namespace std; +using namespace solidity::lsp; + +IOStreamTransport::IOStreamTransport(istream& _in, ostream& _out): + m_input{_in}, + m_output{_out} +{ +} + +IOStreamTransport::IOStreamTransport(): + IOStreamTransport(cin, cout) +{ +} + +bool IOStreamTransport::closed() const noexcept +{ + return m_input.eof(); +} + +optional IOStreamTransport::receive() +{ + auto const headers = parseHeaders(); + if (!headers) + { + error({}, ErrorCode::ParseError, "Could not parse RPC headers."); + return nullopt; + } + + if (!headers->count("content-length")) + { + error({}, ErrorCode::ParseError, "No content-length header found."); + return nullopt; + } + + string const data = util::readBytes(m_input, stoul(headers->at("content-length"))); + + Json::Value jsonMessage; + string jsonParsingErrors; + solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors); + if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject()) + { + error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors); + return nullopt; + } + + return {move(jsonMessage)}; +} + +void IOStreamTransport::notify(string _method, Json::Value _message) +{ + Json::Value json; + json["method"] = move(_method); + json["params"] = move(_message); + send(move(json)); +} + +void IOStreamTransport::reply(MessageID _id, Json::Value _message) +{ + Json::Value json; + json["result"] = move(_message); + send(move(json), _id); +} + +void IOStreamTransport::error(MessageID _id, ErrorCode _code, string _message) +{ + Json::Value json; + json["error"]["code"] = static_cast(_code); + json["error"]["message"] = move(_message); + send(move(json), _id); +} + +void IOStreamTransport::send(Json::Value _json, MessageID _id) +{ + solAssert(_json.isObject()); + _json["jsonrpc"] = "2.0"; + if (_id != Json::nullValue) + _json["id"] = _id; + + string const jsonString = solidity::util::jsonCompactPrint(_json); + + m_output << "Content-Length: " << jsonString.size() << "\r\n"; + m_output << "\r\n"; + m_output << jsonString; + + m_output.flush(); +} + +optional> IOStreamTransport::parseHeaders() +{ + map headers; + + while (true) + { + string line; + getline(m_input, line); + if (boost::trim_copy(line).empty()) + break; + + auto const delimiterPos = line.find(':'); + if (delimiterPos == string::npos) + return nullopt; + + string name = boost::to_lower_copy(line.substr(0, delimiterPos)); + string value = line.substr(delimiterPos + 1); + if (!headers.emplace( + boost::trim_copy(name), + boost::trim_copy(value) + ).second) + return nullopt; + } + return {move(headers)}; +} diff --git a/libsolidity/lsp/Transport.h b/libsolidity/lsp/Transport.h new file mode 100644 index 0000000000..c6ed8fa8a2 --- /dev/null +++ b/libsolidity/lsp/Transport.h @@ -0,0 +1,101 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace solidity::lsp +{ + +using MessageID = Json::Value; + +enum class ErrorCode +{ + // Defined by JSON RPC + ParseError = -32700, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603, + + // Defined by the protocol. + ServerNotInitialized = -32002, + RequestFailed = -32803 +}; + +/** + * Transport layer API + * + * The transport layer API is abstracted to make LSP more testable as well as + * this way it could be possible to support other transports (HTTP for example) easily. + */ +class Transport +{ +public: + virtual ~Transport() = default; + + virtual bool closed() const noexcept = 0; + virtual std::optional receive() = 0; + virtual void notify(std::string _method, Json::Value _params) = 0; + virtual void reply(MessageID _id, Json::Value _result) = 0; + virtual void error(MessageID _id, ErrorCode _code, std::string _message) = 0; +}; + +/** + * LSP Transport using JSON-RPC over iostreams. + */ +class IOStreamTransport: public Transport +{ +public: + /// Constructs a standard stream transport layer. + /// + /// @param _in for example std::cin (stdin) + /// @param _out for example std::cout (stdout) + IOStreamTransport(std::istream& _in, std::ostream& _out); + + // Constructs a JSON transport using standard I/O streams. + IOStreamTransport(); + + bool closed() const noexcept override; + std::optional receive() override; + void notify(std::string _method, Json::Value _params) override; + void reply(MessageID _id, Json::Value _result) override; + void error(MessageID _id, ErrorCode _code, std::string _message) override; + +protected: + /// Sends an arbitrary raw message to the client. + /// + /// Used by the notify/reply/error function family. + virtual void send(Json::Value _message, MessageID _id = Json::nullValue); + + /// Parses header section from the client including message-delimiting empty line. + std::optional> parseHeaders(); + +private: + std::istream& m_input; + std::ostream& m_output; +}; + +} diff --git a/scripts/tests.sh b/scripts/tests.sh index 029be16291..5515a68691 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -83,6 +83,9 @@ done printTask "Testing Python scripts..." "$REPO_ROOT/test/pyscriptTests.py" +printTask "Testing LSP..." +"$REPO_ROOT/scripts/test_solidity_lsp.py" "${SOLIDITY_BUILD_DIR}/solc/solc" + printTask "Running commandline tests..." # Only run in parallel if this is run on CI infrastructure if [[ -n "$CI" ]] diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 94bfd8a68b..235059a02b 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include @@ -56,6 +58,7 @@ #include #include +#include #include #include @@ -499,7 +502,11 @@ void CommandLineInterface::readInputFiles() m_fileReader.setStdin(readUntilEnd(m_sin)); } - if (m_fileReader.sourceUnits().empty() && !m_standardJsonInput.has_value()) + if ( + m_options.input.mode != InputMode::LanguageServer && + m_fileReader.sourceUnits().empty() && + !m_standardJsonInput.has_value() + ) solThrow(CommandLineValidationError, "All specified input files either do not exist or are not regular files."); } @@ -624,6 +631,9 @@ void CommandLineInterface::processInput() m_standardJsonInput.reset(); break; } + case InputMode::LanguageServer: + serveLSP(); + break; case InputMode::Assembler: assemble(m_options.assembly.inputLanguage, m_options.assembly.targetMachine); break; @@ -884,6 +894,13 @@ void CommandLineInterface::handleAst() } } +void CommandLineInterface::serveLSP() +{ + lsp::IOStreamTransport transport; + if (!lsp::LanguageServer{transport}.run()) + solThrow(CommandLineExecutionError, "LSP terminated abnormally."); +} + void CommandLineInterface::link() { solAssert(m_options.input.mode == InputMode::Linker, ""); diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 9d1646e528..951731825c 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -82,6 +82,7 @@ class CommandLineInterface void printVersion(); void printLicense(); void compile(); + void serveLSP(); void link(); void writeLinkedFiles(); /// @returns the ``// -> name`` hint for library placeholders. diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 87348686c6..65c7d78621 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -59,6 +59,7 @@ static string const g_strIPFS = "ipfs"; static string const g_strLicense = "license"; static string const g_strLibraries = "libraries"; static string const g_strLink = "link"; +static string const g_strLSP = "lsp"; static string const g_strMachine = "machine"; static string const g_strMetadataHash = "metadata-hash"; static string const g_strMetadataLiteral = "metadata-literal"; @@ -135,6 +136,7 @@ static map const g_inputModeName = { {InputMode::Assembler, "assembler"}, {InputMode::StandardJson, "standard JSON"}, {InputMode::Linker, "linker"}, + {InputMode::LanguageServer, "language server (LSP)"}, }; void CommandLineParser::checkMutuallyExclusive(vector const& _optionNames) @@ -455,6 +457,7 @@ void CommandLineParser::parseOutputSelection() case InputMode::Help: case InputMode::License: case InputMode::Version: + case InputMode::LanguageServer: solAssert(false); case InputMode::Compiler: case InputMode::CompilerWithASTImport: @@ -633,6 +636,11 @@ General Information)").c_str(), "Supported Inputs is the output of the --" + g_strStandardJSON + " or the one produced by " "--" + g_strCombinedJson + " " + CombinedJsonRequests::componentName(&CombinedJsonRequests::ast)).c_str() ) + ( + g_strLSP.c_str(), + "Switch to language server mode (\"LSP\"). Allows the compiler to be used as an analysis backend " + "for your favourite IDE." + ) ; desc.add(alternativeInputModes); @@ -865,6 +873,7 @@ void CommandLineParser::processArgs() g_strStrictAssembly, g_strYul, g_strImportAst, + g_strLSP }); if (m_args.count(g_strHelp) > 0) @@ -875,6 +884,8 @@ void CommandLineParser::processArgs() m_options.input.mode = InputMode::Version; else if (m_args.count(g_strStandardJSON) > 0) m_options.input.mode = InputMode::StandardJson; + else if (m_args.count(g_strLSP)) + m_options.input.mode = InputMode::LanguageServer; else if (m_args.count(g_strAssemble) > 0 || m_args.count(g_strStrictAssembly) > 0 || m_args.count(g_strYul) > 0) m_options.input.mode = InputMode::Assembler; else if (m_args.count(g_strLink) > 0) @@ -910,6 +921,9 @@ void CommandLineParser::processArgs() joinOptionNames(invalidOptionsForCurrentInputMode) ); + if (m_options.input.mode == InputMode::LanguageServer) + return; + checkMutuallyExclusive({g_strColor, g_strNoColor}); array const conflictingWithStopAfter{ diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index c1a95a11f9..791e7f1c10 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -56,6 +56,7 @@ enum class InputMode StandardJson, Linker, Assembler, + LanguageServer }; struct CompilerOutputs diff --git a/test/libsolidity/lsp/didChange_template.sol b/test/libsolidity/lsp/didChange_template.sol new file mode 100644 index 0000000000..d08ba140e5 --- /dev/null +++ b/test/libsolidity/lsp/didChange_template.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.0; + +contract C +{ +} diff --git a/test/libsolidity/lsp/didOpen_with_import.sol b/test/libsolidity/lsp/didOpen_with_import.sol new file mode 100644 index 0000000000..f505ca6e5e --- /dev/null +++ b/test/libsolidity/lsp/didOpen_with_import.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.0; + +import './lib.sol'; + +contract C +{ + function f(uint a, uint b) public pure returns (uint) + { + return Lib.add(2 * a, b); + } +} diff --git a/test/libsolidity/lsp/lib.sol b/test/libsolidity/lsp/lib.sol new file mode 100644 index 0000000000..f4fb51e77b --- /dev/null +++ b/test/libsolidity/lsp/lib.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.0; + +library Lib +{ + function add(uint a, uint b) public pure returns (uint result) + { + result = a + b; + } + + function warningWithUnused() public pure + { + uint unused; + } +} diff --git a/test/libsolidity/lsp/publish_diagnostics_1.sol b/test/libsolidity/lsp/publish_diagnostics_1.sol new file mode 100644 index 0000000000..e667185122 --- /dev/null +++ b/test/libsolidity/lsp/publish_diagnostics_1.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.0; + +contract MyContract +{ + constructor() + { + uint unused; // [Warning 2072] Unused local variable. + } +} + +contract D +{ + function main() public payable returns (uint) + { + MyContract c = new MyContract(); + } +} diff --git a/test/libsolidity/lsp/publish_diagnostics_2.sol b/test/libsolidity/lsp/publish_diagnostics_2.sol new file mode 100644 index 0000000000..9686189552 --- /dev/null +++ b/test/libsolidity/lsp/publish_diagnostics_2.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.0; + +contract C +{ + function makeSomeError() public pure returns (uint res) + { + uint x = "hi"; + return; + res = 2; + } +} + +contract D +{ + function main() public payable returns (uint) + { + C c = new C(); + return c.makeSomeError(2, 3); + } +} diff --git a/test/libsolidity/lsp/publish_diagnostics_3.sol b/test/libsolidity/lsp/publish_diagnostics_3.sol new file mode 100644 index 0000000000..bb8998a6ad --- /dev/null +++ b/test/libsolidity/lsp/publish_diagnostics_3.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.0; + +abstract contract A { + function a() public virtual; +} + +contract B is A +{ +} diff --git a/test/lsp.py b/test/lsp.py new file mode 100755 index 0000000000..d558c20d95 --- /dev/null +++ b/test/lsp.py @@ -0,0 +1,874 @@ +#!/usr/bin/env python3 + +import argparse +import fnmatch +import json +import os +import subprocess +import traceback + +from typing import Any, List, Optional, Tuple, Union + +import colorama # Enables the use of SGR & CUP terminal VT sequences on Windows. +from deepdiff import DeepDiff + +# {{{ JsonRpcProcess +class BadHeader(Exception): + def __init__(self, msg: str): + super().__init__("Bad header: " + msg) + +class JsonRpcProcess: + exe_path: str + exe_args: List[str] + process: subprocess.Popen + trace_io: bool + + def __init__(self, exe_path: str, exe_args: List[str], trace_io: bool = True): + self.exe_path = exe_path + self.exe_args = exe_args + self.trace_io = trace_io + + def __enter__(self): + self.process = subprocess.Popen( + [self.exe_path, *self.exe_args], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + return self + + def __exit__(self, exception_type, exception_value, traceback) -> None: + self.process.kill() + self.process.wait(timeout=2.0) + + def trace(self, topic: str, message: str) -> None: + if self.trace_io: + print(f"{SGR_TRACE}{topic}:{SGR_RESET} {message}") + + def receive_message(self) -> Union[None, dict]: + # Note, we should make use of timeout to avoid infinite blocking if nothing is received. + CONTENT_LENGTH_HEADER = "Content-Length: " + CONTENT_TYPE_HEADER = "Content-Type: " + if self.process.stdout == None: + return None + message_size = None + while True: + # read header + line = self.process.stdout.readline() + if line == '': + # server quit + return None + line = line.decode("utf-8") + if not line.endswith("\r\n"): + raise BadHeader("missing newline") + # remove the "\r\n" + line = line[:-2] + if line == '': + break # done with the headers + if line.startswith(CONTENT_LENGTH_HEADER): + line = line[len(CONTENT_LENGTH_HEADER):] + if not line.isdigit(): + raise BadHeader("size is not int") + message_size = int(line) + elif line.startswith(CONTENT_TYPE_HEADER): + # nothing todo with type for now. + pass + else: + raise BadHeader("unknown header") + if message_size is None: + raise BadHeader("missing size") + rpc_message = self.process.stdout.read(message_size).decode("utf-8") + json_object = json.loads(rpc_message) + self.trace('receive_message', json.dumps(json_object, indent=4, sort_keys=True)) + return json_object + + def send_message(self, method_name: str, params: Optional[dict]) -> None: + if self.process.stdin == None: + return + message = { + 'jsonrpc': '2.0', + 'method': method_name, + 'params': params + } + json_string = json.dumps(obj=message) + rpc_message = f"Content-Length: {len(json_string)}\r\n\r\n{json_string}" + self.trace(f'send_message ({method_name})', json.dumps(message, indent=4, sort_keys=True)) + self.process.stdin.write(rpc_message.encode("utf-8")) + self.process.stdin.flush() + + def call_method(self, method_name: str, params: Optional[dict]) -> Any: + self.send_message(method_name, params) + return self.receive_message() + + def send_notification(self, name: str, params: Optional[dict] = None) -> None: + self.send_message(name, params) + +# }}} + +SGR_RESET = '\033[m' +SGR_TRACE = '\033[1;36m' +SGR_NOTICE = '\033[1;35m' +SGR_TEST_BEGIN = '\033[1;33m' +SGR_ASSERT_BEGIN = '\033[1;34m' +SGR_STATUS_OKAY = '\033[1;32m' +SGR_STATUS_FAIL = '\033[1;31m' + +class ExpectationFailed(Exception): + def __init__(self, actual, expected): + self.actual = actual + self.expected = expected + diff = DeepDiff(actual, expected) + super().__init__( + f"Expectation failed.\n\tExpected {expected}\n\tbut got {actual}.\n\t{diff}" + ) + +def create_cli_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="Solidity LSP Test suite") + parser.set_defaults(trace_io=False) + parser.add_argument( + "-T, --trace-io", + dest="trace_io", + action="store_true", + help="Be more verbose by also printing assertions." + ) + parser.set_defaults(print_assertions=False) + parser.add_argument( + "-v, --print-assertions", + dest="print_assertions", + action="store_true", + help="Be more verbose by also printing assertions." + ) + parser.add_argument( + "-t, --test-pattern", + dest="test_pattern", + type=str, + default="*", + help="Filters all available tests by matching against this test pattern (using globbing)", + nargs="?" + ) + parser.add_argument( + "solc_path", + type=str, + default="solc", + help="Path to solc binary to test against", + nargs="?" + ) + parser.add_argument( + "project_root_dir", + type=str, + default=f"{os.path.dirname(os.path.realpath(__file__))}/..", + help="Path to Solidity project's root directory (must be fully qualified).", + nargs="?" + ) + return parser + +class Counter: + total: int = 0 + passed: int = 0 + failed: int = 0 + +class SolidityLSPTestSuite: # {{{ + test_counter = Counter() + assertion_counter = Counter() + print_assertions: bool = False + trace_io: bool = False + test_pattern: str + + def __init__(self): + colorama.init() + args = create_cli_parser().parse_args() + self.solc_path = args.solc_path + self.project_root_dir = os.path.realpath(args.project_root_dir) + "/test/libsolidity/lsp" + self.project_root_uri = "file://" + self.project_root_dir + self.print_assertions = args.print_assertions + self.trace_io = args.trace_io + self.test_pattern = args.test_pattern + + print(f"{SGR_NOTICE}test pattern: {self.test_pattern}{SGR_RESET}") + + def main(self) -> int: + """ + Runs all test cases. + Returns 0 on success and the number of failing assertions (capped to 127) otherwise. + """ + all_tests = sorted([ + str(name)[5:] + for name in dir(SolidityLSPTestSuite) + if callable(getattr(SolidityLSPTestSuite, name)) and name.startswith("test_") + ]) + filtered_tests = fnmatch.filter(all_tests, self.test_pattern) + for method_name in filtered_tests: + test_fn = getattr(self, 'test_' + method_name) + title: str = test_fn.__name__[5:] + print(f"{SGR_TEST_BEGIN}Testing {title} ...{SGR_RESET}") + try: + with JsonRpcProcess(self.solc_path, ["--lsp"], trace_io=self.trace_io) as solc: + test_fn(solc) + self.test_counter.passed += 1 + except ExpectationFailed as e: + self.test_counter.failed += 1 + print(e) + print(traceback.format_exc()) + except Exception as e: # pragma pylint: disable=broad-except + self.test_counter.failed += 1 + print(f"Unhandled exception {e.__class__.__name__} caught: {e}") + print(traceback.format_exc()) + + print( + f"\n{SGR_NOTICE}Summary:{SGR_RESET}\n\n" + f" Test cases: {self.test_counter.passed} passed, {self.test_counter.failed} failed\n" + f" Assertions: {self.assertion_counter.passed} passed, {self.assertion_counter.failed} failed\n" + ) + + return min(max(self.test_counter.failed, self.assertion_counter.failed), 127) + + def setup_lsp(self, lsp: JsonRpcProcess, expose_project_root=True): + """ + Prepares the solc LSP server by calling `initialize`, + and `initialized` methods. + """ + params = { + 'processId': None, + 'rootUri': self.project_root_uri, + 'trace': 'off', + 'initializationOptions': {}, + 'capabilities': { + 'textDocument': { + 'publishDiagnostics': {'relatedInformation': True} + }, + 'workspace': { + 'applyEdit': True, + 'configuration': True, + 'didChangeConfiguration': {'dynamicRegistration': True}, + 'workspaceEdit': {'documentChanges': True}, + 'workspaceFolders': True + } + } + } + if expose_project_root == False: + params['rootUri'] = None + lsp.call_method('initialize', params) + lsp.send_notification('initialized') + + # {{{ helpers + def get_test_file_path(self, test_case_name): + return f"{self.project_root_dir}/{test_case_name}.sol" + + def get_test_file_uri(self, test_case_name): + return "file://" + self.get_test_file_path(test_case_name) + + def get_test_file_contents(self, test_case_name): + """ + Reads the file contents from disc for a given test case. + The `test_case_name` will be the basename of the file + in the test path (test/libsolidity/lsp). + """ + with open(self.get_test_file_path(test_case_name), mode="r", encoding="utf-8", newline='') as f: + return f.read() + + def require_params_for_method(self, method_name: str, message: dict) -> Any: + """ + Ensures the given RPC message does contain the + field 'method' with the given method name, + and then returns its passed params. + An exception is raised on expectation failures. + """ + assert message is not None + if 'error' in message.keys(): + code = message['error']["code"] + text = message['error']['message'] + raise RuntimeError(f"Error {code} received. {text}") + if 'method' not in message.keys(): + raise RuntimeError("No method received but something else.") + self.expect_equal(message['method'], method_name, "Ensure expected method name") + return message['params'] + + def wait_for_diagnostics(self, solc: JsonRpcProcess, count: int) -> List[dict]: + """ + Return `count` number of published diagnostic reports sorted by file URI. + """ + reports = [] + for _ in range(0, count): + message = solc.receive_message() + assert message is not None # This can happen if the server aborts early. + reports.append( + self.require_params_for_method( + 'textDocument/publishDiagnostics', + message, + ) + ) + return sorted(reports, key=lambda x: x['uri']) + + def open_file_and_wait_for_diagnostics( + self, + solc_process: JsonRpcProcess, + test_case_name: str, + max_diagnostic_reports: int = 1 + ) -> List[Any]: + """ + Opens file for given test case and waits for diagnostics to be published. + """ + assert max_diagnostic_reports > 0 + solc_process.send_message( + 'textDocument/didOpen', + { + 'textDocument': + { + 'uri': self.get_test_file_uri(test_case_name), + 'languageId': 'Solidity', + 'version': 1, + 'text': self.get_test_file_contents(test_case_name) + } + } + ) + return self.wait_for_diagnostics(solc_process, max_diagnostic_reports) + + def expect_equal(self, actual, expected, description="Equality") -> None: + self.assertion_counter.total += 1 + prefix = f"[{self.assertion_counter.total}] {SGR_ASSERT_BEGIN}{description}: " + diff = DeepDiff(actual, expected) + if len(diff) == 0: + self.assertion_counter.passed += 1 + if self.print_assertions: + print(prefix + SGR_STATUS_OKAY + 'OK' + SGR_RESET) + return + + # Failed assertions are always printed. + self.assertion_counter.failed += 1 + print(prefix + SGR_STATUS_FAIL + 'FAILED' + SGR_RESET) + raise ExpectationFailed(actual, expected) + + def expect_empty_diagnostics(self, published_diagnostics: List[dict]) -> None: + self.expect_equal(len(published_diagnostics), 1, "one publish diagnostics notification") + self.expect_equal(len(published_diagnostics[0]['diagnostics']), 0, "should not contain diagnostics") + + def expect_diagnostic( + self, + diagnostic, + code: int, + lineNo: int, + startEndColumns: Tuple[int, int] + ): + assert len(startEndColumns) == 2 + [startColumn, endColumn] = startEndColumns + self.expect_equal(diagnostic['code'], code, f'diagnostic: {code}') + self.expect_equal( + diagnostic['range'], + { + 'start': {'character': startColumn, 'line': lineNo}, + 'end': {'character': endColumn, 'line': lineNo} + }, + "diagnostic: check range" + ) + # }}} + + # {{{ actual tests + def test_publish_diagnostics_warnings(self, solc: JsonRpcProcess) -> None: + self.setup_lsp(solc) + TEST_NAME = 'publish_diagnostics_1' + published_diagnostics = self.open_file_and_wait_for_diagnostics(solc, TEST_NAME) + + self.expect_equal(len(published_diagnostics), 1, "One published_diagnostics message") + report = published_diagnostics[0] + + self.expect_equal(report['uri'], self.get_test_file_uri(TEST_NAME), "Correct file URI") + diagnostics = report['diagnostics'] + + self.expect_equal(len(diagnostics), 3, "3 diagnostic messages") + self.expect_diagnostic(diagnostics[0], code=6321, lineNo=13, startEndColumns=(44, 48)) + self.expect_diagnostic(diagnostics[1], code=2072, lineNo= 7, startEndColumns=( 8, 19)) + self.expect_diagnostic(diagnostics[2], code=2072, lineNo=15, startEndColumns=( 8, 20)) + + def test_publish_diagnostics_errors(self, solc: JsonRpcProcess) -> None: + self.setup_lsp(solc) + TEST_NAME = 'publish_diagnostics_2' + published_diagnostics = self.open_file_and_wait_for_diagnostics(solc, TEST_NAME) + + self.expect_equal(len(published_diagnostics), 1, "One published_diagnostics message") + report = published_diagnostics[0] + + self.expect_equal(report['uri'], self.get_test_file_uri(TEST_NAME), "Correct file URI") + diagnostics = report['diagnostics'] + + self.expect_equal(len(diagnostics), 3, "3 diagnostic messages") + self.expect_diagnostic(diagnostics[0], code=9574, lineNo= 7, startEndColumns=( 8, 21)) + self.expect_diagnostic(diagnostics[1], code=6777, lineNo= 8, startEndColumns=( 8, 15)) + self.expect_diagnostic(diagnostics[2], code=6160, lineNo=18, startEndColumns=(15, 36)) + + def test_publish_diagnostics_errors_multiline(self, solc: JsonRpcProcess) -> None: + self.setup_lsp(solc) + TEST_NAME = 'publish_diagnostics_3' + published_diagnostics = self.open_file_and_wait_for_diagnostics(solc, TEST_NAME) + + self.expect_equal(len(published_diagnostics), 1, "One published_diagnostics message") + report = published_diagnostics[0] + + self.expect_equal(report['uri'], self.get_test_file_uri(TEST_NAME), "Correct file URI") + diagnostics = report['diagnostics'] + + self.expect_equal(len(diagnostics), 1, "3 diagnostic messages") + self.expect_equal(diagnostics[0]['code'], 3656, "diagnostic: check code") + self.expect_equal( + diagnostics[0]['range'], + { + 'end': {'character': 1, 'line': 9}, + 'start': {'character': 0, 'line': 7} + }, + "diagnostic: check range" + ) + + def test_textDocument_didOpen_with_relative_import(self, solc: JsonRpcProcess) -> None: + self.setup_lsp(solc) + TEST_NAME = 'didOpen_with_import' + published_diagnostics = self.open_file_and_wait_for_diagnostics(solc, TEST_NAME, 2) + + self.expect_equal(len(published_diagnostics), 2, "Diagnostic reports for 2 files") + + # primary file: + report = published_diagnostics[0] + self.expect_equal(report['uri'], self.get_test_file_uri(TEST_NAME), "Correct file URI") + self.expect_equal(len(report['diagnostics']), 0, "no diagnostics") + + # imported file (./lib.sol): + report = published_diagnostics[1] + self.expect_equal(report['uri'], self.get_test_file_uri('lib'), "Correct file URI") + self.expect_equal(len(report['diagnostics']), 1, "one diagnostic") + self.expect_diagnostic(report['diagnostics'][0], code=2072, lineNo=12, startEndColumns=(8, 19)) + + def test_didChange_in_A_causing_error_in_B(self, solc: JsonRpcProcess) -> None: + # Reusing another test but now change some file that generates an error in the other. + self.test_textDocument_didOpen_with_relative_import(solc) + self.open_file_and_wait_for_diagnostics(solc, 'lib', 2) + solc.send_message( + 'textDocument/didChange', + { + 'textDocument': + { + 'uri': self.get_test_file_uri('lib') + }, + 'contentChanges': + [ + { + 'range': { + 'start': { 'line': 5, 'character': 0 }, + 'end': { 'line': 10, 'character': 0 } + }, + 'text': "" # deleting function `add` + } + ] + } + ) + published_diagnostics = self.wait_for_diagnostics(solc, 2) + self.expect_equal(len(published_diagnostics), 2, "Diagnostic reports for 2 files") + + # Main file now contains a new diagnostic + report = published_diagnostics[0] + self.expect_equal(report['uri'], self.get_test_file_uri('didOpen_with_import')) + diagnostics = report['diagnostics'] + self.expect_equal(len(diagnostics), 1, "now, no diagnostics") + self.expect_diagnostic(diagnostics[0], code=9582, lineNo=9, startEndColumns=(15, 22)) + + # The modified file retains the same diagnostics. + report = published_diagnostics[1] + self.expect_equal(report['uri'], self.get_test_file_uri('lib')) + self.expect_equal(len(report['diagnostics']), 0) + # The warning went away because the compiler aborts further processing after the error. + + def test_textDocument_didOpen_with_relative_import_without_project_url(self, solc: JsonRpcProcess) -> None: + self.setup_lsp(solc, expose_project_root=False) + TEST_NAME = 'didOpen_with_import' + published_diagnostics = self.open_file_and_wait_for_diagnostics(solc, TEST_NAME, 2) + self.verify_didOpen_with_import_diagnostics(published_diagnostics) + + def verify_didOpen_with_import_diagnostics( + self, + published_diagnostics: List[Any], + main_file_name='didOpen_with_import' + ): + self.expect_equal(len(published_diagnostics), 2, "Diagnostic reports for 2 files") + + # primary file: + report = published_diagnostics[0] + self.expect_equal(report['uri'], self.get_test_file_uri(main_file_name), "Correct file URI") + self.expect_equal(len(report['diagnostics']), 0, "one diagnostic") + + # imported file (./lib.sol): + report = published_diagnostics[1] + self.expect_equal(report['uri'], self.get_test_file_uri('lib'), "Correct file URI") + self.expect_equal(len(report['diagnostics']), 1, "one diagnostic") + self.expect_diagnostic(report['diagnostics'][0], code=2072, lineNo=12, startEndColumns=(8, 19)) + + def test_textDocument_didChange_updates_diagnostics(self, solc: JsonRpcProcess) -> None: + self.setup_lsp(solc) + TEST_NAME = 'publish_diagnostics_1' + published_diagnostics = self.open_file_and_wait_for_diagnostics(solc, TEST_NAME) + self.expect_equal(len(published_diagnostics), 1, "One published_diagnostics message") + report = published_diagnostics[0] + self.expect_equal(report['uri'], self.get_test_file_uri(TEST_NAME), "Correct file URI") + diagnostics = report['diagnostics'] + self.expect_equal(len(diagnostics), 3, "3 diagnostic messages") + self.expect_diagnostic(diagnostics[0], code=6321, lineNo=13, startEndColumns=(44, 48)) + self.expect_diagnostic(diagnostics[1], code=2072, lineNo= 7, startEndColumns=( 8, 19)) + self.expect_diagnostic(diagnostics[2], code=2072, lineNo=15, startEndColumns=( 8, 20)) + + solc.send_message( + 'textDocument/didChange', + { + 'textDocument': { + 'uri': self.get_test_file_uri(TEST_NAME) + }, + 'contentChanges': [ + { + 'range': { + 'start': { 'line': 7, 'character': 1 }, + 'end': { 'line': 8, 'character': 1 } + }, + 'text': "" + } + ] + } + ) + published_diagnostics = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(published_diagnostics), 1) + report = published_diagnostics[0] + self.expect_equal(report['uri'], self.get_test_file_uri(TEST_NAME), "Correct file URI") + diagnostics = report['diagnostics'] + self.expect_equal(len(diagnostics), 2) + self.expect_diagnostic(diagnostics[0], code=6321, lineNo=12, startEndColumns=(44, 48)) + self.expect_diagnostic(diagnostics[1], code=2072, lineNo=14, startEndColumns=( 8, 20)) + + def test_textDocument_didChange_delete_line_and_close(self, solc: JsonRpcProcess) -> None: + # Reuse this test to prepare and ensure it is as expected + self.test_textDocument_didOpen_with_relative_import(solc) + self.open_file_and_wait_for_diagnostics(solc, 'lib', 2) + # lib.sol: Fix the unused variable message by removing it. + solc.send_message( + 'textDocument/didChange', + { + 'textDocument': + { + 'uri': self.get_test_file_uri('lib') + }, + 'contentChanges': # delete the in-body statement: `uint unused;` + [ + { + 'range': + { + 'start': { 'line': 12, 'character': 1 }, + 'end': { 'line': 13, 'character': 1 } + }, + 'text': "" + } + ] + } + ) + published_diagnostics = self.wait_for_diagnostics(solc, 2) + self.expect_equal(len(published_diagnostics), 2, "published diagnostics count") + report1 = published_diagnostics[0] + self.expect_equal(report1['uri'], self.get_test_file_uri('didOpen_with_import'), "Correct file URI") + self.expect_equal(len(report1['diagnostics']), 0, "no diagnostics in didOpen_with_import.sol") + report2 = published_diagnostics[1] + self.expect_equal(report2['uri'], self.get_test_file_uri('lib'), "Correct file URI") + self.expect_equal(len(report2['diagnostics']), 0, "no diagnostics in lib.sol") + + # Now close the file and expect the warning to re-appear + solc.send_message( + 'textDocument/didClose', + { 'textDocument': { 'uri': self.get_test_file_uri('lib') }} + ) + + published_diagnostics = self.wait_for_diagnostics(solc, 2) + self.verify_didOpen_with_import_diagnostics(published_diagnostics) + + def test_textDocument_opening_two_new_files_edit_and_close(self, solc: JsonRpcProcess) -> None: + """ + Open two new files A and B, let A import B, expect no error, + then close B and now expect the error of file B not being found. + """ + + self.setup_lsp(solc) + FILE_A_URI = 'file:///a.sol' + solc.send_message('textDocument/didOpen', { + 'textDocument': { + 'uri': FILE_A_URI, + 'languageId': 'Solidity', + 'version': 1, + 'text': ''.join([ + '// SPDX-License-Identifier: UNLICENSED\n', + 'pragma solidity >=0.8.0;\n', + ]) + } + }) + reports = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(reports), 1, "one publish diagnostics notification") + self.expect_equal(len(reports[0]['diagnostics']), 0, "should not contain diagnostics") + + FILE_B_URI = 'file:///b.sol' + solc.send_message('textDocument/didOpen', { + 'textDocument': { + 'uri': FILE_B_URI, + 'languageId': 'Solidity', + 'version': 1, + 'text': ''.join([ + '// SPDX-License-Identifier: UNLICENSED\n', + 'pragma solidity >=0.8.0;\n', + ]) + } + }) + reports = self.wait_for_diagnostics(solc, 2) + self.expect_equal(len(reports), 2, "one publish diagnostics notification") + self.expect_equal(len(reports[0]['diagnostics']), 0, "should not contain diagnostics") + self.expect_equal(len(reports[1]['diagnostics']), 0, "should not contain diagnostics") + + solc.send_message('textDocument/didChange', { + 'textDocument': { + 'uri': FILE_A_URI + }, + 'contentChanges': [ + { + 'range': { + 'start': { 'line': 2, 'character': 0 }, + 'end': { 'line': 2, 'character': 0 } + }, + 'text': 'import "./b.sol";\n' + } + ] + }) + reports = self.wait_for_diagnostics(solc, 2) + self.expect_equal(len(reports), 2, "one publish diagnostics notification") + self.expect_equal(len(reports[0]['diagnostics']), 0, "should not contain diagnostics") + self.expect_equal(len(reports[1]['diagnostics']), 0, "should not contain diagnostics") + + solc.send_message( + 'textDocument/didClose', + { 'textDocument': { 'uri': FILE_B_URI }} + ) + # We only get one diagnostics message since the diagnostics for b.sol was empty. + reports = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(reports), 1, "one publish diagnostics notification") + self.expect_diagnostic(reports[0]['diagnostics'][0], 6275, 2, (0, 17)) # a.sol: File B not found + self.expect_equal(reports[0]['uri'], FILE_A_URI, "Correct uri") + + def test_textDocument_closing_virtual_file_removes_imported_real_file(self, solc: JsonRpcProcess) -> None: + """ + We open a virtual file that imports a real file with a warning. + Once we close the virtual file, the warning is removed from the diagnostics, + since the real file is not considered part of the project anymore. + """ + + self.setup_lsp(solc) + FILE_A_URI = f'file://{self.project_root_dir}/a.sol' + solc.send_message('textDocument/didOpen', { + 'textDocument': { + 'uri': FILE_A_URI, + 'languageId': 'Solidity', + 'version': 1, + 'text': + '// SPDX-License-Identifier: UNLICENSED\n' + 'pragma solidity >=0.8.0;\n' + 'import "./lib.sol";\n' + } + }) + reports = self.wait_for_diagnostics(solc, 2) + self.expect_equal(len(reports), 2, '') + self.expect_equal(len(reports[0]['diagnostics']), 0, "should not contain diagnostics") + self.expect_diagnostic(reports[1]['diagnostics'][0], 2072, 12, (8, 19)) # unused variable in lib.sol + + # Now close the file and expect the warning for lib.sol to be removed + solc.send_message( + 'textDocument/didClose', + { 'textDocument': { 'uri': FILE_A_URI }} + ) + reports = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(reports), 1, '') + self.expect_equal(reports[0]['uri'], f'file://{self.project_root_dir}/lib.sol', "") + self.expect_equal(len(reports[0]['diagnostics']), 0, "should not contain diagnostics") + + + def test_textDocument_didChange_at_eol(self, solc: JsonRpcProcess) -> None: + """ + Append at one line and insert a new one below. + """ + self.setup_lsp(solc) + FILE_NAME = 'didChange_template' + FILE_URI = self.get_test_file_uri(FILE_NAME) + solc.send_message('textDocument/didOpen', { + 'textDocument': { + 'uri': FILE_URI, + 'languageId': 'Solidity', + 'version': 1, + 'text': self.get_test_file_contents(FILE_NAME) + } + }) + published_diagnostics = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(published_diagnostics), 1, "one publish diagnostics notification") + self.expect_equal(len(published_diagnostics[0]['diagnostics']), 0, "no diagnostics") + solc.send_message('textDocument/didChange', { + 'textDocument': { + 'uri': FILE_URI + }, + 'contentChanges': [ + { + 'range': { + 'start': { 'line': 6, 'character': 0 }, + 'end': { 'line': 6, 'character': 0 } + }, + 'text': " f" + } + ] + }) + published_diagnostics = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(published_diagnostics), 1, "one publish diagnostics notification") + report2 = published_diagnostics[0] + self.expect_equal(report2['uri'], FILE_URI, "Correct file URI") + self.expect_equal(len(report2['diagnostics']), 1, "one diagnostic") + self.expect_diagnostic(report2['diagnostics'][0], 7858, 6, (1, 2)) + + solc.send_message('textDocument/didChange', { + 'textDocument': { 'uri': FILE_URI }, + 'contentChanges': [ + { + 'range': { + 'start': { 'line': 6, 'character': 2 }, + 'end': { 'line': 6, 'character': 2 } + }, + 'text': 'unction f() public {}' + } + ] + }) + published_diagnostics = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(published_diagnostics), 1, "one publish diagnostics notification") + report3 = published_diagnostics[0] + self.expect_equal(report3['uri'], FILE_URI, "Correct file URI") + self.expect_equal(len(report3['diagnostics']), 1, "one diagnostic") + self.expect_diagnostic(report3['diagnostics'][0], 4126, 6, (1, 23)) + + def test_textDocument_didChange_empty_file(self, solc: JsonRpcProcess) -> None: + """ + Starts with an empty file and changes it to look like + the didOpen_with_import test case. Then we can use + the same verification calls to ensure it worked as expected. + """ + # This FILE_NAME must be alphabetically before lib.sol to not over-complify + # the test logic in verify_didOpen_with_import_diagnostics. + FILE_NAME = 'a_new_file' + FILE_URI = self.get_test_file_uri(FILE_NAME) + self.setup_lsp(solc) + solc.send_message('textDocument/didOpen', { + 'textDocument': { + 'uri': FILE_URI, + 'languageId': 'Solidity', + 'version': 1, + 'text': '' + } + }) + reports = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(reports), 1) + report = reports[0] + published_diagnostics = report['diagnostics'] + self.expect_equal(len(published_diagnostics), 2) + self.expect_diagnostic(published_diagnostics[0], code=1878, lineNo=0, startEndColumns=(0, 0)) + self.expect_diagnostic(published_diagnostics[1], code=3420, lineNo=0, startEndColumns=(0, 0)) + solc.send_message('textDocument/didChange', { + 'textDocument': { + 'uri': self.get_test_file_uri('a_new_file') + }, + 'contentChanges': [ + { + 'range': { + 'start': { 'line': 0, 'character': 0 }, + 'end': { 'line': 0, 'character': 0 } + }, + 'text': self.get_test_file_contents('didOpen_with_import') + } + ] + }) + published_diagnostics = self.wait_for_diagnostics(solc, 2) + self.verify_didOpen_with_import_diagnostics(published_diagnostics, 'a_new_file') + + def test_textDocument_didChange_multi_line(self, solc: JsonRpcProcess) -> None: + """ + Starts with an empty file and changes it to multiple times, changing + content across lines. + """ + self.setup_lsp(solc) + FILE_NAME = 'didChange_template' + FILE_URI = self.get_test_file_uri(FILE_NAME) + solc.send_message('textDocument/didOpen', { + 'textDocument': { + 'uri': FILE_URI, + 'languageId': 'Solidity', + 'version': 1, + 'text': self.get_test_file_contents(FILE_NAME) + } + }) + published_diagnostics = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(published_diagnostics), 1, "one publish diagnostics notification") + self.expect_equal(len(published_diagnostics[0]['diagnostics']), 0, "no diagnostics") + solc.send_message('textDocument/didChange', { + 'textDocument': { 'uri': FILE_URI }, + 'contentChanges': [ + { + 'range': { + 'start': { 'line': 3, 'character': 3 }, + 'end': { 'line': 4, 'character': 1 } + }, + 'text': "tract D {\n\n uint x\n = -1; \n " + } + ] + }) + published_diagnostics = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(published_diagnostics), 1, "one publish diagnostics notification") + report2 = published_diagnostics[0] + self.expect_equal(report2['uri'], FILE_URI, "Correct file URI") + self.expect_equal(len(report2['diagnostics']), 1, "one diagnostic") + self.expect_diagnostic(report2['diagnostics'][0], 7407, 6, (3, 5)) + + # Now we are changing the part "x\n = -" of "uint x\n = -1;" + solc.send_message('textDocument/didChange', { + 'textDocument': { 'uri': FILE_URI }, + 'contentChanges': [ + { + 'range': { + 'start': { 'line': 5, 'character': 7 }, + 'end': { 'line': 6, 'character': 4 } + }, + 'text': "y\n = [\nuint(1),\n3,4]+" + } + ] + }) + published_diagnostics = self.wait_for_diagnostics(solc, 1) + self.expect_equal(len(published_diagnostics), 1, "one publish diagnostics notification") + report3 = published_diagnostics[0] + self.expect_equal(report3['uri'], FILE_URI, "Correct file URI") + self.expect_equal(len(report3['diagnostics']), 2, "two diagnostics") + diagnostic = report3['diagnostics'][0] + self.expect_equal(diagnostic['code'], 2271, 'diagnostic: 2271') + # check multi-line error code + self.expect_equal( + diagnostic['range'], + { + 'end': {'character': 6, 'line': 8}, + 'start': {'character': 3, 'line': 6} + }, + "diagnostic: check range" + ) + diagnostic = report3['diagnostics'][1] + self.expect_equal(diagnostic['code'], 7407, 'diagnostic: 7407') + # check multi-line error code + self.expect_equal( + diagnostic['range'], + { + 'end': {'character': 6, 'line': 8}, + 'start': {'character': 3, 'line': 6} + }, + "diagnostic: check range" + ) + + # }}} + # }}} + +if __name__ == "__main__": + suite = SolidityLSPTestSuite() + exit_code = suite.main() + exit(exit_code) diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 494dbbd94d..73c999f3f7 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -158,7 +158,7 @@ BOOST_AUTO_TEST_CASE(multiple_input_modes) }; string expectedMessage = "The following options are mutually exclusive: " - "--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast. " + "--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast, --lsp. " "Select at most one."; for (string const& mode1: inputModeOptions) From 84738eb9e6c630949cff0a21c1faedd8cbed9274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 16 Dec 2021 18:05:25 +0100 Subject: [PATCH 0095/1704] Add security policy to github's template chooser --- .github/ISSUE_TEMPLATE/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 139c117874..a5a945a675 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -9,3 +9,6 @@ contact_links: - name: Feature Request url: https://github.com/ethereum/solidity/issues/new?template=feature_request.md&projects=ethereum/solidity/43 about: Solidity language or infrastructure feature requests. + - name: Report a security vulnerability + url: https://github.com/ethereum/solidity/security/policy + about: Please review our security policy for more details. From b3d9c596cd8371728935cfaedb060ff439075315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 16 Dec 2021 18:12:04 +0100 Subject: [PATCH 0096/1704] Move issue template labels to config.yml --- .github/ISSUE_TEMPLATE/bug_report.md | 1 - .github/ISSUE_TEMPLATE/config.yml | 6 +++--- .github/ISSUE_TEMPLATE/documentation_issue.md | 1 - .github/ISSUE_TEMPLATE/feature_request.md | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 7be77f4226..36e25b1f09 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,5 @@ --- name: Bug Report -labels: ["bug :bug:"] --- no change in version. -3. A breaking change is introduced --> version is bumped to 0.5.0. -4. The 0.5.0 release is made. +1. The 0.4.0 release is made. +2. The nightly build has a version of 0.4.1 from now on. +3. Non-breaking changes are introduced --> no change in version. +4. A breaking change is introduced --> version is bumped to 0.5.0. +5. The 0.5.0 release is made. This behaviour works well with the :ref:`version pragma `. From 95f9289f2ced419639478821618f962041ac9599 Mon Sep 17 00:00:00 2001 From: Younghoon-Lee <8109h@naver.com> Date: Fri, 28 Jan 2022 01:11:35 +0900 Subject: [PATCH 0207/1704] Add blank line to make it consistency --- docs/style-guide.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 177f4a7987..1bbe6cc740 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -281,6 +281,7 @@ Yes: // ... } + contract B is Owned { // ... } @@ -846,15 +847,20 @@ Yes: constructor(uint) { } } + + contract C { constructor(uint, uint) { } } + + contract D { constructor(uint) { } } + contract A is B, C, D { uint x; From dec511aad8f7ea748455a2bdc5e3218398f04995 Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Tue, 25 Jan 2022 20:31:01 +0530 Subject: [PATCH 0208/1704] Corresponding code in the .cpp file has been commented instead of begin removed pending preliminary reviews Code generators needed fixing of the cleanup process during typecasting of bytes and integers --- Changelog.md | 2 ++ libsolidity/codegen/YulUtilFunctions.cpp | 4 ++-- .../codegen/ir/IRGeneratorForStatements.cpp | 15 +++++++----- .../codegen/ir/IRGeneratorForStatements.h | 12 ++++++---- ...nup_bytes_types_shortening_OldCodeGen.sol} | 5 ++-- ...anup_bytes_types_shortening_newCodeGen.sol | 14 +++++++++++ ...xed_log_topic_during_explicit_downcast.sol | 23 +++++++++++++++++++ ...ing_explicit_downcast_during_emissions.sol | 19 +++++++++++++++ .../userDefinedValueType/erc20.sol | 2 +- .../semanticTests/various/erc20.sol | 2 +- 10 files changed, 81 insertions(+), 17 deletions(-) rename test/libsolidity/semanticTests/cleanup/{cleanup_bytes_types_shortening.sol => cleanup_bytes_types_shortening_OldCodeGen.sol} (77%) create mode 100644 test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening_newCodeGen.sol create mode 100644 test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast.sol create mode 100644 test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast_during_emissions.sol diff --git a/Changelog.md b/Changelog.md index 571c1011d3..510feae9f2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,8 @@ Bugfixes: * Code Generator: Fix ICE 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. * Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the parent contract contains immutable variables. + * 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: 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. * TypeChecker: Fix ICE when a constant variable declaration forward references a struct. diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 217ec14b0d..84f63a9e15 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -3400,11 +3400,11 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) .render(); else { - // clear for conversion to longer bytes solAssert(toCategory == Type::Category::FixedBytes, "Invalid type conversion requested."); + FixedBytesType const& to = dynamic_cast(_to); body = Whiskers("converted := (value)") - ("clean", cleanupFunction(from)) + ("clean", cleanupFunction((to.numBytes() <= from.numBytes()) ? to : from)) .render(); } break; diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 420c48baa4..cf48df4700 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1035,7 +1035,10 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) ")\n"; } else - indexedArgs.emplace_back(convert(arg, *paramTypes[i])); + { + solAssert(parameterTypes[i]->sizeOnStack() == 1, ""); + indexedArgs.emplace_back(convert(arg, *paramTypes[i], true)); + } } else { @@ -2724,14 +2727,14 @@ void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly( m_context.addToInternalDispatch(_referencedFunction); } -IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to) +IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to, bool _forceCleanup) { - if (_from.type() == _to) + if (_from.type() == _to && !_forceCleanup) return _from; else { IRVariable converted(m_context.newYulVariable(), _to); - define(converted, _from); + define(converted, _from, _forceCleanup); return converted; } } @@ -2763,10 +2766,10 @@ void IRGeneratorForStatements::declare(IRVariable const& _var) appendCode() << "let " << _var.commaSeparatedList() << "\n"; } -void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare) +void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare, bool _forceCleanup) { string output; - if (_lhs.type() == _rhs.type()) + if (_lhs.type() == _rhs.type() && !_forceCleanup) for (auto const& [stackItemName, stackItemType]: _lhs.type().stackItems()) if (stackItemType) declareAssign(_lhs.part(stackItemName), _rhs.part(stackItemName), _declare); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index 74b7def549..10e8f0b5ef 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -86,7 +86,11 @@ class IRGeneratorForStatements: public IRGeneratorForStatementsBase IRVariable evaluateExpression(Expression const& _expression, Type const& _to); /// Defines @a _var using the value of @a _value while performing type conversions, if required. - void define(IRVariable const& _var, IRVariable const& _value) { declareAssign(_var, _value, true); } + /// If @a _forceCleanup is set to true, it also cleans the value of the variable after the conversion. + void define(IRVariable const& _var, IRVariable const& _value, bool _forceCleanup = false) + { + declareAssign(_var, _value, true, _forceCleanup); + } /// @returns the name of a function that computes the value of the given constant /// and also generates the function. @@ -162,8 +166,8 @@ class IRGeneratorForStatements: public IRGeneratorForStatementsBase ); /// Generates the required conversion code and @returns an IRVariable referring to the value of @a _variable - /// converted to type @a _to. - IRVariable convert(IRVariable const& _variable, Type const& _to); + /// If @a _forceCleanup is set to true, it also cleans the value of the variable after the conversion. + IRVariable convert(IRVariable const& _variable, Type const& _to, bool _forceCleanup = false); /// @returns a Yul expression representing the current value of @a _expression, /// converted to type @a _to if it does not yet have that type. @@ -179,7 +183,7 @@ class IRGeneratorForStatements: public IRGeneratorForStatementsBase /// Declares variable @a _var. void declare(IRVariable const& _var); - void declareAssign(IRVariable const& _var, IRVariable const& _value, bool _define); + void declareAssign(IRVariable const& _var, IRVariable const& _value, bool _define, bool _forceCleanup = false); /// @returns an IRVariable with the zero /// value of @a _type. diff --git a/test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening.sol b/test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening_OldCodeGen.sol similarity index 77% rename from test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening.sol rename to test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening_OldCodeGen.sol index edae83729c..9ca68e6d0d 100644 --- a/test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening.sol +++ b/test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening_OldCodeGen.sol @@ -11,7 +11,6 @@ contract C { } } // ==== -// compileToEwasm: also -// compileViaYul: also +// compileViaYul: false // ---- -// f() -> "\xff\xff\xff\xff" +// f() -> 0xffffffff00000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening_newCodeGen.sol b/test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening_newCodeGen.sol new file mode 100644 index 0000000000..a99b82a085 --- /dev/null +++ b/test/libsolidity/semanticTests/cleanup/cleanup_bytes_types_shortening_newCodeGen.sol @@ -0,0 +1,14 @@ +contract C { + function f() public pure returns (bytes32 r) { + bytes4 x = 0xffffffff; + bytes2 y = bytes2(x); + assembly { + r := y + } + } +} +// ==== +// compileToEwasm: also +// compileViaYul: true +// ---- +// f() -> 0xffff000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast.sol b/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast.sol new file mode 100644 index 0000000000..f0aa239bae --- /dev/null +++ b/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast.sol @@ -0,0 +1,23 @@ +contract C { + function f() public pure returns (uint32 y) { + uint8 x = uint8(uint256(0x31313131313131313131313131313131)); + assembly { y := x } + } + + function g() public pure returns (bytes32 y) { + bytes1 x = bytes1(bytes16(0x31313131313131313131313131313131)); + assembly { y := x } + } + + function h() external returns (bytes32 y) { + bytes1 x; + assembly { x := sub(0,1) } + y = x; + } +} +// ==== +// compileViaYul: true +// ---- +// f() -> 0x31 +// g() -> 0x3100000000000000000000000000000000000000000000000000000000000000 +// h() -> 0xff00000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast_during_emissions.sol b/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast_during_emissions.sol new file mode 100644 index 0000000000..df6bc2192f --- /dev/null +++ b/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast_during_emissions.sol @@ -0,0 +1,19 @@ +contract C { + event ev0(bytes1 indexed); + constructor() { + emit ev0(bytes1(bytes16(0x31313131313131313131313131313131))); + } + function j() external { + bytes1 x; + assembly { x := 0x3131313131313131313131313131313131313131313131313131313131313131 } + emit ev0(x); + } +} +// ==== +// compileViaYul: also +// ---- +// constructor() -> +// ~ emit ev0(bytes1): #"1" +// gas legacy: 168735 +// j() -> +// ~ emit ev0(bytes1): #"1" diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index efe2ee1148..220d9d9a24 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -115,7 +115,7 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 442239 +// gas irOptimized: 447831 // gas legacy: 861559 // gas legacyOptimized: 420959 // totalSupply() -> 20 diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index 204e620d62..64a3286a94 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -98,7 +98,7 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 437697 +// gas irOptimized: 443295 // gas legacy: 833310 // gas legacyOptimized: 416135 // totalSupply() -> 20 From 0f7b69432e9c7d576c57812889dba3261053a534 Mon Sep 17 00:00:00 2001 From: Nikita Stupin <18281368+nikitastupin@users.noreply.github.com> Date: Tue, 21 Sep 2021 12:04:43 +0300 Subject: [PATCH 0209/1704] Separate visibility for state variables and functions --- docs/contracts/visibility-and-getters.rst | 63 ++++++++++++++--------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index f04945cfdb..8932c5079b 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -1,20 +1,41 @@ .. index:: ! visibility, external, public, private, internal +.. |visibility-caveat| replace:: Making something ``private`` or ``internal`` only prevents other contracts from reading or modifying the information, but it will still be visible to the whole world outside of the blockchain. + .. _visibility-and-getters: ********************** Visibility and Getters ********************** -Solidity knows two kinds of function calls: internal -ones that do not create an actual EVM call (also called -a "message call") and external -ones that do. Because of that, there are four types of visibility for -functions and state variables. +State Variable Visibility +========================= + +``public`` + Public state variables differ from internal ones only in that the compiler automatically generates + :ref:`getter functions` for them, which allows other contracts to read their values. + When used within the same contract, the external access (e.g. ``this.x``) invokes the getter + while internal access (e.g. ``x``) gets the variable value directly from storage. + Setter functions are not generated so other contracts cannot directly modify their values. + +``internal`` + Internal state variables can only be accessed from within the contract they are defined in + and in derived contracts. + They cannot be accessed externally. + This is the default visibility level for state variables. + +``private`` + Private state variables are like internal ones but they are not visible in derived contracts. + +.. warning:: + |visibility-caveat| -Functions have to be specified as being ``external``, -``public``, ``internal`` or ``private``. -For state variables, ``external`` is not possible. +Function Visibility +=================== + +Solidity knows two kinds of function calls: external ones that do create an actual EVM message call and internal ones that do not. +Furthermore, internal functions can be made inaccessible to derived contracts. +This gives rise to four types of visibility for functions. ``external`` External functions are part of the contract interface, @@ -24,27 +45,19 @@ For state variables, ``external`` is not possible. ``public`` Public functions are part of the contract interface - and can be either called internally or via - messages. For public state variables, an automatic getter - function (see below) is generated. + and can be either called internally or via message calls. ``internal`` - Those functions and state variables can only be - accessed internally (i.e. from within the current contract - or contracts deriving from it), without using ``this``. - This is the default visibility level for state variables. + Internal functions can only be accessed from within the current contract + or contracts deriving from it. + They cannot be accessed externally. + Since they are not exposed to the outside through the contract's ABI, they can take parameters of internal types like mappings or storage references. ``private`` - Private functions and state variables are only - visible for the contract they are defined in and not in - derived contracts. - -.. note:: - Everything that is inside a contract is visible to - all observers external to the blockchain. Making something ``private`` - only prevents other contracts from reading or modifying - the information, but it will still be visible to the - whole world outside of the blockchain. + Private functions are like internal ones but they are not visible in derived contracts. + +.. warning:: + |visibility-caveat| The visibility specifier is given after the type for state variables and between parameter list and From 0fe5811459bb25078e471ceeec475eaf49374d21 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 24 Jan 2022 11:56:27 +0100 Subject: [PATCH 0210/1704] Fixed a ICE on calldata to struct member copy --- Changelog.md | 1 + .../codegen/ir/IRGeneratorForStatements.cpp | 7 +- .../structs/copy_from_calldata.sol | 38 ++++++++ .../structs/copy_from_storage.sol | 24 +++++ .../copy_struct_array_from_storage.sol | 96 +++++++++++++++++++ .../structs/function_type_copy.sol | 44 +++++++++ .../msg_data_to_struct_member_copy.sol | 45 +++++++++ .../array/copy_from_function_type.sol | 9 ++ 8 files changed, 262 insertions(+), 2 deletions(-) create mode 100644 test/libsolidity/semanticTests/structs/copy_from_calldata.sol create mode 100644 test/libsolidity/semanticTests/structs/copy_from_storage.sol create mode 100644 test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol create mode 100644 test/libsolidity/semanticTests/structs/function_type_copy.sol create mode 100644 test/libsolidity/semanticTests/structs/msg_data_to_struct_member_copy.sol create mode 100644 test/libsolidity/syntaxTests/array/copy_from_function_type.sol diff --git a/Changelog.md b/Changelog.md index 510feae9f2..a49aedea4c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,6 +18,7 @@ Bugfixes: * Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the parent contract contains immutable variables. * 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: 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. * Natspec: Fix ICE 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. diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index cf48df4700..d68bc39c60 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2985,8 +2985,11 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable { solAssert(_lvalue.type.sizeOnStack() == 1); auto const* valueReferenceType = dynamic_cast(&_value.type()); - solAssert(valueReferenceType && valueReferenceType->dataStoredIn(DataLocation::Memory)); - appendCode() << "mstore(" + _memory.address + ", " + _value.part("mpos").name() + ")\n"; + solAssert(valueReferenceType); + if (valueReferenceType->dataStoredIn(DataLocation::Memory)) + appendCode() << "mstore(" + _memory.address + ", " + _value.part("mpos").name() + ")\n"; + else + appendCode() << "mstore(" + _memory.address + ", " + m_utils.conversionFunction(_value.type(), _lvalue.type) + "(" + _value.commaSeparatedList() + "))\n"; } }, [&](IRLValue::Stack const& _stack) { assign(_stack.variable, _value); }, diff --git a/test/libsolidity/semanticTests/structs/copy_from_calldata.sol b/test/libsolidity/semanticTests/structs/copy_from_calldata.sol new file mode 100644 index 0000000000..bfe6fc949c --- /dev/null +++ b/test/libsolidity/semanticTests/structs/copy_from_calldata.sol @@ -0,0 +1,38 @@ +// Example from https://github.com/ethereum/solidity/issues/12558 +pragma abicoder v2; +contract C { + function f(uint[] calldata a) external returns (uint[][] memory) { + uint[][] memory m = new uint[][](2); + m[0] = a; + + return m; + } +} +contract Test { + C immutable c = new C(); + + function test() external returns (bool) { + uint[] memory arr = new uint[](4); + + arr[0] = 13; + arr[1] = 14; + arr[2] = 15; + arr[3] = 16; + + uint[][] memory ret = c.f(arr); + assert(ret.length == 2); + assert(ret[0].length == 4); + assert(ret[0][0] == 13); + assert(ret[0][1] == 14); + assert(ret[0][2] == 15); + assert(ret[0][3] == 16); + assert(ret[1].length == 0); + + return true; + } +} +// ==== +// EVMVersion: >homestead +// compileViaYul: also +// ---- +// test() -> true diff --git a/test/libsolidity/semanticTests/structs/copy_from_storage.sol b/test/libsolidity/semanticTests/structs/copy_from_storage.sol new file mode 100644 index 0000000000..d4a970bdce --- /dev/null +++ b/test/libsolidity/semanticTests/structs/copy_from_storage.sol @@ -0,0 +1,24 @@ +pragma abicoder v2; +// Example from https://github.com/ethereum/solidity/issues/12558 +struct S { + uint x; +} + +contract C { + S sStorage; + constructor() { + sStorage.x = 13; + } + + function f() external returns (S[] memory) { + S[] memory sMemory = new S[](1); + + sMemory[0] = sStorage; + + return sMemory; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 0x20, 1, 13 diff --git a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol new file mode 100644 index 0000000000..7bbe495ce2 --- /dev/null +++ b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol @@ -0,0 +1,96 @@ +pragma abicoder v2; + +struct S { uint value; } + +contract Test { + S[][] a; + S[] b; + + constructor() { + a.push(); + a[0].push(S(1)); + a[0].push(S(2)); + a[0].push(S(3)); + + b.push(S(4)); + b.push(S(5)); + b.push(S(6)); + b.push(S(7)); + } + + function test1() external returns (bool) { + a.push(); + a[1] = b; + + assert(a.length == 2); + assert(a[0].length == 3); + assert(a[1].length == 4); + assert(a[1][0].value == 4); + assert(a[1][1].value == 5); + assert(a[1][2].value == 6); + assert(a[1][3].value == 7); + + return true; + } + + function test2() external returns (bool) { + S[][] memory temp = new S[][](2); + + temp = a; + + assert(temp.length == 2); + assert(temp[0].length == 3); + assert(temp[1].length == 4); + assert(temp[1][0].value == 4); + assert(temp[1][1].value == 5); + assert(temp[1][2].value == 6); + assert(temp[1][3].value == 7); + + return true; + } + + function test3() external returns (bool) { + S[][] memory temp = new S[][](2); + + temp[0] = a[0]; + temp[1] = a[1]; + + assert(temp.length == 2); + assert(temp[0].length == 3); + assert(temp[1].length == 4); + assert(temp[1][0].value == 4); + assert(temp[1][1].value == 5); + assert(temp[1][2].value == 6); + assert(temp[1][3].value == 7); + + return true; + } + + function test4() external returns (bool) { + S[][] memory temp = new S[][](2); + + temp[0] = a[0]; + temp[1] = b; + + assert(temp.length == 2); + assert(temp[0].length == 3); + assert(temp[1].length == 4); + assert(temp[1][0].value == 4); + assert(temp[1][1].value == 5); + assert(temp[1][2].value == 6); + assert(temp[1][3].value == 7); + + return true; + } +} +// ==== +// EVMVersion: >homestead +// compileViaYul: also +// ---- +// test1() -> true +// gas irOptimized: 150618 +// gas legacy: 150266 +// gas legacyOptimized: 149875 +// test2() -> true +// test3() -> true +// test4() -> true diff --git a/test/libsolidity/semanticTests/structs/function_type_copy.sol b/test/libsolidity/semanticTests/structs/function_type_copy.sol new file mode 100644 index 0000000000..79fe5ef4c8 --- /dev/null +++ b/test/libsolidity/semanticTests/structs/function_type_copy.sol @@ -0,0 +1,44 @@ +pragma abicoder v2; +struct S { + function () external[] functions; +} + +contract C { + function f(function () external[] calldata functions) external returns (S memory) { + S memory s; + s.functions = functions; + return s; + } +} + +contract Test { + C immutable c = new C(); + + function test() external returns (bool) { + function() external[] memory functions = new function() external[](3); + + functions[0] = this.random1; + functions[1] = this.random2; + functions[2] = this.random3; + + S memory ret = c.f(functions); + + assert(ret.functions.length == 3); + assert(ret.functions[0] == this.random1); + assert(ret.functions[1] == this.random2); + assert(ret.functions[2] == this.random3); + + return true; + } + function random1() external { + } + function random2() external { + } + function random3() external { + } +} +// ==== +// EVMVersion: >homestead +// compileViaYul: also +// ---- +// test() -> true diff --git a/test/libsolidity/semanticTests/structs/msg_data_to_struct_member_copy.sol b/test/libsolidity/semanticTests/structs/msg_data_to_struct_member_copy.sol new file mode 100644 index 0000000000..f28bbf477f --- /dev/null +++ b/test/libsolidity/semanticTests/structs/msg_data_to_struct_member_copy.sol @@ -0,0 +1,45 @@ +pragma abicoder v2; + +struct St0 { + bytes el0; +} +contract C { + function f() external returns (St0 memory) { + St0 memory x; + x.el0 = msg.data; + return x; + } + + function g() external returns (St0 memory) { + bytes memory temp = msg.data; + St0 memory x; + x.el0 = temp; + return x; + } + + function hashes() external returns (bytes4, bytes4) { + return (this.f.selector, this.g.selector); + } + + function large(uint256, uint256, uint256, uint256) external returns (St0 memory) { + St0 memory x; + x.el0 = msg.data; + return x; + } + + function another_large(uint256, uint256, uint256, uint256) external returns (St0 memory) { + bytes memory temp = msg.data; + St0 memory x; + x.el0 = temp; + return x; + } + +} +// ==== +// compileViaYul: also +// ---- +// f() -> 0x20, 0x20, 4, 0x26121ff000000000000000000000000000000000000000000000000000000000 +// g() -> 0x20, 0x20, 4, 0xe2179b8e00000000000000000000000000000000000000000000000000000000 +// hashes() -> 0x26121ff000000000000000000000000000000000000000000000000000000000, 0xe2179b8e00000000000000000000000000000000000000000000000000000000 +// large(uint256,uint256,uint256,uint256): 1, 2, 3, 4 -> 0x20, 0x20, 0x84, 0xe02492f800000000000000000000000000000000000000000000000000000000, 0x100000000000000000000000000000000000000000000000000000000, 0x200000000000000000000000000000000000000000000000000000000, 0x300000000000000000000000000000000000000000000000000000000, 0x400000000000000000000000000000000000000000000000000000000 +// another_large(uint256,uint256,uint256,uint256): 1, 2, 3, 4 -> 0x20, 0x20, 0x84, 0x2a46f85a00000000000000000000000000000000000000000000000000000000, 0x100000000000000000000000000000000000000000000000000000000, 0x200000000000000000000000000000000000000000000000000000000, 0x300000000000000000000000000000000000000000000000000000000, 0x400000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/syntaxTests/array/copy_from_function_type.sol b/test/libsolidity/syntaxTests/array/copy_from_function_type.sol new file mode 100644 index 0000000000..b795094683 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/copy_from_function_type.sol @@ -0,0 +1,9 @@ +// Example from https://github.com/ethereum/solidity/issues/12558 +pragma abicoder v2; +contract C { + function() external[1][] s0; + constructor(function() external[1][] memory i0) + { + i0[0] = s0[1]; + } +} From f1ce1528bb988fe3d51f3cc98e16dd1b5eaa9d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 28 Jan 2022 21:46:01 +0100 Subject: [PATCH 0211/1704] Update the release checklist to use the build+publish commands for solc-js --- ReleaseChecklist.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index b95ea32a94..39a3d9a324 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -66,7 +66,8 @@ ### Release solc-js - [ ] Wait until solc-bin was properly deployed. You can test this via remix - a test run through remix is advisable anyway. - [ ] Increment the version number, create a pull request for that, merge it after tests succeeded. - - [ ] Run ``npm run updateBinary && npm publish`` in the updated ``solc-js`` repository. + - [ ] Run ``npm run build:tarball`` in the updated ``solc-js`` repository to create ``solc-.tgz``. Inspect the tarball to ensure that it contains an up to date compiler binary. + - [ ] Run ``npm run publish:tarball`` to publish the newly created tarball. - [ ] Create a tag using ``git tag --annotate v$VERSION`` and push it with ``git push --tags``. ### Post-release From 8728971354c15b1a8147726fa8c3efe8c801f0ee Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 31 Jan 2022 19:07:01 +0100 Subject: [PATCH 0212/1704] Correct type of address.code --- docs/types/value-types.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 215a18ceec..30a8577963 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -331,7 +331,9 @@ on ``call``. * ``code`` and ``codehash`` -You can query the deployed code for any smart contract. Use ``code`` to get the EVM bytecode as a string, which might be empty. Use ``codehash`` get the Keccak-256 hash of that code. +You can query the deployed code for any smart contract. Use ``.code`` to get the EVM bytecode as a +``bytes memory``, which might be empty. Use ``.codehash`` get the Keccak-256 hash of that code +(as a ``bytes32``). Note that ``addr.codehash`` is cheaper than using ``keccak256(addr.code)``. .. note:: All contracts can be converted to ``address`` type, so it is possible to query the balance of the From 4259e1bb7021d28931bf3d3f5973e32431f2c837 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 31 Jan 2022 19:18:32 +0100 Subject: [PATCH 0213/1704] Fix changelog --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index a49aedea4c..e75e2c710e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,7 +15,7 @@ Bugfixes: * Code Generator: Fix ICE 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``. * Control Flow Graph: Perform proper virtual lookup for modifiers for uninitialized variable and unreachable code analysis. - * Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the parent contract contains immutable variables. + * Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the derived contract contains immutable variables. * 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: Fix internal error when copying reference types in calldata and storage to struct or array members in memory. From 73470aed6afb172f189a550b79e310c9cac8c680 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 3 Nov 2021 16:10:14 +0100 Subject: [PATCH 0214/1704] Fix util::valueOrDefault. --- libsolutil/CommonData.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index 0d5a75282e..b117c27728 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -267,17 +267,22 @@ template< typename MapType, typename KeyType, typename ValueType = std::decay_t().find(std::declval())->second)> const&, - typename AllowCopyType = void* + typename AllowCopyType = std::conditional_t || std::is_pointer_v, detail::allow_copy, void*> > -decltype(auto) valueOrDefault(MapType&& _map, KeyType const& _key, ValueType&& _defaultValue = {}, AllowCopyType = nullptr) +decltype(auto) valueOrDefault( + MapType&& _map, + KeyType const& _key, + ValueType&& _defaultValue = {}, + AllowCopyType = {} +) { auto it = _map.find(_key); static_assert( std::is_same_v || - std::is_reference_vsecond)>, + std::is_reference_v(_defaultValue) : it->second)>, "valueOrDefault does not allow copies by default. Pass allow_copy as additional argument, if you want to allow copies." ); - return (it == _map.end()) ? _defaultValue : it->second; + return (it == _map.end()) ? std::forward(_defaultValue) : it->second; } namespace detail From 8bcc4ee7d1a65f4732549f31cd7d5e8194c6c260 Mon Sep 17 00:00:00 2001 From: franzihei Date: Mon, 31 Jan 2022 15:32:49 +0100 Subject: [PATCH 0215/1704] Adding a few resources --- docs/resources.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/resources.rst b/docs/resources.rst index 5b8d0013ab..a3b8d17e08 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -14,7 +14,7 @@ General Resources * `Solidity Compiler Developers Chat `_ * `Awesome Solidity `_ * `Solidity by Example `_ - +* `Solidity Documentation Community Translations `_ Integrated (Ethereum) Development Environments ============================================== @@ -28,15 +28,15 @@ Integrated (Ethereum) Development Environments * `Embark `_ Developer platform for building and deploying decentralized applications. + * `Foundry `_ + Fast, portable and modular toolkit for Ethereum application development written in Rust. + * `Hardhat `_ Ethereum development environment with local Ethereum network, debugging features and plugin ecosystem. * `Remix `_ Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. - * `Scaffold-ETH `_ - Ethereum development stack focused on fast product iterations. - * `Truffle `_ Ethereum development framework. @@ -112,6 +112,9 @@ Solidity Tools * `PIET `_ A tool to develop, audit and use Solidity smart contracts through a simple graphical interface. +* `Scaffold-ETH `_ + Forkable Ethereum development stack focused on fast product iterations. + * `sol2uml `_ Unified Modeling Language (UML) class diagram generator for Solidity contracts. @@ -130,6 +133,9 @@ Solidity Tools * `Solhint `_ Solidity linter that provides security, style guide and best practice rules for smart contract validation. +* `Sourcify `_ + Decentralized automated contract verification service and public repository of contract metadata. + * `Sūrya `_ Utility tool for smart contract systems, offering a number of visual outputs and information about the contracts' structure. Also supports querying the function call graph. From e2711b7fabcbf3af0c15e415778d821c1581d913 Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Tue, 25 Jan 2022 20:31:01 +0530 Subject: [PATCH 0216/1704] Corresponding code in the .cpp file has been commented instead of begin removed pending preliminary reviews Code generators needed fixing of the cleanup process during typecasting of bytes and integers --- .../codegen/ir/IRGeneratorForStatements.cpp | 37 ++++++++++++------- .../codegen/ir/IRGeneratorForStatements.h | 30 +++++++++++---- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index d68bc39c60..86d00dbc9c 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -805,8 +805,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) if (auto type = dynamic_cast(commonType)) isSigned = type->isSigned(); - string args = expressionAsType(_binOp.leftExpression(), *commonType, true); - args += ", " + expressionAsType(_binOp.rightExpression(), *commonType, true); + string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType); + args += ", " + expressionAsCleanedType(_binOp.rightExpression(), *commonType); auto functionType = dynamic_cast(commonType); solAssert(functionType ? (op == Token::Equal || op == Token::NotEqual) : true, "Invalid function pointer comparison!"); @@ -1037,7 +1037,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) else { solAssert(parameterTypes[i]->sizeOnStack() == 1, ""); - indexedArgs.emplace_back(convert(arg, *paramTypes[i], true)); + indexedArgs.emplace_back(convertAndCleanup(arg, *parameterTypes[i])); } } else @@ -2727,32 +2727,43 @@ void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly( m_context.addToInternalDispatch(_referencedFunction); } -IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to, bool _forceCleanup) +IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to) { - if (_from.type() == _to && !_forceCleanup) + if (_from.type() == _to) return _from; else { IRVariable converted(m_context.newYulVariable(), _to); - define(converted, _from, _forceCleanup); + define(converted, _from); return converted; } } -std::string IRGeneratorForStatements::expressionAsType(Expression const& _expression, Type const& _to, bool _forceCleanup) +IRVariable IRGeneratorForStatements::convertAndCleanup(IRVariable const& _from, Type const& _to) +{ + IRVariable converted(m_context.newYulVariable(), _to); + defineAndCleanup(converted, _from); + return converted; +} + +std::string IRGeneratorForStatements::expressionAsType(Expression const& _expression, Type const& _to) { IRVariable from(_expression); if (from.type() == _to) - { - if (_forceCleanup) - return m_utils.cleanupFunction(_to) + "(" + from.commaSeparatedList() + ")"; - else - return from.commaSeparatedList(); - } + return from.commaSeparatedList(); else return m_utils.conversionFunction(from.type(), _to) + "(" + from.commaSeparatedList() + ")"; } +std::string IRGeneratorForStatements::expressionAsCleanedType(Expression const& _expression, Type const& _to) +{ + IRVariable from(_expression); + if (from.type() == _to) + return m_utils.cleanupFunction(_to) + "(" + expressionAsType(_expression, _to) + ")"; + else + return expressionAsType(_expression, _to) ; +} + std::ostream& IRGeneratorForStatements::define(IRVariable const& _var) { if (_var.type().sizeOnStack() > 0) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index 10e8f0b5ef..11f8b3c846 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -86,10 +86,19 @@ class IRGeneratorForStatements: public IRGeneratorForStatementsBase IRVariable evaluateExpression(Expression const& _expression, Type const& _to); /// Defines @a _var using the value of @a _value while performing type conversions, if required. - /// If @a _forceCleanup is set to true, it also cleans the value of the variable after the conversion. - void define(IRVariable const& _var, IRVariable const& _value, bool _forceCleanup = false) + void define(IRVariable const& _var, IRVariable const& _value) { - declareAssign(_var, _value, true, _forceCleanup); + bool _declare = true; + declareAssign(_var, _value, _declare); + } + + /// Defines @a _var using the value of @a _value while performing type conversions, if required. + /// It also cleans the value of the variable. + void defineAndCleanup(IRVariable const& _var, IRVariable const& _value) + { + bool _forceCleanup = true; + bool _declare = true; + declareAssign(_var, _value, _declare, _forceCleanup); } /// @returns the name of a function that computes the value of the given constant @@ -166,13 +175,20 @@ class IRGeneratorForStatements: public IRGeneratorForStatementsBase ); /// Generates the required conversion code and @returns an IRVariable referring to the value of @a _variable - /// If @a _forceCleanup is set to true, it also cleans the value of the variable after the conversion. - IRVariable convert(IRVariable const& _variable, Type const& _to, bool _forceCleanup = false); + IRVariable convert(IRVariable const& _variable, Type const& _to); + + /// Generates the required conversion code and @returns an IRVariable referring to the value of @a _variable + /// It also cleans the value of the variable. + IRVariable convertAndCleanup(IRVariable const& _from, Type const& _to); + + /// @returns a Yul expression representing the current value of @a _expression, + /// converted to type @a _to if it does not yet have that type. + std::string expressionAsType(Expression const& _expression, Type const& _to); /// @returns a Yul expression representing the current value of @a _expression, /// converted to type @a _to if it does not yet have that type. - /// If @a _forceCleanup is set to true, it also cleans the value, in case it already has type @a _to. - std::string expressionAsType(Expression const& _expression, Type const& _to, bool _forceCleanup = false); + /// It also cleans the value, in case it already has type @a _to. + std::string expressionAsCleanedType(Expression const& _expression, Type const& _to); /// @returns an output stream that can be used to define @a _var using a function call or /// single stack slot expression. From 1528d4b9e4e8de6771ce15da90341e96d08dba86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 1 Feb 2022 14:34:03 +0100 Subject: [PATCH 0217/1704] perpetual-pools: Switch the test to our fork (original repo is gone) --- test/externalTests/perpetual-pools.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/perpetual-pools.sh b/test/externalTests/perpetual-pools.sh index 6c4af4937b..e1ee9af8f5 100755 --- a/test/externalTests/perpetual-pools.sh +++ b/test/externalTests/perpetual-pools.sh @@ -34,7 +34,7 @@ function test_fn { yarn test; } function perpetual_pools_test { - local repo="https://github.com/tracer-protocol/perpetual-pools-contracts" + local repo="https://github.com/solidity-external-tests/perpetual-pools-contracts" local ref_type=branch local ref=pools-v2 local config_file="hardhat.config.ts" From 6788f77541729e3ab2bc9e41dda66c2c06540b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 1 Feb 2022 15:25:13 +0100 Subject: [PATCH 0218/1704] Add missing SELECTED_PRESETS argument to some of the recently added external tests --- test/externalTests/bleeps.sh | 1 + test/externalTests/elementfi.sh | 1 + test/externalTests/trident.sh | 1 + test/externalTests/uniswap.sh | 1 + 4 files changed, 4 insertions(+) diff --git a/test/externalTests/bleeps.sh b/test/externalTests/bleeps.sh index df0e5e39e0..a4d1efa625 100755 --- a/test/externalTests/bleeps.sh +++ b/test/externalTests/bleeps.sh @@ -27,6 +27,7 @@ source test/externalTests/common.sh verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" +SELECTED_PRESETS="$3" function compile_fn { npm run compile; } function test_fn { npm run test; } diff --git a/test/externalTests/elementfi.sh b/test/externalTests/elementfi.sh index 7227ce37e2..f52a13ca67 100755 --- a/test/externalTests/elementfi.sh +++ b/test/externalTests/elementfi.sh @@ -27,6 +27,7 @@ source test/externalTests/common.sh verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" +SELECTED_PRESETS="$3" function compile_fn { npm run build; } function test_fn { npm run test; } diff --git a/test/externalTests/trident.sh b/test/externalTests/trident.sh index 26c3d38104..8e6f35ae33 100755 --- a/test/externalTests/trident.sh +++ b/test/externalTests/trident.sh @@ -27,6 +27,7 @@ source test/externalTests/common.sh verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" +SELECTED_PRESETS="$3" function compile_fn { yarn build; } diff --git a/test/externalTests/uniswap.sh b/test/externalTests/uniswap.sh index b3baad1a32..96a5d2b63b 100755 --- a/test/externalTests/uniswap.sh +++ b/test/externalTests/uniswap.sh @@ -27,6 +27,7 @@ source test/externalTests/common.sh verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" +SELECTED_PRESETS="$3" function compile_fn { yarn compile; } function test_fn { UPDATE_SNAPSHOT=1 npx hardhat test; } From 57800529d1f54daa5d5c961532362dd50a62405d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 1 Feb 2022 16:40:08 +0100 Subject: [PATCH 0219/1704] bleeps: Switch to the main branch --- test/externalTests/bleeps.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/externalTests/bleeps.sh b/test/externalTests/bleeps.sh index a4d1efa625..70f69d4603 100755 --- a/test/externalTests/bleeps.sh +++ b/test/externalTests/bleeps.sh @@ -35,8 +35,8 @@ function test_fn { npm run test; } function bleeps_test { local repo="https://github.com/wighawag/bleeps" - local ref_type=tag - local ref=bleeps_migrations # TODO: There's a 0.4.19 contract in 'main' that would need patching for the latest compiler. + local ref_type=branch + local ref=main local config_file="hardhat.config.ts" local config_var=config From e1a90b829e395d5356812d461322e465506c501e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 1 Feb 2022 16:40:28 +0100 Subject: [PATCH 0220/1704] bleeps: Patch WETH9.sol for 0.8.x --- test/externalTests/bleeps.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/externalTests/bleeps.sh b/test/externalTests/bleeps.sh index 70f69d4603..d005cf8efb 100755 --- a/test/externalTests/bleeps.sh +++ b/test/externalTests/bleeps.sh @@ -66,6 +66,12 @@ function bleeps_test pushd "contracts/" sed -i 's|"bleeps-common": "workspace:\*",|"bleeps-common": "file:../common-lib/",|g' package.json + sed -i 's/function() public/fallback() external/g' src/externals/WETH9.sol + sed -i 's/this\.balance/address(this).balance/g' src/externals/WETH9.sol + sed -i 's/uint(-1)/type(uint).max/g' src/externals/WETH9.sol + sed -i 's/msg\.sender\.transfer(/payable(msg.sender).transfer(/g' src/externals/WETH9.sol + sed -i 's/^\s*\(Deposit\|Withdrawal\|Approval\|Transfer\)(/emit \1(/g' src/externals/WETH9.sol + neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" From 1e0a695d241dcf430c485dfdfb1d9e2b454fdb7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 1 Feb 2022 17:01:10 +0100 Subject: [PATCH 0221/1704] Disable bleeps external test until it gets fixed upstream --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 143a692fdb..44b44bb012 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1468,7 +1468,8 @@ workflows: - t_ems_ext: *job_native_test_ext_trident - t_ems_ext: *job_native_test_ext_euler - t_ems_ext: *job_native_test_ext_yield_liquidator - - t_ems_ext: *job_native_test_ext_bleeps + # Disabled until we have a fix for https://github.com/wighawag/bleeps/issues/2 + #-t_ems_ext: *job_native_test_ext_bleeps - 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_uniswap From 9043621747de80cfb6b4a5e890f062d6e962d27d Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Fri, 28 Jan 2022 23:27:05 +0530 Subject: [PATCH 0222/1704] Changed occurences of isByteArray() to isByteArrayOrString(). The idea is to, in a future commit, replace such occurences of isByteArrayOrString() which are required to return True only for Bytes type with a new isByteArray() function. --- .../analysis/DeclarationTypeChecker.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 4 +- libsolidity/ast/Types.cpp | 26 ++++---- libsolidity/ast/Types.h | 8 +-- libsolidity/codegen/ABIFunctions.cpp | 24 +++---- libsolidity/codegen/ArrayUtils.cpp | 58 ++++++++-------- libsolidity/codegen/CompilerUtils.cpp | 12 ++-- libsolidity/codegen/ExpressionCompiler.cpp | 14 ++-- libsolidity/codegen/YulUtilFunctions.cpp | 66 +++++++++---------- libsolidity/codegen/ir/IRGenerator.cpp | 4 +- .../codegen/ir/IRGeneratorForStatements.cpp | 6 +- libsolidity/formal/SMTEncoder.cpp | 10 +-- libsolidity/formal/SymbolicTypes.cpp | 2 +- libsolidity/interface/ABI.cpp | 2 +- libsolidity/interface/StorageLayout.cpp | 2 +- 15 files changed, 120 insertions(+), 120 deletions(-) diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index 7a4aa99427..ba989972cb 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -441,7 +441,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable) { bool allowed = false; if (auto arrayType = dynamic_cast(type)) - allowed = arrayType->isByteArray(); + allowed = arrayType->isByteArrayOrString(); if (!allowed) m_errorReporter.fatalTypeError(9259_error, _variable.location(), "Only constants of value type and byte array type are implemented."); } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index f3ba2884b7..1a07d6ded0 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1783,7 +1783,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType( ( ( resultArrayType->isPointer() || - (argArrayType->isByteArray() && resultArrayType->isByteArray()) + (argArrayType->isByteArrayOrString() && resultArrayType->isByteArrayOrString()) ) && resultArrayType->location() == DataLocation::Storage ), @@ -1791,7 +1791,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType( ); else solAssert( - argArrayType->isByteArray() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes, + argArrayType->isByteArrayOrString() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes, "" ); } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index fb31a93030..f50210ff55 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1206,7 +1206,7 @@ BoolResult StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) ); return arrayType->location() != DataLocation::CallData && - arrayType->isByteArray() && + arrayType->isByteArrayOrString() && !(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer()); } else @@ -1530,7 +1530,7 @@ BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const if (_convertTo.category() != category()) return false; auto& convertTo = dynamic_cast(_convertTo); - if (convertTo.isByteArray() != isByteArray() || convertTo.isString() != isString()) + if (convertTo.isByteArrayOrString() != isByteArrayOrString() || convertTo.isString() != isString()) return false; // memory/calldata to storage can be converted, but only to a direct storage reference if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer()) @@ -1571,11 +1571,11 @@ BoolResult ArrayType::isExplicitlyConvertibleTo(Type const& _convertTo) const return true; // allow conversion bytes <-> string and bytes -> bytesNN if (_convertTo.category() != category()) - return isByteArray() && !isString() && _convertTo.category() == Type::Category::FixedBytes; + return isByteArrayOrString() && !isString() && _convertTo.category() == Type::Category::FixedBytes; auto& convertTo = dynamic_cast(_convertTo); if (convertTo.location() != location()) return false; - if (!isByteArray() || !convertTo.isByteArray()) + if (!isByteArrayOrString() || !convertTo.isByteArrayOrString()) return false; return true; } @@ -1585,7 +1585,7 @@ string ArrayType::richIdentifier() const string id; if (isString()) id = "t_string"; - else if (isByteArray()) + else if (isByteArrayOrString()) id = "t_bytes"; else { @@ -1608,7 +1608,7 @@ bool ArrayType::operator==(Type const& _other) const ArrayType const& other = dynamic_cast(_other); if ( !ReferenceType::operator==(other) || - other.isByteArray() != isByteArray() || + other.isByteArrayOrString() != isByteArrayOrString() || other.isString() != isString() || other.isDynamicallySized() != isDynamicallySized() ) @@ -1751,7 +1751,7 @@ string ArrayType::toString(bool _short) const string ret; if (isString()) ret = "string"; - else if (isByteArray()) + else if (isByteArrayOrString()) ret = "bytes"; else { @@ -1770,7 +1770,7 @@ string ArrayType::canonicalName() const string ret; if (isString()) ret = "string"; - else if (isByteArray()) + else if (isByteArrayOrString()) ret = "bytes"; else { @@ -1784,7 +1784,7 @@ string ArrayType::canonicalName() const string ArrayType::signatureInExternalFunction(bool _structsByName) const { - if (isByteArray()) + if (isByteArrayOrString()) return canonicalName(); else { @@ -1899,7 +1899,7 @@ u256 ArrayType::memoryDataSize() const { solAssert(!isDynamicallySized(), ""); solAssert(m_location == DataLocation::Memory, ""); - solAssert(!isByteArray(), ""); + solAssert(!isByteArrayOrString(), ""); bigint size = bigint(m_length) * m_baseType->memoryHeadSize(); solAssert(size <= numeric_limits::max(), "Array size does not fit u256."); return u256(size); @@ -2701,7 +2701,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): } else if (auto arrayType = dynamic_cast(returnType)) { - if (arrayType->isByteArray()) + if (arrayType->isByteArrayOrString()) // Return byte arrays as whole. break; returnType = arrayType->baseType(); @@ -2720,7 +2720,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): if (member.type->category() != Category::Mapping) { if (auto arrayType = dynamic_cast(member.type)) - if (!arrayType->isByteArray()) + if (!arrayType->isByteArrayOrString()) continue; m_returnParameterTypes.push_back(TypeProvider::withLocationIfReference( DataLocation::Memory, @@ -3813,7 +3813,7 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons } else if ( auto const* arrayType = dynamic_cast(m_actualType); - arrayType && arrayType->isByteArray() + arrayType && arrayType->isByteArrayOrString() ) members.emplace_back("concat", TypeProvider::function( TypePointers{}, diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index f15da58ab3..e34c114057 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -838,7 +838,7 @@ class ArrayType: public ReferenceType BoolResult validForLocation(DataLocation _loc) const override; /// @returns true if this is a byte array or a string - bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; } + bool isByteArrayOrString() const { return m_arrayKind != ArrayKind::Ordinary; } /// @returns true if this is a string bool isString() const { return m_arrayKind == ArrayKind::String; } Type const* baseType() const { solAssert(!!m_baseType, ""); return m_baseType; } @@ -849,11 +849,11 @@ class ArrayType: public ReferenceType std::unique_ptr copyForLocation(DataLocation _location, bool _isPointer) const override; /// The offset to advance in calldata to move from one array element to the next. - unsigned calldataStride() const { return isByteArray() ? 1 : m_baseType->calldataHeadSize(); } + unsigned calldataStride() const { return isByteArrayOrString() ? 1 : m_baseType->calldataHeadSize(); } /// The offset to advance in memory to move from one array element to the next. - unsigned memoryStride() const { return isByteArray() ? 1 : m_baseType->memoryHeadSize(); } + unsigned memoryStride() const { return isByteArrayOrString() ? 1 : m_baseType->memoryHeadSize(); } /// The offset to advance in storage to move from one array element to the next. - unsigned storageStride() const { return isByteArray() ? 1 : m_baseType->storageBytes(); } + unsigned storageStride() const { return isByteArrayOrString() ? 1 : m_baseType->storageBytes(); } void clearCache() const override; diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 97cf3425db..65f9e1723a 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -312,7 +312,7 @@ string ABIFunctions::abiEncodingFunction( { case DataLocation::CallData: if ( - fromArray->isByteArray() || + fromArray->isByteArrayOrString() || *fromArray->baseType() == *TypeProvider::uint256() || *fromArray->baseType() == FixedBytesType(32) ) @@ -320,7 +320,7 @@ string ABIFunctions::abiEncodingFunction( else return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options); case DataLocation::Memory: - if (fromArray->isByteArray()) + if (fromArray->isByteArrayOrString()) return abiEncodingFunctionMemoryByteArray(*fromArray, *toArray, _options); else return abiEncodingFunctionSimpleArray(*fromArray, *toArray, _options); @@ -448,7 +448,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( solAssert(fromArrayType.location() == DataLocation::CallData, ""); solAssert( - fromArrayType.isByteArray() || + fromArrayType.isByteArrayOrString() || *fromArrayType.baseType() == *TypeProvider::uint256() || *fromArrayType.baseType() == FixedBytesType(32), "" @@ -468,7 +468,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( _to.identifier() + _options.toFunctionNameSuffix(); return createFunction(functionName, [&]() { - bool needsPadding = _options.padded && fromArrayType.isByteArray(); + bool needsPadding = _options.padded && fromArrayType.isByteArrayOrString(); if (fromArrayType.isDynamicallySized()) { Whiskers templ(R"( @@ -482,7 +482,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( )"); templ("storeLength", arrayStoreLengthForEncodingFunction(toArrayType, _options)); templ("functionName", functionName); - if (fromArrayType.isByteArray() || fromArrayType.calldataStride() == 1) + if (fromArrayType.isByteArrayOrString() || fromArrayType.calldataStride() == 1) templ("scaleLengthByStride", ""); else templ("scaleLengthByStride", @@ -536,7 +536,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), ""); solAssert(_from.length() == _to.length(), ""); - solAssert(!_from.isByteArray(), ""); + solAssert(!_from.isByteArrayOrString(), ""); if (_from.dataStoredIn(DataLocation::Storage)) solAssert(_from.baseType()->storageBytes() > 16, ""); @@ -647,10 +647,10 @@ string ABIFunctions::abiEncodingFunctionMemoryByteArray( solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), ""); solAssert(_from.length() == _to.length(), ""); solAssert(_from.dataStoredIn(DataLocation::Memory), ""); - solAssert(_from.isByteArray(), ""); + solAssert(_from.isByteArrayOrString(), ""); return createFunction(functionName, [&]() { - solAssert(_to.isByteArray(), ""); + solAssert(_to.isByteArrayOrString(), ""); Whiskers templ(R"( function (value, pos) -> end { let length := (value) @@ -686,9 +686,9 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( solAssert(_from.dataStoredIn(DataLocation::Storage), ""); return createFunction(functionName, [&]() { - if (_from.isByteArray()) + if (_from.isByteArrayOrString()) { - solAssert(_to.isByteArray(), ""); + solAssert(_to.isByteArrayOrString(), ""); Whiskers templ(R"( // -> function (value, pos) -> ret { @@ -1168,7 +1168,7 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory) { solAssert(_type.dataStoredIn(DataLocation::Memory), ""); - if (_type.isByteArray()) + if (_type.isByteArrayOrString()) return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory); solAssert(_type.calldataStride() > 0, ""); @@ -1275,7 +1275,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory) { solAssert(_type.dataStoredIn(DataLocation::Memory), ""); - solAssert(_type.isByteArray(), ""); + solAssert(_type.isByteArrayOrString(), ""); string functionName = "abi_decode_available_length_" + diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 27afe14985..d2691c8779 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -50,8 +50,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons solAssert(_targetType.location() == DataLocation::Storage, ""); Type const* uint256 = TypeProvider::uint256(); - Type const* targetBaseType = _targetType.isByteArray() ? uint256 : _targetType.baseType(); - Type const* sourceBaseType = _sourceType.isByteArray() ? uint256 : _sourceType.baseType(); + Type const* targetBaseType = _targetType.isByteArrayOrString() ? uint256 : _targetType.baseType(); + Type const* sourceBaseType = _sourceType.isByteArrayOrString() ? uint256 : _sourceType.baseType(); // TODO unroll loop for small sizes @@ -97,7 +97,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons // stack: target_ref source_ref source_length target_ref target_length if (_targetType.isDynamicallySized()) // store new target length - if (!_targetType.isByteArray()) + if (!_targetType.isByteArrayOrString()) // Otherwise, length will be stored below. _context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE; if (sourceBaseType->category() == Type::Category::Mapping) @@ -126,7 +126,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons evmasm::AssemblyItem copyLoopEndWithoutByteOffset = _context.newTag(); // special case for short byte arrays: Store them together with their length. - if (_targetType.isByteArray()) + if (_targetType.isByteArrayOrString()) { // stack: target_ref target_data_end source_length target_data_pos source_ref _context << Instruction::DUP3; @@ -141,7 +141,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons _context << Instruction::DUP3 << u256(31) << Instruction::LT; evmasm::AssemblyItem longByteArray = _context.appendConditionalJump(); // store the short byte array - solAssert(_sourceType.isByteArray(), ""); + solAssert(_sourceType.isByteArrayOrString(), ""); if (_sourceType.location() == DataLocation::Storage) { // just copy the slot, it contains length and data @@ -323,7 +323,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord { if (!_sourceType.isDynamicallySized()) m_context << _sourceType.length(); - if (!_sourceType.isByteArray()) + if (!_sourceType.isByteArrayOrString()) convertLengthToSize(_sourceType); string routine = "calldatacopy(target, source, len)\n"; @@ -375,14 +375,14 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord m_context << Instruction::SWAP1 << u256(32) << Instruction::ADD; m_context << Instruction::SWAP1; } - if (!_sourceType.isByteArray()) + if (!_sourceType.isByteArrayOrString()) convertLengthToSize(_sourceType); // stack: m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4; // We can resort to copying full 32 bytes only if // - the length is known to be a multiple of 32 or // - we will pad to full 32 bytes later anyway. - if (!_sourceType.isByteArray() || _padToWordBoundaries) + if (!_sourceType.isByteArrayOrString() || _padToWordBoundaries) utils.memoryCopy32(); else utils.memoryCopy(); @@ -390,7 +390,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord m_context << Instruction::SWAP1 << Instruction::POP; // stack: - bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArray(); + bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArrayOrString(); if (paddingNeeded) { @@ -446,7 +446,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord m_context << Instruction::DUP1 << Instruction::ISZERO; evmasm::AssemblyItem loopEnd = m_context.appendConditionalJump(); // Special case for tightly-stored byte arrays - if (_sourceType.isByteArray()) + if (_sourceType.isByteArrayOrString()) { // stack here: memory_offset storage_offset length m_context << Instruction::DUP1 << u256(31) << Instruction::LT; @@ -482,14 +482,14 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord } // stack here: memory_end_offset storage_data_offset memory_offset - bool haveByteOffset = !_sourceType.isByteArray() && storageBytes <= 16; + bool haveByteOffset = !_sourceType.isByteArrayOrString() && storageBytes <= 16; if (haveByteOffset) m_context << u256(0) << Instruction::SWAP1; // stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset evmasm::AssemblyItem loopStart = m_context.newTag(); m_context << loopStart; // load and store - if (_sourceType.isByteArray()) + if (_sourceType.isByteArrayOrString()) { // Packed both in storage and memory. m_context << Instruction::DUP2 << Instruction::SLOAD; @@ -528,12 +528,12 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord // stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset if (haveByteOffset) m_context << Instruction::SWAP1 << Instruction::POP; - if (!_sourceType.isByteArray()) + if (!_sourceType.isByteArrayOrString()) { solAssert(_sourceType.calldataStride() % 32 == 0, ""); solAssert(_sourceType.memoryStride() % 32 == 0, ""); } - if (_padToWordBoundaries && _sourceType.isByteArray()) + if (_padToWordBoundaries && _sourceType.isByteArrayOrString()) { // memory_end_offset - start is the actual length (we want to compute the ceil of). // memory_offset - start is its next multiple of 32, but it might be off by 32. @@ -624,7 +624,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const m_context << u256(0) << Instruction::DUP3 << Instruction::SSTORE; // Special case: short byte arrays are stored togeher with their length evmasm::AssemblyItem endTag = m_context.newTag(); - if (_type.isByteArray()) + if (_type.isByteArrayOrString()) { // stack: ref old_length m_context << Instruction::DUP1 << u256(31) << Instruction::LT; @@ -664,7 +664,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const ArrayType const& _type = dynamic_cast(*type); solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.isDynamicallySized(), ""); - if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32) + if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32) solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); unsigned stackHeightStart = _context.stackHeight(); @@ -677,7 +677,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "2"); // Special case for short byte arrays, they are stored together with their length - if (_type.isByteArray()) + if (_type.isByteArrayOrString()) { evmasm::AssemblyItem regularPath = _context.newTag(); // We start by a large case-distinction about the old and new length of the byte array. @@ -766,7 +766,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const // stack: ref new_length old_length // store new length _context << Instruction::DUP2; - if (_type.isByteArray()) + if (_type.isByteArrayOrString()) // For a "long" byte array, store length as 2*length+1 _context << Instruction::DUP1 << Instruction::ADD << u256(1) << Instruction::ADD; _context << Instruction::DUP4 << Instruction::SSTORE; @@ -806,10 +806,10 @@ void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const { solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.isDynamicallySized(), ""); - if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32) + if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32) solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); - if (_type.isByteArray()) + if (_type.isByteArrayOrString()) { // We almost always just add 2 (length of byte arrays is shifted left by one) // except for the case where we transition from a short byte array @@ -850,10 +850,10 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const { solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.isDynamicallySized(), ""); - if (!_type.isByteArray() && _type.baseType()->storageBytes() < 32) + if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32) solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); - if (_type.isByteArray()) + if (_type.isByteArrayOrString()) { m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1; m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1); @@ -999,7 +999,7 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con } else { - if (!_arrayType.isByteArray()) + if (!_arrayType.isByteArrayOrString()) { if (_arrayType.location() == DataLocation::Memory) m_context << _arrayType.memoryStride(); @@ -1031,7 +1031,7 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType, unsigned _stackDept break; case DataLocation::Storage: m_context << Instruction::SLOAD; - if (_arrayType.isByteArray()) + if (_arrayType.isByteArrayOrString()) m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1); break; } @@ -1062,7 +1062,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b { case DataLocation::Memory: // stack: - if (!_arrayType.isByteArray()) + if (!_arrayType.isByteArrayOrString()) m_context << u256(_arrayType.memoryHeadSize()) << Instruction::MUL; if (_arrayType.isDynamicallySized()) m_context << u256(32) << Instruction::ADD; @@ -1071,7 +1071,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b m_context << Instruction::ADD; break; case DataLocation::CallData: - if (!_arrayType.isByteArray()) + if (!_arrayType.isByteArrayOrString()) { m_context << _arrayType.calldataStride(); m_context << Instruction::MUL; @@ -1090,7 +1090,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b // stack: [] evmasm::AssemblyItem endTag = m_context.newTag(); - if (_arrayType.isByteArray()) + if (_arrayType.isByteArrayOrString()) { // Special case of short byte arrays. m_context << Instruction::SWAP1; @@ -1153,7 +1153,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d { solAssert(_arrayType.baseType()->storageBytes() <= 32, ""); if ( - !_arrayType.isByteArray() && + !_arrayType.isByteArrayOrString() && _arrayType.baseType()->storageBytes() < 32 && m_context.useABICoderV2() ) @@ -1165,7 +1165,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d CompilerUtils(m_context).loadFromMemoryDynamic( *_arrayType.baseType(), true, - !_arrayType.isByteArray(), + !_arrayType.isByteArrayOrString(), false ); } diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 1876b6ac06..ba678878f2 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -970,7 +970,7 @@ void CompilerUtils::convertType( else if (targetTypeCategory == Type::Category::Array) { auto const& arrayType = dynamic_cast(_targetType); - solAssert(arrayType.isByteArray()); + solAssert(arrayType.isByteArrayOrString()); size_t storageSize = 32 + ((data.size() + 31) / 32) * 32; allocateMemory(storageSize); // stack: mempos @@ -992,7 +992,7 @@ void CompilerUtils::convertType( if (_targetType.category() == Type::Category::FixedBytes) { solAssert( - typeOnStack.isByteArray() && !typeOnStack.isString(), + typeOnStack.isByteArrayOrString() && !typeOnStack.isString(), "Array types other than bytes not convertible to bytesNN." ); solAssert(typeOnStack.isDynamicallySized()); @@ -1019,7 +1019,7 @@ void CompilerUtils::convertType( case DataLocation::Storage: // Other cases are done explicitly in LValue::storeValue, and only possible by assignment. solAssert( - (targetType.isPointer() || (typeOnStack.isByteArray() && targetType.isByteArray())) && + (targetType.isPointer() || (typeOnStack.isByteArrayOrString() && targetType.isByteArrayOrString())) && typeOnStack.location() == DataLocation::Storage, "Invalid conversion to storage type." ); @@ -1105,7 +1105,7 @@ void CompilerUtils::convertType( } case DataLocation::CallData: solAssert( - ((targetType.isByteArray() && typeOnStack.isByteArray()) || _typeOnStack == _targetType) && + ((targetType.isByteArrayOrString() && typeOnStack.isByteArrayOrString()) || _typeOnStack == _targetType) && typeOnStack.location() == DataLocation::CallData, "Invalid conversion to calldata type." ); @@ -1119,7 +1119,7 @@ void CompilerUtils::convertType( if (_targetType.category() == Type::Category::FixedBytes) { solAssert( - typeOnStack.arrayType().isByteArray() && !typeOnStack.arrayType().isString(), + typeOnStack.arrayType().isByteArrayOrString() && !typeOnStack.arrayType().isString(), "Array types other than bytes not convertible to bytesNN." ); solAssert(typeOnStack.isDynamicallySized()); @@ -1142,7 +1142,7 @@ void CompilerUtils::convertType( auto const& targetArrayType = dynamic_cast(_targetType); solAssert( typeOnStack.arrayType().isImplicitlyConvertibleTo(targetArrayType) || - (typeOnStack.arrayType().isByteArray() && targetArrayType.isByteArray()) + (typeOnStack.arrayType().isByteArrayOrString() && targetArrayType.isByteArrayOrString()) ); solAssert( typeOnStack.arrayType().dataStoredIn(DataLocation::CallData) && diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index a76d1f3d9b..da3022251f 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -153,7 +153,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& if (paramTypes[i]->isDynamicallySized()) { solAssert( - dynamic_cast(*paramTypes[i]).isByteArray(), + dynamic_cast(*paramTypes[i]).isByteArrayOrString(), "Expected string or byte array for mapping key type" ); @@ -239,7 +239,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& if (returnTypes[i]->category() == Type::Category::Mapping) continue; if (auto arrayType = dynamic_cast(returnTypes[i])) - if (!arrayType->isByteArray()) + if (!arrayType->isByteArrayOrString()) continue; pair const& offsets = structType->storageOffsetsOfMember(names[i]); m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second); @@ -1047,7 +1047,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // stack: ArrayReference (newLength-1) ArrayUtils(m_context).accessIndex(*arrayType, false); - if (arrayType->isByteArray()) + if (arrayType->isByteArrayOrString()) setLValue(_functionCall); else setLValueToStorageItem(_functionCall); @@ -1084,7 +1084,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().moveToStackTop(1 + type->sizeOnStack()); utils().moveToStackTop(1 + type->sizeOnStack()); // stack: argValue storageSlot slotOffset - if (!arrayType->isByteArray()) + if (!arrayType->isByteArrayOrString()) StorageItem(m_context, *paramType).storeValue(*type, _functionCall.location(), true); else StorageByteArrayElement(m_context).storeValue(*type, _functionCall.location(), true); @@ -1165,7 +1165,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // update free memory pointer m_context << Instruction::DUP1; // Stack: memptr requested_length requested_length - if (arrayType.isByteArray()) + if (arrayType.isByteArrayOrString()) // Round up to multiple of 32 m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND; else @@ -2086,7 +2086,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) { case DataLocation::Storage: ArrayUtils(m_context).accessIndex(arrayType); - if (arrayType.isByteArray()) + if (arrayType.isByteArrayOrString()) { solAssert(!arrayType.isString(), "Index access to string is not allowed."); setLValue(_indexAccess); @@ -2096,7 +2096,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) break; case DataLocation::Memory: ArrayUtils(m_context).accessIndex(arrayType); - setLValue(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArray()); + setLValue(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArrayOrString()); break; case DataLocation::CallData: ArrayUtils(m_context).accessCallDataArrayElement(arrayType); diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 84f63a9e15..3c79b64b46 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1183,8 +1183,8 @@ string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type) w("calldata", _type.location() == DataLocation::CallData); if (_type.location() == DataLocation::Storage) { - w("byteArray", _type.isByteArray()); - if (_type.isByteArray()) + w("byteArray", _type.isByteArrayOrString()); + if (_type.isByteArrayOrString()) w("extractByteArrayLength", extractByteArrayLengthFunction()); } @@ -1220,7 +1220,7 @@ std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type) solAssert(_type.location() == DataLocation::Storage, ""); solUnimplementedAssert(_type.baseType()->storageBytes() <= 32); - if (_type.isByteArray()) + if (_type.isByteArrayOrString()) return resizeDynamicByteArrayFunction(_type); string functionName = "resize_array_" + _type.identifier(); @@ -1259,7 +1259,7 @@ string YulUtilFunctions::cleanUpStorageArrayEndFunction(ArrayType const& _type) { solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.baseType()->category() != Type::Category::Mapping, ""); - solAssert(!_type.isByteArray(), ""); + solAssert(!_type.isByteArrayOrString(), ""); solUnimplementedAssert(_type.baseType()->storageBytes() <= 32); string functionName = "cleanup_storage_array_end_" + _type.identifier(); @@ -1319,7 +1319,7 @@ string YulUtilFunctions::resizeDynamicByteArrayFunction(ArrayType const& _type) string YulUtilFunctions::cleanUpDynamicByteArrayEndSlotsFunction(ArrayType const& _type) { - solAssert(_type.isByteArray(), ""); + solAssert(_type.isByteArrayOrString(), ""); solAssert(_type.isDynamicallySized(), ""); string functionName = "clean_up_bytearray_end_slots_" + _type.identifier(); @@ -1479,7 +1479,7 @@ string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type) solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.isDynamicallySized(), ""); solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented."); - if (_type.isByteArray()) + if (_type.isByteArrayOrString()) return storageByteArrayPopFunction(_type); string functionName = "array_pop_" + _type.identifier(); @@ -1509,7 +1509,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type) { solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.isDynamicallySized(), ""); - solAssert(_type.isByteArray(), ""); + solAssert(_type.isByteArrayOrString(), ""); string functionName = "byte_array_pop_" + _type.identifier(); return m_functionCollector.createFunction(functionName, [&]() { @@ -1566,7 +1566,7 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c return m_functionCollector.createFunction(functionName, [&]() { return Whiskers(R"( function (array ) { - + let data := sload(array) let oldLen := (data) if iszero(lt(oldLen, )) { () } @@ -1598,20 +1598,20 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c let slot, offset := (array, oldLen) (slot, offset ) } - + let oldLen := sload(array) if iszero(lt(oldLen, )) { () } sstore(array, add(oldLen, 1)) let slot, offset := (array, oldLen) (slot, offset ) - + })") ("functionName", functionName) ("values", _fromType->sizeOnStack() == 0 ? "" : ", " + suffixedVariableNameList("value", 0, _fromType->sizeOnStack())) ("panic", panicFunction(PanicCode::ResourceError)) - ("extractByteArrayLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "") + ("extractByteArrayLength", _type.isByteArrayOrString() ? extractByteArrayLengthFunction() : "") ("dataAreaFunction", arrayDataAreaFunction(_type)) - ("isByteArray", _type.isByteArray()) + ("isByteArrayOrString", _type.isByteArrayOrString()) ("indexAccess", storageArrayIndexAccessFunction(_type)) ("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType())) ("maxArrayLength", (u256(1) << 64).str()) @@ -1642,9 +1642,9 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type) slot, offset := (array, oldLen) })") ("functionName", functionName) - ("isBytes", _type.isByteArray()) - ("increaseBytesSize", _type.isByteArray() ? increaseByteArraySizeFunction(_type) : "") - ("extractLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "") + ("isBytes", _type.isByteArrayOrString()) + ("increaseBytesSize", _type.isByteArrayOrString() ? increaseByteArraySizeFunction(_type) : "") + ("extractLength", _type.isByteArrayOrString() ? extractByteArrayLengthFunction() : "") ("panic", panicFunction(PanicCode::ResourceError)) ("fetchLength", arrayLengthFunction(_type)) ("indexAccess", storageArrayIndexAccessFunction(_type)) @@ -1795,7 +1795,7 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, if (!_toType.isDynamicallySized()) solAssert(!_fromType.isDynamicallySized() && _fromType.length() <= _toType.length(), ""); - if (_fromType.isByteArray()) + if (_fromType.isByteArrayOrString()) return copyByteArrayToStorageFunction(_fromType, _toType); if (_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType()) return copyValueArrayStorageToStorageFunction(_fromType, _toType); @@ -1902,8 +1902,8 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy *_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast(_toType), "" ); - solAssert(_fromType.isByteArray(), ""); - solAssert(_toType.isByteArray(), ""); + solAssert(_fromType.isByteArrayOrString(), ""); + solAssert(_toType.isByteArrayOrString(), ""); string functionName = "copy_byte_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier(); return m_functionCollector.createFunction(functionName, [&](){ @@ -1980,8 +1980,8 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& solAssert(_toType.baseType()->isValueType(), ""); solAssert(_fromType.baseType()->isImplicitlyConvertibleTo(*_toType.baseType()), ""); - solAssert(!_fromType.isByteArray(), ""); - solAssert(!_toType.isByteArray(), ""); + solAssert(!_fromType.isByteArrayOrString(), ""); + solAssert(!_toType.isByteArrayOrString(), ""); solAssert(_fromType.dataStoredIn(DataLocation::Storage), ""); solAssert(_toType.dataStoredIn(DataLocation::Storage), ""); @@ -2155,7 +2155,7 @@ string YulUtilFunctions::arrayConvertLengthToSize(ArrayType const& _type) })") ("functionName", functionName) ("stride", to_string(_type.location() == DataLocation::Memory ? _type.memoryStride() : _type.calldataStride())) - ("byteArray", _type.isByteArray()) + ("byteArray", _type.isByteArrayOrString()) ("mul", overflowCheckedIntMulFunction(*TypeProvider::uint256())) .render(); default: @@ -2187,7 +2187,7 @@ string YulUtilFunctions::arrayAllocationSizeFunction(ArrayType const& _type) )"); w("functionName", functionName); w("panic", panicFunction(PanicCode::ResourceError)); - w("byteArray", _type.isByteArray()); + w("byteArray", _type.isByteArrayOrString()); w("roundUp", roundUpFunction()); w("dynamic", _type.isDynamicallySized()); return w.render(); @@ -2262,7 +2262,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type) ("dataAreaFunc", arrayDataAreaFunction(_type)) ("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction()) ("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16) - ("isBytesArray", _type.isByteArray()) + ("isBytesArray", _type.isByteArrayOrString()) ("storageSize", _type.baseType()->storageSize().str()) ("storageBytes", toString(_type.baseType()->storageBytes())) ("itemsPerSlot", to_string(32 / _type.baseType()->storageBytes())) @@ -2376,7 +2376,7 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type) string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type) { - solAssert(!_type.isByteArray(), ""); + solAssert(!_type.isByteArrayOrString(), ""); if (_type.dataStoredIn(DataLocation::Storage)) solAssert(_type.baseType()->storageBytes() > 16, ""); string functionName = "array_nextElement_" + _type.identifier(); @@ -2447,7 +2447,7 @@ string YulUtilFunctions::copyArrayFromStorageToMemoryFunction(ArrayType const& _ solAssert(_to.memoryStride() == 32, ""); solAssert(_to.baseType()->dataStoredIn(DataLocation::Memory), ""); solAssert(_from.baseType()->dataStoredIn(DataLocation::Storage), ""); - solAssert(!_from.isByteArray(), ""); + solAssert(!_from.isByteArrayOrString(), ""); solAssert(*_to.withLocation(DataLocation::Storage, _from.isPointer()) == _from, ""); return Whiskers(R"( function (slot) -> memPtr { @@ -2755,7 +2755,7 @@ string YulUtilFunctions::updateStorageValueFunction( solAssert(_fromType.category() == Type::Category::StringLiteral, ""); solAssert(toReferenceType->category() == Type::Category::Array, ""); auto const& toArrayType = dynamic_cast(*toReferenceType); - solAssert(toArrayType.isByteArray(), ""); + solAssert(toArrayType.isByteArrayOrString(), ""); return Whiskers(R"( function (slot, offset) { @@ -3216,7 +3216,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) auto const& fromType = dynamic_cast(_from); if (_to.category() == Type::Category::FixedBytes) { - solAssert(fromType.arrayType().isByteArray(), "Array types other than bytes not convertible to bytesNN."); + solAssert(fromType.arrayType().isByteArrayOrString(), "Array types other than bytes not convertible to bytesNN."); return bytesToFixedBytesConversionFunction(fromType.arrayType(), dynamic_cast(_to)); } solAssert(_to.category() == Type::Category::Array); @@ -3224,7 +3224,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) solAssert( fromType.arrayType().isImplicitlyConvertibleTo(targetType) || - (fromType.arrayType().isByteArray() && targetType.isByteArray()) + (fromType.arrayType().isByteArrayOrString() && targetType.isByteArrayOrString()) ); solAssert( fromType.arrayType().dataStoredIn(DataLocation::CallData) && @@ -3256,7 +3256,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) auto const& fromArrayType = dynamic_cast(_from); if (_to.category() == Type::Category::FixedBytes) { - solAssert(fromArrayType.isByteArray(), "Array types other than bytes not convertible to bytesNN."); + solAssert(fromArrayType.isByteArrayOrString(), "Array types other than bytes not convertible to bytesNN."); return bytesToFixedBytesConversionFunction(fromArrayType, dynamic_cast(_to)); } solAssert(_to.category() == Type::Category::Array, ""); @@ -3460,7 +3460,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) string YulUtilFunctions::bytesToFixedBytesConversionFunction(ArrayType const& _from, FixedBytesType const& _to) { - solAssert(_from.isByteArray() && !_from.isString(), ""); + solAssert(_from.isByteArrayOrString() && !_from.isString(), ""); solAssert(_from.isDynamicallySized(), ""); string functionName = "convert_bytes_to_fixedbytes_from_" + _from.identifier() + "_to_" + _to.identifier(); return m_functionCollector.createFunction(functionName, [&](auto& _args, auto& _returnParams) { @@ -3633,14 +3633,14 @@ string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayTy { if (_to.dataStoredIn(DataLocation::CallData)) solAssert( - _from.dataStoredIn(DataLocation::CallData) && _from.isByteArray() && _to.isByteArray(), + _from.dataStoredIn(DataLocation::CallData) && _from.isByteArrayOrString() && _to.isByteArrayOrString(), "" ); // Other cases are done explicitly in LValue::storeValue, and only possible by assignment. if (_to.location() == DataLocation::Storage) solAssert( - (_to.isPointer() || (_from.isByteArray() && _to.isByteArray())) && + (_to.isPointer() || (_from.isByteArrayOrString() && _to.isByteArrayOrString())) && _from.location() == DataLocation::Storage, "Invalid conversion to storage type." ); @@ -4238,7 +4238,7 @@ string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const } else if (_to.category() == Type::Category::Array) { - solAssert(dynamic_cast(_to).isByteArray(), ""); + solAssert(dynamic_cast(_to).isByteArrayOrString(), ""); Whiskers templ(R"( function () -> converted { converted := () diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index c2bb0c3cf3..e361ada473 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -677,7 +677,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) continue; if ( auto const* arrayType = dynamic_cast(returnTypes[i]); - arrayType && !arrayType->isByteArray() + arrayType && !arrayType->isByteArrayOrString() ) continue; @@ -698,7 +698,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) solAssert(returnTypes.size() == 1, ""); auto const* arrayType = dynamic_cast(returnTypes.front()); if (arrayType) - solAssert(arrayType->isByteArray(), ""); + solAssert(arrayType->isByteArrayOrString(), ""); vector retVars = IRVariable("ret", *returnTypes.front()).stackSlots(); returnVariables += retVars; code += Whiskers(R"( diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 86d00dbc9c..065b351f61 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2088,7 +2088,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) else if (dynamic_cast(&actualType)) solAssert(member == "wrap" || member == "unwrap"); else if (auto const* arrayType = dynamic_cast(&actualType)) - solAssert(arrayType->isByteArray() && member == "concat"); + solAssert(arrayType->isByteArrayOrString() && member == "concat"); else // The old code generator had a generic "else" case here // without any specific code being generated, @@ -2226,7 +2226,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) setLValue(_indexAccess, IRLValue{ *arrayType.baseType(), - IRLValue::Memory{memAddress, arrayType.isByteArray()} + IRLValue::Memory{memAddress, arrayType.isByteArrayOrString()} }); break; } @@ -2240,7 +2240,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) ", " + expressionAsType(*_indexAccess.indexExpression(), *TypeProvider::uint256()) + ")"; - if (arrayType.isByteArray()) + if (arrayType.isByteArrayOrString()) define(_indexAccess) << m_utils.cleanupFunction(*arrayType.baseType()) << "(calldataload(" << diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index b42e9b3557..76342ba08e 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -953,7 +953,7 @@ bool isReturnedFromStructGetter(Type const* _type) if (category == Type::Category::Mapping) return false; if (category == Type::Category::Array) - return dynamic_cast(*_type).isByteArray(); + return dynamic_cast(*_type).isByteArrayOrString(); // default return true; } @@ -990,7 +990,7 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall) { if ( type->isValueType() || - (type->category() == Type::Category::Array && dynamic_cast(*type).isByteArray()) + (type->category() == Type::Category::Array && dynamic_cast(*type).isByteArrayOrString()) ) { solAssert(symbArguments.empty(), ""); @@ -1071,7 +1071,7 @@ void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall) if (auto sliceType = dynamic_cast(argType)) arrayType = &sliceType->arrayType(); - if (arrayType && arrayType->isByteArray() && smt::isFixedBytes(*funCallType)) + if (arrayType && arrayType->isByteArrayOrString() && smt::isFixedBytes(*funCallType)) { auto array = dynamic_pointer_cast(m_context.expression(*argument)); bytesToFixedBytesAssertions(*array, _funCall); @@ -2695,14 +2695,14 @@ Expression const* SMTEncoder::cleanExpression(Expression const& _expr) auto typeType = dynamic_cast(functionCall->expression().annotation().type); solAssert(typeType, ""); if (auto const* arrayType = dynamic_cast(typeType->actualType())) - if (arrayType->isByteArray()) + if (arrayType->isByteArrayOrString()) { // this is a cast to `bytes` solAssert(functionCall->arguments().size() == 1, ""); Expression const& arg = *functionCall->arguments()[0]; if ( auto const* argArrayType = dynamic_cast(arg.annotation().type); - argArrayType && argArrayType->isByteArray() + argArrayType && argArrayType->isByteArrayOrString() ) return cleanExpression(arg); } diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 36d9a0f353..024e33be6e 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -96,7 +96,7 @@ SortPointer smtSort(frontend::Type const& _type) auto sliceArrayType = dynamic_cast(&_type); ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast(&_type); if ( - (arrayType && (arrayType->isString() || arrayType->isByteArray())) || + (arrayType && (arrayType->isString() || arrayType->isByteArrayOrString())) || _type.category() == frontend::Type::Category::StringLiteral ) tupleName = "bytes"; diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index cf395ffa02..9c7a645b6f 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -176,7 +176,7 @@ Json::Value ABI::formatType( ret["type"] = _encodingType.canonicalName() + suffix; else if (ArrayType const* arrayType = dynamic_cast(&_encodingType)) { - if (arrayType->isByteArray()) + if (arrayType->isByteArrayOrString()) ret["type"] = _encodingType.canonicalName() + suffix; else { diff --git a/libsolidity/interface/StorageLayout.cpp b/libsolidity/interface/StorageLayout.cpp index a484503c11..74d7ccf4bb 100644 --- a/libsolidity/interface/StorageLayout.cpp +++ b/libsolidity/interface/StorageLayout.cpp @@ -94,7 +94,7 @@ void StorageLayout::generate(Type const* _type) } else if (auto arrayType = dynamic_cast(_type)) { - if (arrayType->isByteArray()) + if (arrayType->isByteArrayOrString()) typeInfo["encoding"] = "bytes"; else { From cc6344c03c2b9c00a76bc2af1d9f1da7aa9c467b Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Wed, 2 Feb 2022 16:14:24 +0530 Subject: [PATCH 0223/1704] Changed instaces of isByteArrayOrString() to isByteArray() where it's only supposed to return a True for Bytes Type --- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/ast/Types.cpp | 6 +++--- libsolidity/ast/Types.h | 2 ++ libsolidity/codegen/CompilerUtils.cpp | 4 ++-- libsolidity/codegen/YulUtilFunctions.cpp | 6 +++--- libsolidity/formal/SymbolicTypes.cpp | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 1a07d6ded0..5b03717d9d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1791,7 +1791,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType( ); else solAssert( - argArrayType->isByteArrayOrString() && !argArrayType->isString() && resultType->category() == Type::Category::FixedBytes, + argArrayType->isByteArray() && resultType->category() == Type::Category::FixedBytes, "" ); } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index f50210ff55..74cd76ee73 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1530,7 +1530,7 @@ BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const if (_convertTo.category() != category()) return false; auto& convertTo = dynamic_cast(_convertTo); - if (convertTo.isByteArrayOrString() != isByteArrayOrString() || convertTo.isString() != isString()) + if (convertTo.isByteArray() != isByteArray() || convertTo.isString() != isString()) return false; // memory/calldata to storage can be converted, but only to a direct storage reference if (convertTo.location() == DataLocation::Storage && location() != DataLocation::Storage && convertTo.isPointer()) @@ -1571,7 +1571,7 @@ BoolResult ArrayType::isExplicitlyConvertibleTo(Type const& _convertTo) const return true; // allow conversion bytes <-> string and bytes -> bytesNN if (_convertTo.category() != category()) - return isByteArrayOrString() && !isString() && _convertTo.category() == Type::Category::FixedBytes; + return isByteArray() && _convertTo.category() == Type::Category::FixedBytes; auto& convertTo = dynamic_cast(_convertTo); if (convertTo.location() != location()) return false; @@ -1608,7 +1608,7 @@ bool ArrayType::operator==(Type const& _other) const ArrayType const& other = dynamic_cast(_other); if ( !ReferenceType::operator==(other) || - other.isByteArrayOrString() != isByteArrayOrString() || + other.isByteArray() != isByteArray() || other.isString() != isString() || other.isDynamicallySized() != isDynamicallySized() ) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index e34c114057..3f134df17d 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -837,6 +837,8 @@ class ArrayType: public ReferenceType BoolResult validForLocation(DataLocation _loc) const override; + /// @returns true if this is a byte array. + bool isByteArray() const { return m_arrayKind == ArrayKind::Bytes; } /// @returns true if this is a byte array or a string bool isByteArrayOrString() const { return m_arrayKind != ArrayKind::Ordinary; } /// @returns true if this is a string diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index ba678878f2..0ad37241b4 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -992,7 +992,7 @@ void CompilerUtils::convertType( if (_targetType.category() == Type::Category::FixedBytes) { solAssert( - typeOnStack.isByteArrayOrString() && !typeOnStack.isString(), + typeOnStack.isByteArray(), "Array types other than bytes not convertible to bytesNN." ); solAssert(typeOnStack.isDynamicallySized()); @@ -1119,7 +1119,7 @@ void CompilerUtils::convertType( if (_targetType.category() == Type::Category::FixedBytes) { solAssert( - typeOnStack.arrayType().isByteArrayOrString() && !typeOnStack.arrayType().isString(), + typeOnStack.arrayType().isByteArray(), "Array types other than bytes not convertible to bytesNN." ); solAssert(typeOnStack.isDynamicallySized()); diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 3c79b64b46..9b50d68cd9 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -3216,7 +3216,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) auto const& fromType = dynamic_cast(_from); if (_to.category() == Type::Category::FixedBytes) { - solAssert(fromType.arrayType().isByteArrayOrString(), "Array types other than bytes not convertible to bytesNN."); + solAssert(fromType.arrayType().isByteArray(), "Array types other than bytes not convertible to bytesNN."); return bytesToFixedBytesConversionFunction(fromType.arrayType(), dynamic_cast(_to)); } solAssert(_to.category() == Type::Category::Array); @@ -3256,7 +3256,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) auto const& fromArrayType = dynamic_cast(_from); if (_to.category() == Type::Category::FixedBytes) { - solAssert(fromArrayType.isByteArrayOrString(), "Array types other than bytes not convertible to bytesNN."); + solAssert(fromArrayType.isByteArray(), "Array types other than bytes not convertible to bytesNN."); return bytesToFixedBytesConversionFunction(fromArrayType, dynamic_cast(_to)); } solAssert(_to.category() == Type::Category::Array, ""); @@ -3460,7 +3460,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) string YulUtilFunctions::bytesToFixedBytesConversionFunction(ArrayType const& _from, FixedBytesType const& _to) { - solAssert(_from.isByteArrayOrString() && !_from.isString(), ""); + solAssert(_from.isByteArray(), ""); solAssert(_from.isDynamicallySized(), ""); string functionName = "convert_bytes_to_fixedbytes_from_" + _from.identifier() + "_to_" + _to.identifier(); return m_functionCollector.createFunction(functionName, [&](auto& _args, auto& _returnParams) { diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 024e33be6e..b9041c6bd4 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -96,7 +96,7 @@ SortPointer smtSort(frontend::Type const& _type) auto sliceArrayType = dynamic_cast(&_type); ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast(&_type); if ( - (arrayType && (arrayType->isString() || arrayType->isByteArrayOrString())) || + (arrayType && arrayType->isByteArrayOrString()) || _type.category() == frontend::Type::Category::StringLiteral ) tupleName = "bytes"; From dcaa094f1f3850203f3908b9853efefeb3c54d58 Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 2 Feb 2022 18:11:14 -0500 Subject: [PATCH 0224/1704] Add NatSpec note for libraries --- docs/natspec-format.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index 297bbc8c62..a66c104629 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -36,7 +36,7 @@ tools. Documentation Example ===================== -Documentation is inserted above each ``contract``, ``interface``, +Documentation is inserted above each ``contract``, ``interface``, ``library``, ``function``, and ``event`` using the Doxygen notation format. A ``public`` state variable is equivalent to a ``function`` for the purposes of NatSpec. From f5b345504beab1f1cd10c21f382f97b7c6aa5321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 3 Feb 2022 14:52:58 +0100 Subject: [PATCH 0225/1704] When installing solc-js use the dist/ subdir, which contains the built JS files --- scripts/bytecodecompare/storebytecode.sh | 2 +- scripts/solc-bin/bytecode_reports_for_modified_binaries.sh | 4 ++-- test/externalTests/colony.sh | 6 +++--- test/externalTests/gnosis-v2.sh | 6 +++--- test/externalTests/gnosis.sh | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/bytecodecompare/storebytecode.sh b/scripts/bytecodecompare/storebytecode.sh index 1c300662bc..3574fe6bfb 100755 --- a/scripts/bytecodecompare/storebytecode.sh +++ b/scripts/bytecodecompare/storebytecode.sh @@ -52,7 +52,7 @@ TMPDIR=$(mktemp -d) popd cp "$REPO_ROOT/scripts/bytecodecompare/prepare_report.js" . - npm install solc-js/ + npm install ./solc-js/dist echo "Running the compiler..." # shellcheck disable=SC2035 diff --git a/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh b/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh index be151bca86..68ab995afc 100755 --- a/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh +++ b/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh @@ -149,11 +149,11 @@ for binary_name in $platform_binaries; do if [[ $platform == emscripten-wasm32 ]] || [[ $platform == emscripten-asmjs ]]; then ln -sf "${solc_bin_dir}/${platform}/${binary_name}" "${solcjs_dir}/soljson.js" ln -sf "${solc_bin_dir}/${platform}/${binary_name}" "${solcjs_dir}/dist/soljson.js" - ln -s "${solcjs_dir}" solc-js + npm install "${solcjs_dir}/dist" cp "${script_dir}/bytecodecompare/prepare_report.js" prepare_report.js validate_reported_version \ - "$(solc-js/dist/solc.js --version)" \ + "$(node_modules/solc/solc.js --version)" \ "$solidity_version_and_commit" # shellcheck disable=SC2035 diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index 8386b0b491..d659899535 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -59,7 +59,7 @@ function colony_test [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$(first_word "$SELECTED_PRESETS")" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")" yarn install git submodule update --init @@ -69,10 +69,10 @@ function colony_test cd .. replace_version_pragmas - [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" + [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist" for preset in $SELECTED_PRESETS; do - truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$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 done } diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index 16f3d6f622..8ad070d113 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -63,14 +63,14 @@ function gnosis_safe_test neutralize_package_lock neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$(first_word "$SELECTED_PRESETS")" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")" npm install --package-lock replace_version_pragmas - [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" + [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist" for preset in $SELECTED_PRESETS; do - truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$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 done } diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 62dea10df6..edada2fef3 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -61,14 +61,14 @@ function gnosis_safe_test neutralize_package_lock neutralize_package_json_hooks - force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$(first_word "$SELECTED_PRESETS")" + force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")" npm install --package-lock replace_version_pragmas - [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc" + [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist" for preset in $SELECTED_PRESETS; do - truffle_run_test "$config_file" "$BINARY_TYPE" "${DIR}/solc" "$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 done } From e85bceb4178f82e05762dc3e7e7bcf3020ded091 Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Fri, 4 Feb 2022 02:08:36 +0530 Subject: [PATCH 0226/1704] Types.h:872 had a comment /// String is interpreted as a subtype of Bytes. - this was now incorrect after #12593 . That has been removed now. --- libsolidity/ast/Types.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 3f134df17d..c4aaf38ca1 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -864,7 +864,6 @@ class ArrayType: public ReferenceType std::vector decomposition() const override { return {m_baseType}; } private: - /// String is interpreted as a subtype of Bytes. enum class ArrayKind { Ordinary, Bytes, String }; bigint unlimitedStaticCalldataSize(bool _padded) const; From b925250705d5ba44cbf6a2b49bb78eacaa402d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 28 Jan 2022 19:14:29 +0100 Subject: [PATCH 0227/1704] Make solc-js.sh run its tests directly - Its structure has diverged a lot from other external tests and there's not point in keeping it abstracted like this. --- test/externalTests/common.sh | 14 -------------- test/externalTests/solc-js/solc-js.sh | 8 ++++---- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 10df975256..3737069cb3 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -323,20 +323,6 @@ function hardhat_clean rm -rf 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 { local preset="$1" diff --git a/test/externalTests/solc-js/solc-js.sh b/test/externalTests/solc-js/solc-js.sh index 33b43e6430..3da03519b3 100755 --- a/test/externalTests/solc-js/solc-js.sh +++ b/test/externalTests/solc-js/solc-js.sh @@ -29,9 +29,6 @@ VERSION="$2" [[ $SOLJSON != "" && -f "$SOLJSON" && $VERSION != "" ]] || fail "Usage: $0 " -function compile_fn { echo "Nothing to compile."; } -function test_fn { npm test; } - function solcjs_test { TEST_DIR=$(pwd) @@ -60,7 +57,10 @@ function solcjs_test echo "Updating package.json to 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 From 9e641e60e7eeff966f3cd33824cf42bdb5111493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 28 Jan 2022 20:51:04 +0100 Subject: [PATCH 0228/1704] externalTests/solc-js: Allow using a local checkout of solc-js --- test/externalTests/common.sh | 10 +++++++++- test/externalTests/solc-js/solc-js.sh | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 3737069cb3..ec782f0562 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -71,15 +71,23 @@ function setup_solc local binary_path="$3" local solcjs_branch="${4:-master}" local install_dir="${5:-solc/}" + local solcjs_dir="$6" [[ $binary_type == native || $binary_type == solcjs ]] || assertFail + [[ $binary_type == solcjs || $solcjs_dir == "" ]] || assertFail cd "$test_dir" if [[ $binary_type == solcjs ]] then 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" npm install diff --git a/test/externalTests/solc-js/solc-js.sh b/test/externalTests/solc-js/solc-js.sh index 3da03519b3..bf7ca87628 100755 --- a/test/externalTests/solc-js/solc-js.sh +++ b/test/externalTests/solc-js/solc-js.sh @@ -26,8 +26,9 @@ source test/externalTests/common.sh SOLJSON="$1" VERSION="$2" +SOLCJS_CHECKOUT="$3" # optional -[[ $SOLJSON != "" && -f "$SOLJSON" && $VERSION != "" ]] || fail "Usage: $0 " +[[ $SOLJSON != "" && -f "$SOLJSON" && $VERSION != "" ]] || fail "Usage: $0 []" function solcjs_test { @@ -35,7 +36,7 @@ function solcjs_test SOLCJS_INPUT_DIR="$TEST_DIR"/test/externalTests/solc-js # 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/ printLog "Updating index.js file..." From b52032a452004e53115a8c214341593ef29018db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 4 Feb 2022 15:18:37 +0100 Subject: [PATCH 0229/1704] Re-enable Bleeps and just disable the failing governor test --- .circleci/config.yml | 3 +-- test/externalTests/bleeps.sh | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 44b44bb012..143a692fdb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1468,8 +1468,7 @@ workflows: - t_ems_ext: *job_native_test_ext_trident - t_ems_ext: *job_native_test_ext_euler - t_ems_ext: *job_native_test_ext_yield_liquidator - # Disabled until we have a fix for https://github.com/wighawag/bleeps/issues/2 - #-t_ems_ext: *job_native_test_ext_bleeps + - t_ems_ext: *job_native_test_ext_bleeps - 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_uniswap diff --git a/test/externalTests/bleeps.sh b/test/externalTests/bleeps.sh index d005cf8efb..561200e219 100755 --- a/test/externalTests/bleeps.sh +++ b/test/externalTests/bleeps.sh @@ -72,6 +72,10 @@ function bleeps_test sed -i 's/msg\.sender\.transfer(/payable(msg.sender).transfer(/g' src/externals/WETH9.sol sed -i 's/^\s*\(Deposit\|Withdrawal\|Approval\|Transfer\)(/emit \1(/g' src/externals/WETH9.sol + # This test does not currently pass due to an upstream problem. + # TODO: Remove this line when https://github.com/wighawag/bleeps/issues/2 is fixed + rm test/BleepsDAO.governor.test.ts + neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" From 4ebd839d3a303814865b83ff2c605f1a50d80b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 4 Feb 2022 15:51:34 +0100 Subject: [PATCH 0230/1704] Run full tests, not just test:contracts in PRBMath external test - `test:contracts` does not seem to be running any tests at all. --- test/externalTests/prb-math.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/prb-math.sh b/test/externalTests/prb-math.sh index 339a5e75d4..53fad2c255 100755 --- a/test/externalTests/prb-math.sh +++ b/test/externalTests/prb-math.sh @@ -30,7 +30,7 @@ BINARY_PATH="$2" SELECTED_PRESETS="$3" function compile_fn { yarn compile; } -function test_fn { yarn test:contracts; } +function test_fn { yarn test; } function prb_math_test { From 653c1e68429937abec17c9242a191227db0202b9 Mon Sep 17 00:00:00 2001 From: Ayush Shukla Date: Thu, 3 Feb 2022 20:26:46 +0530 Subject: [PATCH 0231/1704] Fix slot calculation for bytes/string mapping --- docs/internals/layout_in_storage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index b1b89a6a3c..9afe97ddbf 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -90,7 +90,7 @@ The value corresponding to a mapping key ``k`` is located at ``keccak256(h(k) . where ``.`` is concatenation and ``h`` is a function that is applied to the key depending on its type: - for value types, ``h`` pads the value to 32 bytes in the same way as when storing the value in memory. -- for strings and byte arrays, ``h`` computes the ``keccak256`` hash of the unpadded data. +- for strings and byte arrays, ``h(k)`` is just the unpadded data. If the mapping value is a non-value type, the computed slot marks the start of the data. If the value is of struct type, From 4d65bfa95e28f3dc3b8ad6cd6aaf8578c15851c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 5 Feb 2022 00:05:39 +0100 Subject: [PATCH 0232/1704] CI: Remove notes about Hardhat failing on nodejs 17; that version is officially not supported --- .circleci/config.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 143a692fdb..3f2c661a0c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -521,35 +521,30 @@ defaults: name: t_native_test_ext_ens project: ens binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - job_native_test_ext_trident: &job_native_test_ext_trident <<: *workflow_ubuntu2004_static name: t_native_test_ext_trident project: trident binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - job_native_test_ext_euler: &job_native_test_ext_euler <<: *workflow_ubuntu2004_static name: t_native_test_ext_euler project: euler binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - job_native_test_ext_yield_liquidator: &job_native_test_ext_yield_liquidator <<: *workflow_ubuntu2004_static name: t_native_test_ext_yield_liquidator project: yield-liquidator binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - job_native_test_ext_bleeps: &job_native_test_ext_bleeps <<: *workflow_ubuntu2004_static name: t_native_test_ext_bleeps project: bleeps binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' resource_class: medium - job_native_test_ext_pool_together: &job_native_test_ext_pool_together @@ -557,35 +552,30 @@ defaults: name: t_native_test_ext_pool_together project: pool-together binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - job_native_test_ext_perpetual_pools: &job_native_test_ext_perpetual_pools <<: *workflow_ubuntu2004_static name: t_native_test_ext_perpetual_pools project: perpetual-pools binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - job_native_test_ext_uniswap: &job_native_test_ext_uniswap <<: *workflow_ubuntu2004_static name: t_native_test_ext_uniswap project: uniswap binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - job_native_test_prb_math: &job_native_test_prb_math <<: *workflow_ubuntu2004_static name: t_native_test_ext_prb_math project: prb-math binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' - job_native_test_ext_elementfi: &job_native_test_ext_elementfi <<: *workflow_ubuntu2004_static name: t_native_test_ext_elementfi project: elementfi binary_type: native - # NOTE: Tests crash on nodejs 17: "Error: error:0308010C:digital envelope routines::unsupported" nodejs_version: '16' resource_class: medium - job_ems_test_ext_colony: &job_ems_test_ext_colony From 247eab90567e36fb9d8e390ef530551316fc7a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 5 Feb 2022 00:03:53 +0100 Subject: [PATCH 0233/1704] CI: Rename node_latest_small to node_small --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3f2c661a0c..db9baaa642 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -384,7 +384,7 @@ defaults: TERM: xterm MAKEFLAGS: -j 2 - - base_node_latest_small: &base_node_latest_small + - base_node_small: &base_node_small docker: - image: circleci/node resource_class: small @@ -605,7 +605,7 @@ jobs: - gitter_notify_failure_unless_pr chk_docs_examples: - <<: *base_node_latest_small + <<: *base_node_small steps: - checkout - attach_workspace: @@ -674,7 +674,7 @@ jobs: - gitter_notify_failure_unless_pr chk_buglist: - <<: *base_node_latest_small + <<: *base_node_small steps: - checkout - run: @@ -1136,7 +1136,7 @@ jobs: - gitter_notify_failure_unless_pr t_ems_ext_hardhat: - <<: *base_node_latest_small + <<: *base_node_small environment: TERM: xterm HARDHAT_TESTS_SOLC_PATH: /tmp/workspace/soljson.js @@ -1339,7 +1339,7 @@ jobs: - gitter_notify_failure_unless_pr b_bytecode_ems: - <<: *base_node_latest_small + <<: *base_node_small environment: SOLC_EMSCRIPTEN: "On" steps: From 2f0ccb21bef0ddee12b37b52289ca7081b6a5d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 5 Feb 2022 00:04:20 +0100 Subject: [PATCH 0234/1704] CI: Switch t_ems_ext_hardhat to nodejs 16 --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index db9baaa642..58a4c27428 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1137,6 +1137,8 @@ jobs: t_ems_ext_hardhat: <<: *base_node_small + docker: + - image: circleci/node:16 environment: TERM: xterm HARDHAT_TESTS_SOLC_PATH: /tmp/workspace/soljson.js From 7634fc4ea9537d60fdf686f43a4e54e7ab0f43fe Mon Sep 17 00:00:00 2001 From: a3d4 Date: Fri, 4 Feb 2022 17:54:21 +0100 Subject: [PATCH 0235/1704] Clarify symlink handling on Windows --- docs/contributing.rst | 7 +++++++ test/FilesystemUtils.cpp | 1 + 2 files changed, 8 insertions(+) diff --git a/docs/contributing.rst b/docs/contributing.rst index 2895744ef4..ba5a0a0f8f 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -94,6 +94,13 @@ dependencies (`evmone `_, On macOS some of the testing scripts expect GNU coreutils to be installed. 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 `_ +or +`enable Developer Mode `_. + Running the Tests ----------------- diff --git a/test/FilesystemUtils.cpp b/test/FilesystemUtils.cpp index 0235b11476..0d1de3af95 100644 --- a/test/FilesystemUtils.cpp +++ b/test/FilesystemUtils.cpp @@ -81,5 +81,6 @@ bool solidity::test::createSymlinkIfSupportedByFilesystem( BOOST_THROW_EXCEPTION(runtime_error( "Failed to create a symbolic link: \"" + _linkName.string() + "\"" " -> " + _targetPath.string() + "\"." + " " + symlinkCreationError.message() + "." )); } From 0a17495cf94016318ee76f299419595d6bfdd718 Mon Sep 17 00:00:00 2001 From: a3d4 Date: Sat, 5 Feb 2022 11:51:11 +0100 Subject: [PATCH 0236/1704] Treat root path in normalizeCLIPathForVFS as case insensitive on Windows --- libsolidity/interface/FileReader.cpp | 3 ++- test/libsolidity/interface/FileReader.cpp | 28 +++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 47f4d2b5aa..adb4b01cae 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -269,7 +269,8 @@ boost::filesystem::path FileReader::normalizeCLIPathForVFS( if (!isUNCPath(normalizedPath)) { 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 = "/"; } diff --git a/test/libsolidity/interface/FileReader.cpp b/test/libsolidity/interface/FileReader.cpp index 866a4435ac..39355e536f 100644 --- a/test/libsolidity/interface/FileReader.cpp +++ b/test/libsolidity/interface/FileReader.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -192,8 +193,8 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_root_name_only) #if defined(_WIN32) boost::filesystem::path driveLetter = boost::filesystem::current_path().root_name(); - solAssert(!driveLetter.empty(), ""); - solAssert(driveLetter.is_relative(), ""); + soltestAssert(!driveLetter.empty(), ""); + soltestAssert(driveLetter.is_relative(), ""); BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(driveLetter, resolveSymlinks), expectedWorkDir); #endif @@ -212,13 +213,32 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_stripping_root_name) for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled}) { + boost::filesystem::path workDir = boost::filesystem::current_path(); + boost::filesystem::path normalizedPath = FileReader::normalizeCLIPathForVFS( - boost::filesystem::current_path(), + workDir, 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_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, boost::to_upper_copy}) + { + 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 } } From a0dd2cd1ff59d06425c78180a2a8a6e2c8ff506e Mon Sep 17 00:00:00 2001 From: a3d4 Date: Sat, 5 Feb 2022 15:12:49 +0100 Subject: [PATCH 0237/1704] Remove a reference to unused SolidityFixedFeeRegistrar --- test/boostTest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/boostTest.cpp b/test/boostTest.cpp index bfb546736c..1cc512c325 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -57,7 +57,7 @@ void removeTestSuite(std::string const& _name) { master_test_suite_t& master = framework::master_test_suite(); 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); } @@ -279,7 +279,6 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "ABIDecoderTest", "ABIEncoderTest", "SolidityAuctionRegistrar", - "SolidityFixedFeeRegistrar", "SolidityWallet", "GasMeterTests", "GasCostTests", From 6bd38aa4ef2ca036775896b77909b361ed3d8855 Mon Sep 17 00:00:00 2001 From: William Entriken Date: Sat, 5 Feb 2022 23:59:09 -0500 Subject: [PATCH 0238/1704] Fix signature of pop member --- docs/types/reference-types.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 126440321c..88e23a47eb 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -337,9 +337,9 @@ Array Members Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``push(x)`` that you can use to append a given element at the end of the array. The function returns nothing. -**pop**: +**pop()**: Dynamic storage arrays and ``bytes`` (not ``string``) have a member - function called ``pop`` that you can use to remove an element from the + function called ``pop()`` that you can use to remove an element from the end of the array. This also implicitly calls :ref:`delete` on the removed element. .. note:: From c3145979fc18c104479379916b17364e94fccb16 Mon Sep 17 00:00:00 2001 From: Hakeem Almidan Date: Sun, 6 Feb 2022 20:16:04 +0300 Subject: [PATCH 0239/1704] Update cheatsheet.rst Add more description to the bullet point of 'block.timestamp' (under 'Global Variables') --- docs/cheatsheet.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index eab1e3d52a..cd9ba5c149 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -92,7 +92,7 @@ Global Variables - ``block.difficulty`` (``uint``): current block difficulty - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number -- ``block.timestamp`` (``uint``): current block timestamp +- ``block.timestamp`` (``uint``): current block timestamp in seconds since Unix epoch - ``gasleft() returns (uint256)``: remaining gas - ``msg.data`` (``bytes``): complete calldata - ``msg.sender`` (``address``): sender of the message (current call) From 4715fafb829a156e25a027027d8632689ee3d04b Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 7 Feb 2022 11:31:59 +0100 Subject: [PATCH 0240/1704] Re-enable preset for poolTogether. --- test/externalTests/pool-together.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index 1cabd6a501..a7f5933c0e 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -45,7 +45,7 @@ function pool_together_test "${compile_only_presets[@]}" #ir-no-optimize # Compilation fails with "YulException: Variable var_amount_205 is 9 slot(s) too deep inside the stack." #ir-optimize-evm-only # Compilation fails with "YulException: Variable var_amount_205 is 9 slot(s) too deep inside the stack." - #ir-optimize-evm+yul # FIXME: ICE due to https://github.com/ethereum/solidity/issues/12558 + ir-optimize-evm+yul legacy-no-optimize legacy-optimize-evm-only legacy-optimize-evm+yul From b9fe628b70b0f118f02822ace678a69c39f5843c Mon Sep 17 00:00:00 2001 From: Marenz Date: Thu, 27 Jan 2022 14:07:50 +0100 Subject: [PATCH 0241/1704] Emit immutable references for pure yul code --- Changelog.md | 1 + libsolidity/interface/StandardCompiler.cpp | 22 ++++---- .../standard_yul_immutable_references/args | 1 + .../input.json | 22 ++++++++ .../output.json | 52 +++++++++++++++++++ .../standard_yul_object_name/output.json | 2 +- 6 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 test/cmdlineTests/standard_yul_immutable_references/args create mode 100644 test/cmdlineTests/standard_yul_immutable_references/input.json create mode 100644 test/cmdlineTests/standard_yul_immutable_references/output.json diff --git a/Changelog.md b/Changelog.md index e75e2c710e..c938c44b0f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Language Features: Compiler Features: * 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. diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 39ed7c10fb..5ccf2d447b 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1461,36 +1461,36 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) stack.optimize(); MachineAssemblyObject object; - MachineAssemblyObject runtimeObject; - tie(object, runtimeObject) = stack.assembleWithDeployed(); + MachineAssemblyObject deployedObject; + tie(object, deployedObject) = stack.assembleWithDeployed(); if (object.bytecode) object.bytecode->link(_inputsAndSettings.libraries); - if (runtimeObject.bytecode) - runtimeObject.bytecode->link(_inputsAndSettings.libraries); + if (deployedObject.bytecode) + deployedObject.bytecode->link(_inputsAndSettings.libraries); - for (string const& objectKind: vector{"bytecode", "deployedBytecode"}) + for (auto&& [kind, isDeployed]: {make_pair("bytecode"s, false), make_pair("deployedBytecode"s, true)}) if (isArtifactRequested( _inputsAndSettings.outputSelection, sourceName, contractName, - evmObjectComponents(objectKind), + evmObjectComponents(kind), wildcardMatchesExperimental )) { - MachineAssemblyObject const& o = objectKind == "bytecode" ? object : runtimeObject; + MachineAssemblyObject const& o = isDeployed ? deployedObject : object; if (o.bytecode) - output["contracts"][sourceName][contractName]["evm"][objectKind] = + output["contracts"][sourceName][contractName]["evm"][kind] = collectEVMObject( *o.bytecode, o.sourceMappings.get(), Json::arrayValue, - false, - [&](string const& _element) { return isArtifactRequested( + isDeployed, + [&, kind = kind](string const& _element) { return isArtifactRequested( _inputsAndSettings.outputSelection, sourceName, contractName, - "evm." + objectKind + "." + _element, + "evm." + kind + "." + _element, wildcardMatchesExperimental ); } ); diff --git a/test/cmdlineTests/standard_yul_immutable_references/args b/test/cmdlineTests/standard_yul_immutable_references/args new file mode 100644 index 0000000000..d13a8ac44a --- /dev/null +++ b/test/cmdlineTests/standard_yul_immutable_references/args @@ -0,0 +1 @@ +--pretty-json diff --git a/test/cmdlineTests/standard_yul_immutable_references/input.json b/test/cmdlineTests/standard_yul_immutable_references/input.json new file mode 100644 index 0000000000..aedbae8683 --- /dev/null +++ b/test/cmdlineTests/standard_yul_immutable_references/input.json @@ -0,0 +1,22 @@ +{ + "language": "Yul", + "sources": + { + "A": + { + "content": "object \"YulTest\" { code { let size := datasize(\"runtime\") datacopy(0, dataoffset(\"runtime\"), size) setimmutable(0, \"test\", 1) return(0, size) } object \"runtime\" { code { mstore(0, loadimmutable(\"test\")) return(0, 0x20) } }}" + } + }, + "settings": + { + "outputSelection": { + "A": { + "*": [ + "evm.deployedBytecode.immutableReferences", + "evm.bytecode", + "evm.deployedBytecode" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_immutable_references/output.json b/test/cmdlineTests/standard_yul_immutable_references/output.json new file mode 100644 index 0000000000..42361097de --- /dev/null +++ b/test/cmdlineTests/standard_yul_immutable_references/output.json @@ -0,0 +1,52 @@ +{ + "contracts": + { + "A": + { + "YulTest": + { + "evm": + { + "bytecode": + { + "functionDebugData": {}, + "generatedSources": [], + "linkReferences": {}, + "object": "60298060156000396001600060010152806000f3fe7f000000000000000000000000000000000000000000000000000000000000000060005260206000f3", + "opcodes": "PUSH1 0x29 DUP1 PUSH1 0x15 PUSH1 0x0 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH1 0x1 ADD MSTORE DUP1 PUSH1 0x0 RETURN INVALID PUSH32 0x0 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 RETURN ", + "sourceMap": "42:19:0:-:0;100:4;77:21;74:1;65:40;133:1;122;109:26;;;149:4;146:1;139:15" + }, + "deployedBytecode": + { + "functionDebugData": {}, + "generatedSources": [], + "immutableReferences": + { + "test": + [ + { + "length": 32, + "start": 1 + } + ] + }, + "linkReferences": {}, + "object": "7f000000000000000000000000000000000000000000000000000000000000000060005260206000f3", + "opcodes": "PUSH32 0x0 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 RETURN ", + "sourceMap": "203:21:0:-:0;200:1;193:32;241:4;238:1;231:15" + } + } + } + } + }, + "errors": + [ + { + "component": "general", + "formattedMessage": "Yul is still experimental. Please use the output with care.", + "message": "Yul is still experimental. Please use the output with care.", + "severity": "warning", + "type": "Warning" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_object_name/output.json b/test/cmdlineTests/standard_yul_object_name/output.json index f2e85ed7cb..45280c8a1b 100644 --- a/test/cmdlineTests/standard_yul_object_name/output.json +++ b/test/cmdlineTests/standard_yul_object_name/output.json @@ -23,7 +23,7 @@ sub_0: assembly { /* \"A\":137:149 */ revert } -","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"","opcodes":"","sourceMap":""},"deployedBytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"","opcodes":"","sourceMap":""}},"ir":"object \"NamedObject\" { +","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"","opcodes":"","sourceMap":""},"deployedBytecode":{"functionDebugData":{},"generatedSources":[],"immutableReferences":{},"linkReferences":{},"object":"","opcodes":"","sourceMap":""}},"ir":"object \"NamedObject\" { code { let x := dataoffset(\"DataName\") sstore(add(x, 0), 0) From 2e2094ad820994161cf621c90a0e82f3d1c1d6f2 Mon Sep 17 00:00:00 2001 From: Naveen Sahu <42338831+theNvN@users.noreply.github.com> Date: Wed, 2 Feb 2022 02:02:31 +0530 Subject: [PATCH 0242/1704] plain `address` can be sent Ether too The docs state that a plain `address` cannot be sent Ether. But even though `send` and `transfer` members are not available for plain `address`, the `call` is. And `call` can be invoked upon a plain `address` type to send Ether to the address. For instance, the `someone` (`address` type) can be sent Ether by invoking `sendSomeone()` method in the following `Dummy` contract: ``` contract Dummy { address someone = 0xAb8...cb2; function balanceOf(address addr) public view returns (uint) { return addr.balance; } function sendToSomeone() public payable returns (bool) { (bool sent, ) = someone.call{value: msg.value}(""); return sent; } } ``` --- docs/types/value-types.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 30a8577963..0d6a30cd62 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -188,7 +188,8 @@ The address type comes in two flavours, which are largely identical: - ``address payable``: Same as ``address``, but with the additional members ``transfer`` and ``send``. The idea behind this distinction is that ``address payable`` is an address you can send Ether to, -while a plain ``address`` cannot be sent Ether. +while you are not supposed to send Ether to a plain ``address``, for example because it might be a smart contract +that was not built to accept Ether. Type conversions: From 6225dad3328ef1d8a440e2710545795f07bf9844 Mon Sep 17 00:00:00 2001 From: joshuatarkwski Date: Wed, 10 Nov 2021 15:16:11 +0100 Subject: [PATCH 0243/1704] Output searched locations on import failure. --- libsolidity/interface/FileReader.cpp | 23 ++++++++++++++----- .../output.json | 4 ++-- test/solc/CommandLineInterfaceAllowPaths.cpp | 6 ++--- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 47f4d2b5aa..8733e91a0d 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -116,7 +116,6 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so for (auto const& prefix: prefixes) { boost::filesystem::path canonicalPath = normalizeCLIPathForVFS(prefix / strippedSourceUnitName, SymlinkResolution::Enabled); - if (boost::filesystem::exists(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() + "\""; }; 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) return ReadCallback::Result{ @@ -135,11 +139,13 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so "." }; - FileSystemPathSet extraAllowedPaths = {m_basePath.empty() ? "." : m_basePath}; - extraAllowedPaths += m_includePaths; + FileSystemPathSet allowedPaths = + m_allowedDirectories + + decltype(allowedPaths){m_basePath.empty() ? "." : m_basePath} + + m_includePaths; 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])) { isAllowed = true; @@ -147,7 +153,12 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so } 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])) return ReadCallback::Result{false, "Not a valid file."}; diff --git a/test/cmdlineTests/standard_yul_single_file_via_urls/output.json b/test/cmdlineTests/standard_yul_single_file_via_urls/output.json index 3f62fa0fe4..a97057c889 100644 --- a/test/cmdlineTests/standard_yul_single_file_via_urls/output.json +++ b/test/cmdlineTests/standard_yul_single_file_via_urls/output.json @@ -3,8 +3,8 @@ [ { "component": "general", - "formattedMessage": "Cannot import url (\"in.yul\"): File not found.", - "message": "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. Searched the following locations: \"\".", "severity": "error", "type": "IOError" }, diff --git a/test/solc/CommandLineInterfaceAllowPaths.cpp b/test/solc/CommandLineInterfaceAllowPaths.cpp index 77f727014f..472f2184b4 100644 --- a/test/solc/CommandLineInterfaceAllowPaths.cpp +++ b/test/solc/CommandLineInterfaceAllowPaths.cpp @@ -100,7 +100,7 @@ ImportCheck checkImport( return ImportCheck::OK(); static regex const sourceNotFoundErrorRegex{ - R"(^Error \(6275\): Source ".+" not found: (.*)\.\n)" + R"(^Error \(6275\): Source "[^"]+" not found: (.*)\.\n)" R"(\s*--> .*:\d+:\d+:\n)" R"(\s*\|\n)" R"(\d+\s*\| import '.+';\n)" @@ -110,12 +110,12 @@ ImportCheck checkImport( smatch submatches; if (!regex_match(cliResult.stderrContent, submatches, sourceNotFoundErrorRegex)) 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 + "'"); if (submatches[1] == "File not found") 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(); else return ImportCheck::Unknown("Unexpected error message '" + submatches[1].str() + "'"); From 9e62f21b2586afb6544f6a03d9c4c2f088dd94f7 Mon Sep 17 00:00:00 2001 From: joshieDo Date: Mon, 17 Jan 2022 21:28:58 +0000 Subject: [PATCH 0244/1704] Add event and error identifiers to cli hashes cmd --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 32 +++++++++++++++++++++++++ libsolidity/interface/CompilerStack.h | 6 +++++ solc/CommandLineInterface.cpp | 20 ++++++++++++++-- test/cmdlineTests/hashes/args | 1 + test/cmdlineTests/hashes/input.sol | 28 ++++++++++++++++++++++ test/cmdlineTests/hashes/output | 23 ++++++++++++++++++ 7 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 test/cmdlineTests/hashes/args create mode 100644 test/cmdlineTests/hashes/input.sol create mode 100644 test/cmdlineTests/hashes/output diff --git a/Changelog.md b/Changelog.md index c938c44b0f..98515970f0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: 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: Emit immutable references for pure yul code when requested. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 5292d5329f..a1c26ab374 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -75,6 +75,7 @@ #include #include #include +#include #include @@ -1024,6 +1025,37 @@ Json::Value CompilerStack::methodIdentifiers(string const& _contractName) const return methodIdentifiers; } +Json::Value CompilerStack::errorIdentifiers(string const& _contractName) const +{ + if (m_stackState < AnalysisPerformed) + solThrow(CompilerError, "Analysis was not successful."); + + Json::Value errorIdentifiers(Json::objectValue); + for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors()) + { + string signature = error->functionType(true)->externalSignature(); + errorIdentifiers[signature] = toHex(toCompactBigEndian(selectorFromSignature32(signature), 4)); + } + + return errorIdentifiers; +} + +Json::Value CompilerStack::eventIdentifiers(string const& _contractName) const +{ + if (m_stackState < AnalysisPerformed) + solThrow(CompilerError, "Analysis was not successful."); + + Json::Value eventIdentifiers(Json::objectValue); + for (EventDefinition const* event: contractDefinition(_contractName).interfaceEvents()) + if (!event->isAnonymous()) + { + string signature = event->functionType(true)->externalSignature(); + eventIdentifiers[signature] = toHex(u256(h256::Arith(keccak256(signature)))); + } + + return eventIdentifiers; +} + bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) const { if (m_stackState < AnalysisPerformed) diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 3609662e02..2e1e687f71 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -330,6 +330,12 @@ class CompilerStack: public langutil::CharStreamProvider /// @returns a JSON representing a map of method identifiers (hashes) to function names. Json::Value methodIdentifiers(std::string const& _contractName) const; + /// @returns a JSON representing a map of error identifiers (hashes) to error names. + Json::Value errorIdentifiers(std::string const& _contractName) const; + + /// @returns a JSON representing a map of event identifiers (hashes) to event names. + Json::Value eventIdentifiers(std::string const& _contractName) const; + /// @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)); } diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 235059a02b..d96460fa1e 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -271,14 +271,30 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract) return; Json::Value methodIdentifiers = m_compiler->methodIdentifiers(_contract); - string out; + string out = "Function signatures:\n"; for (auto const& name: methodIdentifiers.getMemberNames()) out += methodIdentifiers[name].asString() + ": " + name + "\n"; + Json::Value errorIdentifiers = m_compiler->errorIdentifiers(_contract); + if (!errorIdentifiers.empty()) + { + out += "\nError signatures:\n"; + for (auto const& name: errorIdentifiers.getMemberNames()) + out += errorIdentifiers[name].asString() + ": " + name + "\n"; + } + + Json::Value eventIdentifiers = m_compiler->eventIdentifiers(_contract); + if (!eventIdentifiers.empty()) + { + out += "\nEvent signatures:\n"; + for (auto const& name: eventIdentifiers.getMemberNames()) + out += eventIdentifiers[name].asString() + ": " + name + "\n"; + } + if (!m_options.output.dir.empty()) createFile(m_compiler->filesystemFriendlyName(_contract) + ".signatures", out); else - sout() << "Function signatures:" << endl << out; + sout() << out; } void CommandLineInterface::handleMetadata(string const& _contract) diff --git a/test/cmdlineTests/hashes/args b/test/cmdlineTests/hashes/args new file mode 100644 index 0000000000..40469d358c --- /dev/null +++ b/test/cmdlineTests/hashes/args @@ -0,0 +1 @@ +--hashes \ No newline at end of file diff --git a/test/cmdlineTests/hashes/input.sol b/test/cmdlineTests/hashes/input.sol new file mode 100644 index 0000000000..1f5c758f71 --- /dev/null +++ b/test/cmdlineTests/hashes/input.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +error fileLevelError(uint z); + +library L { + event libraryEvent(uint r); + error libraryError(uint r); + error libraryErrorUnused(uint u); + event libraryEventUnused(uint u); +} + +contract C { + struct S { uint x; } + + event ev(uint y); + event anon_ev(uint y) anonymous; + + error err(uint z, uint w); + + function f(S memory s) public { + emit L.libraryEvent(3); + if (s.x > 1) + revert fileLevelError(3); + else + revert L.libraryError(4); + } +} diff --git a/test/cmdlineTests/hashes/output b/test/cmdlineTests/hashes/output new file mode 100644 index 0000000000..5223d732a3 --- /dev/null +++ b/test/cmdlineTests/hashes/output @@ -0,0 +1,23 @@ + +======= 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) + +======= hashes/input.sol:L ======= +Function signatures: + +Error signatures: +8c41f45c: libraryError(uint256) +c61c03f5: libraryErrorUnused(uint256) + +Event signatures: +81f3fb02f88d32d3bb08c80c9a622ca3b3223292f131c6ad049811f9a8a606dc: libraryEvent(uint256) +0a994ad3600197f16ffe1ea1101caea3174efe5ebd9ba9a75d6d5524c5de28cd: libraryEventUnused(uint256) From 3e7c68d9b09b59a959f32975f21ba3ec19152afa Mon Sep 17 00:00:00 2001 From: Marenz Date: Mon, 31 Jan 2022 17:52:08 +0100 Subject: [PATCH 0245/1704] Merge identifier query methods into one --- libsolidity/interface/CompilerStack.cpp | 33 +++++-------------- libsolidity/interface/CompilerStack.h | 10 ++---- libsolidity/interface/StandardCompiler.cpp | 2 +- solc/CommandLineInterface.cpp | 22 ++++++------- .../input.json | 17 ++++++++++ .../output.json | 1 + test/libsolidity/SemanticTest.cpp | 2 +- .../tools/ossfuzz/SolidityEvmoneInterface.cpp | 2 +- test/tools/ossfuzz/SolidityEvmoneInterface.h | 2 +- 9 files changed, 43 insertions(+), 48 deletions(-) create mode 100644 test/cmdlineTests/standard_method_identifiers_requested_empty/input.json create mode 100644 test/cmdlineTests/standard_method_identifiers_requested_empty/output.json diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index a1c26ab374..acf1932956 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1014,46 +1014,31 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); }); } -Json::Value CompilerStack::methodIdentifiers(string const& _contractName) const +Json::Value CompilerStack::contractIdentifiers(string const& _contractName) const { if (m_stackState < AnalysisPerformed) solThrow(CompilerError, "Analysis was not successful."); - Json::Value methodIdentifiers(Json::objectValue); - for (auto const& it: contractDefinition(_contractName).interfaceFunctions()) - methodIdentifiers[it.second->externalSignature()] = it.first.hex(); - return methodIdentifiers; -} + Json::Value contractIdentifiers(Json::objectValue); + // Always have a methods object + contractIdentifiers["methods"] = Json::objectValue; -Json::Value CompilerStack::errorIdentifiers(string const& _contractName) const -{ - if (m_stackState < AnalysisPerformed) - solThrow(CompilerError, "Analysis was not successful."); - - Json::Value errorIdentifiers(Json::objectValue); + for (auto const& it: contractDefinition(_contractName).interfaceFunctions()) + contractIdentifiers["methods"][it.second->externalSignature()] = it.first.hex(); for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors()) { string signature = error->functionType(true)->externalSignature(); - errorIdentifiers[signature] = toHex(toCompactBigEndian(selectorFromSignature32(signature), 4)); + contractIdentifiers["errors"][signature] = toHex(toCompactBigEndian(selectorFromSignature32(signature), 4)); } - return errorIdentifiers; -} - -Json::Value CompilerStack::eventIdentifiers(string const& _contractName) const -{ - if (m_stackState < AnalysisPerformed) - solThrow(CompilerError, "Analysis was not successful."); - - Json::Value eventIdentifiers(Json::objectValue); for (EventDefinition const* event: contractDefinition(_contractName).interfaceEvents()) if (!event->isAnonymous()) { string signature = event->functionType(true)->externalSignature(); - eventIdentifiers[signature] = toHex(u256(h256::Arith(keccak256(signature)))); + contractIdentifiers["events"][signature] = toHex(u256(h256::Arith(keccak256(signature)))); } - return eventIdentifiers; + return contractIdentifiers; } bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) const diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 2e1e687f71..b1f85dd4df 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -327,14 +327,8 @@ class CompilerStack: public langutil::CharStreamProvider /// Prerequisite: Successful call to parse or compile. Json::Value const& natspecDev(std::string const& _contractName) const; - /// @returns a JSON representing a map of method identifiers (hashes) to function names. - Json::Value methodIdentifiers(std::string const& _contractName) const; - - /// @returns a JSON representing a map of error identifiers (hashes) to error names. - Json::Value errorIdentifiers(std::string const& _contractName) const; - - /// @returns a JSON representing a map of event identifiers (hashes) to event names. - Json::Value eventIdentifiers(std::string const& _contractName) const; + /// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names. + Json::Value contractIdentifiers(std::string const& _contractName) const; /// @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)); } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 5ccf2d447b..0e5b8aba46 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1298,7 +1298,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly", wildcardMatchesExperimental)) evmData["legacyAssembly"] = compilerStack.assemblyJSON(contractName); if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.methodIdentifiers", wildcardMatchesExperimental)) - evmData["methodIdentifiers"] = compilerStack.methodIdentifiers(contractName); + evmData["methodIdentifiers"] = compilerStack.contractIdentifiers(contractName)["methods"]; if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.gasEstimates", wildcardMatchesExperimental)) evmData["gasEstimates"] = compilerStack.gasEstimates(contractName); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index d96460fa1e..ba557918c1 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -270,25 +270,23 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract) if (!m_options.compiler.outputs.signatureHashes) return; - Json::Value methodIdentifiers = m_compiler->methodIdentifiers(_contract); + Json::Value contractIdentifiers = m_compiler->contractIdentifiers(_contract); string out = "Function signatures:\n"; - for (auto const& name: methodIdentifiers.getMemberNames()) - out += methodIdentifiers[name].asString() + ": " + name + "\n"; + for (auto const& name: contractIdentifiers["methods"].getMemberNames()) + out += contractIdentifiers["methods"][name].asString() + ": " + name + "\n"; - Json::Value errorIdentifiers = m_compiler->errorIdentifiers(_contract); - if (!errorIdentifiers.empty()) + if (contractIdentifiers.isMember("errors")) { out += "\nError signatures:\n"; - for (auto const& name: errorIdentifiers.getMemberNames()) - out += errorIdentifiers[name].asString() + ": " + name + "\n"; + for (auto const& name: contractIdentifiers["errors"].getMemberNames()) + out += contractIdentifiers["errors"][name].asString() + ": " + name + "\n"; } - Json::Value eventIdentifiers = m_compiler->eventIdentifiers(_contract); - if (!eventIdentifiers.empty()) + if (contractIdentifiers.isMember("events")) { out += "\nEvent signatures:\n"; - for (auto const& name: eventIdentifiers.getMemberNames()) - out += eventIdentifiers[name].asString() + ": " + name + "\n"; + for (auto const& name: contractIdentifiers["events"].getMemberNames()) + out += contractIdentifiers["events"][name].asString() + ": " + name + "\n"; } if (!m_options.output.dir.empty()) @@ -838,7 +836,7 @@ void CommandLineInterface::handleCombinedJSON() m_compiler->runtimeObject(contractName).functionDebugData ); if (m_options.compiler.combinedJsonRequests->signatureHashes) - contractData[g_strSignatureHashes] = m_compiler->methodIdentifiers(contractName); + contractData[g_strSignatureHashes] = m_compiler->contractIdentifiers(contractName)["methods"]; if (m_options.compiler.combinedJsonRequests->natspecDev) contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName); if (m_options.compiler.combinedJsonRequests->natspecUser) diff --git a/test/cmdlineTests/standard_method_identifiers_requested_empty/input.json b/test/cmdlineTests/standard_method_identifiers_requested_empty/input.json new file mode 100644 index 0000000000..28b9699b51 --- /dev/null +++ b/test/cmdlineTests/standard_method_identifiers_requested_empty/input.json @@ -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"] } + } + } +} diff --git a/test/cmdlineTests/standard_method_identifiers_requested_empty/output.json b/test/cmdlineTests/standard_method_identifiers_requested_empty/output.json new file mode 100644 index 0000000000..7953dc1572 --- /dev/null +++ b/test/cmdlineTests/standard_method_identifiers_requested_empty/output.json @@ -0,0 +1 @@ +{"contracts":{"A":{"C":{"evm":{"methodIdentifiers":{}}}}},"sources":{"A":{"id":0}}} diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 4fbb16614c..342cf24fc2 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -435,7 +435,7 @@ TestCase::TestResult SemanticTest::runTest( { soltestAssert( m_allowNonExistingFunctions || - m_compiler.methodIdentifiers(m_compiler.lastContractName(m_sources.mainSourceFile)).isMember(test.call().signature), + m_compiler.contractIdentifiers(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].isMember(test.call().signature), "The function " + test.call().signature + " is not known to the compiler" ); diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp index 4d536183c3..49b17930a3 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp @@ -58,7 +58,7 @@ optional SolidityCompilationFramework::compileContract() else contractName = m_compilerInput.contractName; evmasm::LinkerObject obj = m_compiler.object(contractName); - Json::Value methodIdentifiers = m_compiler.methodIdentifiers(contractName); + Json::Value methodIdentifiers = m_compiler.contractIdentifiers(contractName)["methods"]; return CompilerOutput{obj.bytecode, methodIdentifiers}; } } diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.h b/test/tools/ossfuzz/SolidityEvmoneInterface.h index 980eb9a842..51f6d5bdcc 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.h +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.h @@ -91,7 +91,7 @@ class SolidityCompilationFramework /// @returns method identifiers in contract called @param _contractName. Json::Value methodIdentifiers(std::string const& _contractName) { - return m_compiler.methodIdentifiers(_contractName); + return m_compiler.contractIdentifiers(_contractName)["methods"]; } /// @returns Compilation output comprising EVM bytecode and list of /// method identifiers in contract if compilation is successful, From 0f05b1485e0fa8f54119ba0f48c3e7b7bcac3044 Mon Sep 17 00:00:00 2001 From: yatharthagoenka Date: Sat, 4 Sep 2021 15:37:18 +0530 Subject: [PATCH 0246/1704] CI: shared build and dependency installation steps --- .circleci/config.yml | 62 +++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 58a4c27428..be4940c636 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -214,6 +214,14 @@ defaults: command: ./test/lsp.py ./build/solc/solc - gitter_notify_failure_unless_pr + - steps_build: &steps_build + steps: + - checkout + - run: *run_build + - store_artifacts: *artifacts_solc + - persist_to_workspace: *artifacts_executables + - gitter_notify_failure_unless_pr + - steps_soltest_all: &steps_soltest_all steps: - checkout @@ -234,6 +242,14 @@ defaults: - store_artifacts: *artifacts_test_results - 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 @@ -748,12 +764,7 @@ jobs: CMAKE_OPTIONS: -DSANITIZE=address MAKEFLAGS: -j 3 CMAKE_BUILD_TYPE: Release - steps: - - checkout - - run: *run_build - - store_artifacts: *artifacts_solc - - persist_to_workspace: *artifacts_executables - - gitter_notify_failure_unless_pr + <<: *steps_build b_ubu_clang: &b_ubu_clang <<: *base_ubuntu2004_clang_large @@ -762,12 +773,7 @@ jobs: CC: clang CXX: clang++ MAKEFLAGS: -j 10 - steps: - - checkout - - run: *run_build - - store_artifacts: *artifacts_solc - - persist_to_workspace: *artifacts_executables - - gitter_notify_failure_unless_pr + <<: *steps_build b_ubu_asan_clang: &b_ubu_asan_clang # This runs a bit faster on large and xlarge but on nightly efficiency matters more. @@ -777,12 +783,7 @@ jobs: CXX: clang++ CMAKE_OPTIONS: -DSANITIZE=address MAKEFLAGS: -j 3 - steps: - - checkout - - run: *run_build - - store_artifacts: *artifacts_solc - - persist_to_workspace: *artifacts_executables - - gitter_notify_failure_unless_pr + <<: *steps_build b_ubu_ubsan_clang: &b_ubu_ubsan_clang # This runs a bit faster on large and xlarge but on nightly efficiency matters more. @@ -792,12 +793,7 @@ jobs: 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 + <<: *steps_build b_ubu_release: &b_ubu_release <<: *b_ubu @@ -949,7 +945,7 @@ jobs: - build/test/tools/solfuzzer - gitter_notify_failure_unless_pr - t_osx_soltest: + t_osx_soltest: &t_osx_soltest <<: *base_osx environment: EVM: << pipeline.parameters.evm-version >> @@ -957,11 +953,9 @@ jobs: TERM: xterm steps: - checkout - - restore_cache: - keys: - - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} - - attach_workspace: - at: . + - when: + condition: true + <<: *steps_install_dependencies_osx - run: *run_soltest - store_test_results: *store_test_results - store_artifacts: *artifacts_test_results @@ -971,11 +965,9 @@ jobs: <<: *base_osx steps: - checkout - - restore_cache: - keys: - - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} - - attach_workspace: - at: . + - when: + condition: true + <<: *steps_install_dependencies_osx - run: *run_cmdline_tests - store_artifacts: *artifacts_test_results - gitter_notify_failure_unless_pr From bce5f9e0da5d96b4f0ed715d3138775016e6337f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 8 Feb 2022 14:55:49 +0100 Subject: [PATCH 0247/1704] CI: Store all artifacts in steps_build so that we can use it for b_ubu --- .circleci/config.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index be4940c636..6069ba4fbb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -219,6 +219,8 @@ defaults: - 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 @@ -747,14 +749,7 @@ jobs: # 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. <<: *base_ubuntu2004_xlarge - 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_build # x64 ASAN build, for testing for memory related bugs b_ubu_asan: &b_ubu_asan From bdf84c991fe6902cce3bac52a4a970ae5a1bca3f Mon Sep 17 00:00:00 2001 From: yatharthagoenka Date: Sat, 4 Sep 2021 15:37:18 +0530 Subject: [PATCH 0248/1704] Ci: parameterize the clang sanitizer jobs --- .circleci/config.yml | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6069ba4fbb..39c219bcec 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -604,6 +604,15 @@ defaults: nodejs_version: '14' 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: @@ -770,24 +779,18 @@ jobs: MAKEFLAGS: -j 10 <<: *steps_build - b_ubu_asan_clang: &b_ubu_asan_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=address - MAKEFLAGS: -j 3 - <<: *steps_build - - b_ubu_ubsan_clang: &b_ubu_ubsan_clang + b_ubu_san_clang: # This runs a bit faster on large and xlarge but on nightly efficiency matters more. + parameters: + cmake_options: + type: string <<: *base_ubuntu2004_clang environment: + TERM: xterm CC: clang CXX: clang++ - CMAKE_OPTIONS: -DSANITIZE=undefined MAKEFLAGS: -j 3 + CMAKE_OPTIONS: << parameters.cmake_options >> <<: *steps_build b_ubu_release: &b_ubu_release @@ -1506,13 +1509,13 @@ workflows: # ASan build and tests - 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_clang_soltest: *workflow_ubuntu2004_asan_clang - t_ubu_asan_cli: *workflow_ubuntu2004_asan # 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_cli: *workflow_ubuntu2004_ubsan_clang From 46075d04d953981119f6376851051334076cf946 Mon Sep 17 00:00:00 2001 From: Marenz Date: Tue, 1 Feb 2022 15:42:08 +0100 Subject: [PATCH 0249/1704] Include used events in ``--hashes`` output --- libsolidity/ast/AST.cpp | 20 ++++++++++++------ libsolidity/ast/AST.h | 3 ++- libsolidity/interface/ABI.cpp | 2 +- libsolidity/interface/CompilerStack.cpp | 21 ++++++++++++------- libsolidity/interface/CompilerStack.h | 2 +- libsolidity/interface/Natspec.cpp | 2 +- libsolidity/interface/StandardCompiler.cpp | 2 +- solc/CommandLineInterface.cpp | 20 +++++++++--------- test/cmdlineTests/hashes/output | 1 + test/libsolidity/SemanticTest.cpp | 2 +- .../tools/ossfuzz/SolidityEvmoneInterface.cpp | 2 +- test/tools/ossfuzz/SolidityEvmoneInterface.h | 2 +- 12 files changed, 47 insertions(+), 32 deletions(-) diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index f2b7369b71..2a7609de85 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -192,7 +192,7 @@ FunctionDefinition const* ContractDefinition::receiveFunction() const return nullptr; } -vector const& ContractDefinition::interfaceEvents() const +vector const& ContractDefinition::definedInterfaceEvents() const { return m_interfaceEvents.init([&]{ set eventsSeen; @@ -213,11 +213,20 @@ vector const& ContractDefinition::interfaceEvents() cons interfaceEvents.push_back(e); } } - return interfaceEvents; }); } +vector const ContractDefinition::usedInterfaceEvents() const +{ + solAssert(annotation().creationCallGraph.set(), ""); + + return convertContainer>( + (*annotation().creationCallGraph)->emittedEvents + + (*annotation().deployedCallGraph)->emittedEvents + ); +} + vector ContractDefinition::interfaceErrors(bool _requireCallGraph) const { set result; @@ -227,10 +236,9 @@ vector ContractDefinition::interfaceErrors(bool _require if (_requireCallGraph) solAssert(annotation().creationCallGraph.set(), ""); if (annotation().creationCallGraph.set()) - { - result += (*annotation().creationCallGraph)->usedErrors; - result += (*annotation().deployedCallGraph)->usedErrors; - } + result += + (*annotation().creationCallGraph)->usedErrors + + (*annotation().deployedCallGraph)->usedErrors; return convertContainer>(move(result)); } diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index b7d5db8058..c35c69c9d2 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -519,7 +519,8 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub return ranges::subrange(b, e) | ranges::views::values; } std::vector events() const { return filteredNodes(m_subNodes); } - std::vector const& interfaceEvents() const; + std::vector const& definedInterfaceEvents() const; + std::vector const usedInterfaceEvents() const; /// @returns all errors defined in this contract or any base contract /// and all errors referenced during execution. /// @param _requireCallGraph if false, do not fail if the call graph has not been computed yet. diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index 9c7a645b6f..eab1801c6a 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -101,7 +101,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); abi.emplace(std::move(method)); } - for (auto const& it: _contractDef.interfaceEvents()) + for (auto const& it: _contractDef.definedInterfaceEvents()) { Json::Value event{Json::objectValue}; event["type"] = "event"; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index acf1932956..7a8bc4ddbf 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -81,6 +81,8 @@ #include +#include + #include #include #include @@ -1014,31 +1016,34 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); }); } -Json::Value CompilerStack::contractIdentifiers(string const& _contractName) const +Json::Value CompilerStack::interfaceSymbols(string const& _contractName) const { if (m_stackState < AnalysisPerformed) solThrow(CompilerError, "Analysis was not successful."); - Json::Value contractIdentifiers(Json::objectValue); + Json::Value interfaceSymbols(Json::objectValue); // Always have a methods object - contractIdentifiers["methods"] = Json::objectValue; + interfaceSymbols["methods"] = Json::objectValue; for (auto const& it: contractDefinition(_contractName).interfaceFunctions()) - contractIdentifiers["methods"][it.second->externalSignature()] = it.first.hex(); + interfaceSymbols["methods"][it.second->externalSignature()] = it.first.hex(); for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors()) { string signature = error->functionType(true)->externalSignature(); - contractIdentifiers["errors"][signature] = toHex(toCompactBigEndian(selectorFromSignature32(signature), 4)); + interfaceSymbols["errors"][signature] = toHex(toCompactBigEndian(selectorFromSignature32(signature), 4)); } - for (EventDefinition const* event: contractDefinition(_contractName).interfaceEvents()) + for (EventDefinition const* event: ranges::concat_view( + contractDefinition(_contractName).definedInterfaceEvents(), + contractDefinition(_contractName).usedInterfaceEvents() + )) if (!event->isAnonymous()) { string signature = event->functionType(true)->externalSignature(); - contractIdentifiers["events"][signature] = toHex(u256(h256::Arith(keccak256(signature)))); + interfaceSymbols["events"][signature] = toHex(u256(h256::Arith(keccak256(signature)))); } - return contractIdentifiers; + return interfaceSymbols; } bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) const diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index b1f85dd4df..c1f15a4804 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -328,7 +328,7 @@ class CompilerStack: public langutil::CharStreamProvider Json::Value const& natspecDev(std::string const& _contractName) const; /// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names. - Json::Value contractIdentifiers(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. std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); } diff --git a/libsolidity/interface/Natspec.cpp b/libsolidity/interface/Natspec.cpp index 533cbaa3dd..4496904937 100644 --- a/libsolidity/interface/Natspec.cpp +++ b/libsolidity/interface/Natspec.cpp @@ -78,7 +78,7 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) 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"); if (!value.empty()) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 0e5b8aba46..75876d9353 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1298,7 +1298,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly", wildcardMatchesExperimental)) evmData["legacyAssembly"] = compilerStack.assemblyJSON(contractName); if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.methodIdentifiers", wildcardMatchesExperimental)) - evmData["methodIdentifiers"] = compilerStack.contractIdentifiers(contractName)["methods"]; + evmData["methodIdentifiers"] = compilerStack.interfaceSymbols(contractName)["methods"]; if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.gasEstimates", wildcardMatchesExperimental)) evmData["gasEstimates"] = compilerStack.gasEstimates(contractName); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index ba557918c1..bafd3a7356 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -270,23 +270,23 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract) if (!m_options.compiler.outputs.signatureHashes) return; - Json::Value contractIdentifiers = m_compiler->contractIdentifiers(_contract); + Json::Value interfaceSymbols = m_compiler->interfaceSymbols(_contract); string out = "Function signatures:\n"; - for (auto const& name: contractIdentifiers["methods"].getMemberNames()) - out += contractIdentifiers["methods"][name].asString() + ": " + name + "\n"; + for (auto const& name: interfaceSymbols["methods"].getMemberNames()) + out += interfaceSymbols["methods"][name].asString() + ": " + name + "\n"; - if (contractIdentifiers.isMember("errors")) + if (interfaceSymbols.isMember("errors")) { out += "\nError signatures:\n"; - for (auto const& name: contractIdentifiers["errors"].getMemberNames()) - out += contractIdentifiers["errors"][name].asString() + ": " + name + "\n"; + for (auto const& name: interfaceSymbols["errors"].getMemberNames()) + out += interfaceSymbols["errors"][name].asString() + ": " + name + "\n"; } - if (contractIdentifiers.isMember("events")) + if (interfaceSymbols.isMember("events")) { out += "\nEvent signatures:\n"; - for (auto const& name: contractIdentifiers["events"].getMemberNames()) - out += contractIdentifiers["events"][name].asString() + ": " + name + "\n"; + for (auto const& name: interfaceSymbols["events"].getMemberNames()) + out += interfaceSymbols["events"][name].asString() + ": " + name + "\n"; } if (!m_options.output.dir.empty()) @@ -836,7 +836,7 @@ void CommandLineInterface::handleCombinedJSON() m_compiler->runtimeObject(contractName).functionDebugData ); if (m_options.compiler.combinedJsonRequests->signatureHashes) - contractData[g_strSignatureHashes] = m_compiler->contractIdentifiers(contractName)["methods"]; + contractData[g_strSignatureHashes] = m_compiler->interfaceSymbols(contractName)["methods"]; if (m_options.compiler.combinedJsonRequests->natspecDev) contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName); if (m_options.compiler.combinedJsonRequests->natspecUser) diff --git a/test/cmdlineTests/hashes/output b/test/cmdlineTests/hashes/output index 5223d732a3..b010456d39 100644 --- a/test/cmdlineTests/hashes/output +++ b/test/cmdlineTests/hashes/output @@ -10,6 +10,7 @@ Error signatures: Event signatures: 2d4dd5fe18ada5a020a9f5591539a8dc3010a5c074ba6a70e1c956659f02786a: ev(uint256) +81f3fb02f88d32d3bb08c80c9a622ca3b3223292f131c6ad049811f9a8a606dc: libraryEvent(uint256) ======= hashes/input.sol:L ======= Function signatures: diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 342cf24fc2..1f07f177d4 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -435,7 +435,7 @@ TestCase::TestResult SemanticTest::runTest( { soltestAssert( m_allowNonExistingFunctions || - m_compiler.contractIdentifiers(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].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" ); diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp index 49b17930a3..ff9fcf2d8d 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp @@ -58,7 +58,7 @@ optional SolidityCompilationFramework::compileContract() else contractName = m_compilerInput.contractName; evmasm::LinkerObject obj = m_compiler.object(contractName); - Json::Value methodIdentifiers = m_compiler.contractIdentifiers(contractName)["methods"]; + Json::Value methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"]; return CompilerOutput{obj.bytecode, methodIdentifiers}; } } diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.h b/test/tools/ossfuzz/SolidityEvmoneInterface.h index 51f6d5bdcc..da0fed58f2 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.h +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.h @@ -91,7 +91,7 @@ class SolidityCompilationFramework /// @returns method identifiers in contract called @param _contractName. Json::Value methodIdentifiers(std::string const& _contractName) { - return m_compiler.contractIdentifiers(_contractName)["methods"]; + return m_compiler.interfaceSymbols(_contractName)["methods"]; } /// @returns Compilation output comprising EVM bytecode and list of /// method identifiers in contract if compilation is successful, From d511fe93ab480f22a55e8cb6329abb20ad5c8712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 24 Jan 2022 14:01:58 +0100 Subject: [PATCH 0250/1704] CI: Fix job name for PRBMath external test --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 39c219bcec..af58d830f1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -583,7 +583,7 @@ defaults: project: uniswap binary_type: native 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 name: t_native_test_ext_prb_math project: prb-math @@ -1454,7 +1454,7 @@ workflows: - 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_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 # Windows build and tests From 3e1aee17455b1d58fa485587df52db4ee7a2fc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 18 Dec 2021 00:08:59 +0100 Subject: [PATCH 0251/1704] externalTests: Clean the build/ dir for Hardhat too --- test/externalTests/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index 10df975256..cd0afb8a49 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -320,7 +320,7 @@ function truffle_clean function hardhat_clean { - rm -rf artifacts/ cache/ + rm -rf build/ artifacts/ cache/ } function run_test From 7fc225384132fff74cda971eaf7927fb07c921b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 22 Dec 2021 17:06:52 +0100 Subject: [PATCH 0252/1704] externalTests: Make comments about failing presets less terse --- test/externalTests/gnosis-v2.sh | 6 +++--- test/externalTests/gnosis.sh | 8 ++++---- test/externalTests/zeppelin.sh | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index 8ad070d113..a48dddf9c1 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -40,12 +40,12 @@ function gnosis_safe_test local config_file="truffle-config.js" 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=( "${compile_only_presets[@]}" - #ir-no-optimize # "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-no-optimize # Compilation fails with "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 legacy-optimize-evm-only legacy-optimize-evm+yul diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index edada2fef3..1b430a9ae5 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -42,11 +42,11 @@ function gnosis_safe_test local compile_only_presets=() local settings_presets=( "${compile_only_presets[@]}" - #ir-no-optimize # "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-no-optimize # Compilation fails with "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 - #legacy-no-optimize # "Stack too deep" error - #legacy-optimize-evm-only # "Stack too deep" error + #legacy-no-optimize # Compilation fails with "Stack too deep" error + #legacy-optimize-evm-only # Compilation fails with "Stack too deep" error legacy-optimize-evm+yul ) diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 5c54ceb8b2..d365dfe2a8 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -44,8 +44,8 @@ function zeppelin_test ) local settings_presets=( "${compile_only_presets[@]}" - #ir-no-optimize # "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-no-optimize # Compilation fails with "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-optimize-evm-only legacy-optimize-evm+yul From a7852cba75e58b86955a0b8a5015b8282ca406b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 17 Dec 2021 22:42:45 +0100 Subject: [PATCH 0253/1704] Python script for parsing eth-gas-reporter output --- scripts/externalTests/parse_eth_gas_report.py | 269 +++++++++++++ .../fixtures/eth_gas_report_gnosis.rst | 381 ++++++++++++++++++ ...test_externalTests_parse_eth_gas_report.py | 219 ++++++++++ 3 files changed, 869 insertions(+) create mode 100755 scripts/externalTests/parse_eth_gas_report.py create mode 100644 test/scripts/fixtures/eth_gas_report_gnosis.rst create mode 100644 test/scripts/test_externalTests_parse_eth_gas_report.py diff --git a/scripts/externalTests/parse_eth_gas_report.py b/scripts/externalTests/parse_eth_gas_report.py new file mode 100755 index 0000000000..c5cc58e587 --- /dev/null +++ b/scripts/externalTests/parse_eth_gas_report.py @@ -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[\w\d.]+) + [|\s]+ Optimizer[ ]enabled:\s*(?P[\w]+) + [|\s]+ Runs:\s*(?P[\d]+) + [|\s]+ Block[ ]limit:\s*(?P[\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[^|]+) + [|\s]+ (?P[^|]+) + [|\s]+ (?P[^|]+) + [|\s]+ (?P[^|]+) + [|\s]+ (?P[^|]+) + [|\s]+ (?P[^|]+) + [|\s]+ (?P[^|]+) + [|\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[^|]+) + [|\s]+ (?P[^|]+) + [|\s]+ (?P[^|]+) + [|\s]+ (?P[^|]+) + [|\s]+ (?P[^|]+)\s*% + [|\s]+ (?P[^|]+) + [|\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) diff --git a/test/scripts/fixtures/eth_gas_report_gnosis.rst b/test/scripts/fixtures/eth_gas_report_gnosis.rst new file mode 100644 index 0000000000..c2e77f9bed --- /dev/null +++ b/test/scripts/fixtures/eth_gas_report_gnosis.rst @@ -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 % · - │ +·----------------------------------------------------------------------------------------------------------------------------------------|-------------|-------------|-------------|---------------|--------------· diff --git a/test/scripts/test_externalTests_parse_eth_gas_report.py b/test/scripts/test_externalTests_parse_eth_gas_report.py new file mode 100644 index 0000000000..cefa0487a2 --- /dev/null +++ b/test/scripts/test_externalTests_parse_eth_gas_report.py @@ -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) From c6094bb0c28a6735b0868ad9373c0240404db881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 18 Dec 2021 00:36:30 +0100 Subject: [PATCH 0254/1704] externalTests: Benchmark reports --- .circleci/config.yml | 9 ++ test/externalTests.sh | 32 ++--- test/externalTests/bleeps.sh | 6 +- test/externalTests/colony.sh | 3 + test/externalTests/common.sh | 166 +++++++++++++++++++++++-- test/externalTests/elementfi.sh | 3 + test/externalTests/ens.sh | 3 + test/externalTests/euler.sh | 3 + test/externalTests/gnosis-v2.sh | 4 + test/externalTests/gnosis.sh | 4 + test/externalTests/perpetual-pools.sh | 3 + test/externalTests/pool-together.sh | 3 + test/externalTests/prb-math.sh | 7 +- test/externalTests/trident.sh | 3 + test/externalTests/uniswap.sh | 4 + test/externalTests/yield-liquidator.sh | 3 + test/externalTests/zeppelin.sh | 3 + 17 files changed, 232 insertions(+), 27 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index af58d830f1..44837d8319 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1205,6 +1205,15 @@ jobs: name: External <> tests (native) command: | test/externalTests/<>.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 b_win: &b_win diff --git a/test/externalTests.sh b/test/externalTests.sh index a5e52c8524..b3b46460bf 100755 --- a/test/externalTests.sh +++ b/test/externalTests.sh @@ -28,26 +28,26 @@ set -e -REPO_ROOT="$(dirname "$0")" - source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/..") + verify_input "$@" printTask "Running external tests..." -"$REPO_ROOT/externalTests/zeppelin.sh" "$@" -"$REPO_ROOT/externalTests/gnosis.sh" "$@" -"$REPO_ROOT/externalTests/gnosis-v2.sh" "$@" -"$REPO_ROOT/externalTests/colony.sh" "$@" -"$REPO_ROOT/externalTests/ens.sh" "$@" -"$REPO_ROOT/externalTests/trident.sh" "$@" -"$REPO_ROOT/externalTests/euler.sh" "$@" -"$REPO_ROOT/externalTests/yield-liquidator.sh" "$@" -"$REPO_ROOT/externalTests/bleeps.sh" "$@" -"$REPO_ROOT/externalTests/pool-together.sh" "$@" -"$REPO_ROOT/externalTests/perpetual-pools.sh" "$@" -"$REPO_ROOT/externalTests/uniswap.sh" "$@" -"$REPO_ROOT/externalTests/prb-math.sh" "$@" -"$REPO_ROOT/externalTests/elementfi.sh" "$@" +"{$REPO_ROOT}/test/externalTests/zeppelin.sh" "$@" +"{$REPO_ROOT}/test/externalTests/gnosis.sh" "$@" +"{$REPO_ROOT}/test/externalTests/gnosis-v2.sh" "$@" +"{$REPO_ROOT}/test/externalTests/colony.sh" "$@" +"{$REPO_ROOT}/test/externalTests/ens.sh" "$@" +"{$REPO_ROOT}/test/externalTests/trident.sh" "$@" +"{$REPO_ROOT}/test/externalTests/euler.sh" "$@" +"{$REPO_ROOT}/test/externalTests/yield-liquidator.sh" "$@" +"{$REPO_ROOT}/test/externalTests/bleeps.sh" "$@" +"{$REPO_ROOT}/test/externalTests/pool-together.sh" "$@" +"{$REPO_ROOT}/test/externalTests/perpetual-pools.sh" "$@" +"{$REPO_ROOT}/test/externalTests/uniswap.sh" "$@" +"{$REPO_ROOT}/test/externalTests/prb-math.sh" "$@" +"{$REPO_ROOT}/test/externalTests/elementfi.sh" "$@" diff --git a/test/externalTests/bleeps.sh b/test/externalTests/bleeps.sh index 561200e219..bd3b0255b1 100755 --- a/test/externalTests/bleeps.sh +++ b/test/externalTests/bleeps.sh @@ -24,13 +24,16 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" SELECTED_PRESETS="$3" 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 { @@ -87,6 +90,7 @@ function bleeps_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" + store_benchmark_report hardhat bleeps "$repo" "$preset" done popd diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index d659899535..e23ce11350 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -73,6 +75,7 @@ function colony_test for preset in $SELECTED_PRESETS; do 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 } diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh index cd0afb8a49..8f7b09eb52 100644 --- a/test/externalTests/common.sh +++ b/test/externalTests/common.sh @@ -20,7 +20,7 @@ #------------------------------------------------------------------------------ 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 @@ -207,9 +207,19 @@ function force_truffle_compiler_settings echo "Compiler version (full): ${SOLCVERSION}" echo "-------------------------------------" - # Forcing the settings should always work by just overwriting the solc object. Forcing them by using a - # dedicated settings objects should only be the fallback. - echo "module.exports['compilers'] = $(truffle_compiler_settings "$solc_path" "$preset" "$evm_version");" >> "$config_file" + local compiler_settings gas_reporter_settings + compiler_settings=$(truffle_compiler_settings "$solc_path" "$preset" "$evm_version") + 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 @@ -278,16 +288,21 @@ function force_hardhat_compiler_settings echo "Compiler version (full): ${SOLCVERSION}" echo "-------------------------------------" - local settings - settings=$(hardhat_compiler_settings "$SOLCVERSION_SHORT" "$preset" "$evm_version") + local compiler_settings gas_reporter_settings + compiler_settings=$(hardhat_compiler_settings "$SOLCVERSION_SHORT" "$preset" "$evm_version") + gas_reporter_settings=$(eth_gas_reporter_settings "$preset") if [[ $config_file == *\.js ]]; then [[ $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 [[ $config_file == *\.ts ]] || assertFail [[ $config_var_name != "" ]] || assertFail - echo "${config_var_name}.solidity = {compilers: [${settings}]}" >> "$config_file" - fi + echo 'import "hardhat-gas-reporter";' + echo "${config_var_name}.gasReporter = ${gas_reporter_settings};" + echo "${config_var_name}.solidity = {compilers: [${compiler_settings}]};" + fi >> "$config_file" } function truffle_verify_compiler_version @@ -368,6 +383,21 @@ function replace_global_solc 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 { local solc_path="$1" @@ -495,3 +525,121 @@ function external_test rm -rf "$DIR" 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 `{"": {"": }}`. + # 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 `{"": {"": }}`, + # 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 `":"`. 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" +} diff --git a/test/externalTests/elementfi.sh b/test/externalTests/elementfi.sh index f52a13ca67..3641eac2b4 100755 --- a/test/externalTests/elementfi.sh +++ b/test/externalTests/elementfi.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -96,6 +98,7 @@ function elementfi_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" + store_benchmark_report hardhat elementfi "$repo" "$preset" done } diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index d3fcb0b13d..734c5d8ae8 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -68,6 +70,7 @@ function ens_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn + store_benchmark_report hardhat ens "$repo" "$preset" done } diff --git a/test/externalTests/euler.sh b/test/externalTests/euler.sh index 485d7ae56a..b3b505051c 100755 --- a/test/externalTests/euler.sh +++ b/test/externalTests/euler.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -68,6 +70,7 @@ function euler_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn + store_benchmark_report hardhat euler "$repo" "$preset" done } diff --git a/test/externalTests/gnosis-v2.sh b/test/externalTests/gnosis-v2.sh index a48dddf9c1..6b0915b6a0 100755 --- a/test/externalTests/gnosis-v2.sh +++ b/test/externalTests/gnosis-v2.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -65,12 +67,14 @@ function gnosis_safe_test neutralize_package_json_hooks force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")" npm install --package-lock + npm install eth-gas-reporter replace_version_pragmas [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist" for preset in $SELECTED_PRESETS; do 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 } diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 1b430a9ae5..82d1892f2d 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -63,12 +65,14 @@ function gnosis_safe_test neutralize_package_json_hooks force_truffle_compiler_settings "$config_file" "$BINARY_TYPE" "${DIR}/solc/dist" "$(first_word "$SELECTED_PRESETS")" npm install --package-lock + npm install eth-gas-reporter replace_version_pragmas [[ $BINARY_TYPE == solcjs ]] && force_solc_modules "${DIR}/solc/dist" for preset in $SELECTED_PRESETS; do 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 } diff --git a/test/externalTests/perpetual-pools.sh b/test/externalTests/perpetual-pools.sh index e1ee9af8f5..8f90ed0b4d 100755 --- a/test/externalTests/perpetual-pools.sh +++ b/test/externalTests/perpetual-pools.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -68,6 +70,7 @@ function perpetual_pools_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" + store_benchmark_report hardhat perpetual-pools "$repo" "$preset" done } diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index a7f5933c0e..b24cd6f4b2 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -72,6 +74,7 @@ function pool_together_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" + store_benchmark_report hardhat pool-together "$repo" "$preset" done } diff --git a/test/externalTests/prb-math.sh b/test/externalTests/prb-math.sh index 53fad2c255..01bdb76f18 100755 --- a/test/externalTests/prb-math.sh +++ b/test/externalTests/prb-math.sh @@ -24,13 +24,16 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" SELECTED_PRESETS="$3" 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 { @@ -70,11 +73,13 @@ function prb_math_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" yarn install --no-lock-file + yarn add hardhat-gas-reporter replace_version_pragmas for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" + store_benchmark_report hardhat prb-math "$repo" "$preset" done } diff --git a/test/externalTests/trident.sh b/test/externalTests/trident.sh index 8e6f35ae33..5e230560d5 100755 --- a/test/externalTests/trident.sh +++ b/test/externalTests/trident.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -92,6 +94,7 @@ function trident_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" + store_benchmark_report hardhat trident "$repo" "$preset" done } diff --git a/test/externalTests/uniswap.sh b/test/externalTests/uniswap.sh index 96a5d2b63b..2f94c6abde 100755 --- a/test/externalTests/uniswap.sh +++ b/test/externalTests/uniswap.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -73,11 +75,13 @@ function uniswap_test yarn add @ethereumjs/tx@3.1.3 yarn install + yarn add hardhat-gas-reporter replace_version_pragmas for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" + store_benchmark_report hardhat uniswap "$repo" "$preset" done } diff --git a/test/externalTests/yield-liquidator.sh b/test/externalTests/yield-liquidator.sh index 6712941e74..1b5b9f1462 100755 --- a/test/externalTests/yield-liquidator.sh +++ b/test/externalTests/yield-liquidator.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -68,6 +70,7 @@ function yield_liquidator_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" + store_benchmark_report hardhat yield_liquidator "$repo" "$preset" done } diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index d365dfe2a8..4094c69364 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -24,6 +24,8 @@ set -e source scripts/common.sh source test/externalTests/common.sh +REPO_ROOT=$(realpath "$(dirname "$0")/../..") + verify_input "$@" BINARY_TYPE="$1" BINARY_PATH="$2" @@ -66,6 +68,7 @@ function zeppelin_test for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn + store_benchmark_report hardhat zeppelin "$repo" "$preset" done } From 60d9aa0d4f34da1f0ccd022e69ca4c45f378ce20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 22 Dec 2021 17:45:20 +0100 Subject: [PATCH 0255/1704] Benchmark report collector job + summary --- .circleci/config.yml | 35 +++++++++++ scripts/externalTests/merge_benchmarks.sh | 60 +++++++++++++++++++ scripts/externalTests/summarize_benchmarks.sh | 53 ++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100755 scripts/externalTests/merge_benchmarks.sh create mode 100755 scripts/externalTests/summarize_benchmarks.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 44837d8319..a1fca20ceb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1216,6 +1216,23 @@ jobs: - reports/externalTests/ - 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 <<: *base_win_powershell_large steps: @@ -1466,6 +1483,24 @@ workflows: - t_ems_ext: *job_native_test_ext_prb_math - 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 - b_win: *workflow_trigger_on_tags - b_win_release: *workflow_trigger_on_tags diff --git a/scripts/externalTests/merge_benchmarks.sh b/scripts/externalTests/merge_benchmarks.sh new file mode 100755 index 0000000000..3e2d7318c7 --- /dev/null +++ b/scripts/externalTests/merge_benchmarks.sh @@ -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: +#