From ed96eb256f7519f350abc83b2eb7c712efe992ce Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Thu, 25 Jan 2024 06:36:50 +0100 Subject: [PATCH 01/47] Yul fuzzer: Support blobhash(uint) global function --- test/tools/ossfuzz/protoToYul.cpp | 9 +++++++++ test/tools/ossfuzz/yulProto.proto | 1 + 2 files changed, 10 insertions(+) diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 1719dec46c..1ba0d599d4 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -599,6 +599,12 @@ void ProtoConverter::visit(UnaryOp const& _x) return; } + if (op == UnaryOp::BLOBHASH && !m_evmVersion.hasBlobHash()) + { + m_output << dictionaryToken(); + return; + } + // The following instructions may lead to change of EVM state and are hence // excluded to avoid false positives. if ( @@ -647,6 +653,9 @@ void ProtoConverter::visit(UnaryOp const& _x) case UnaryOp::BLOCKHASH: m_output << "blockhash"; break; + case UnaryOp::BLOBHASH: + m_output << "blobhash"; + break; } m_output << "("; if (op == UnaryOp::MLOAD) diff --git a/test/tools/ossfuzz/yulProto.proto b/test/tools/ossfuzz/yulProto.proto index 2c10329de6..cf14b887c1 100644 --- a/test/tools/ossfuzz/yulProto.proto +++ b/test/tools/ossfuzz/yulProto.proto @@ -156,6 +156,7 @@ message UnaryOp { EXTCODEHASH = 7; BALANCE = 8; BLOCKHASH = 9; + BLOBHASH = 10; } required UOp op = 1; required Expression operand = 2; From 44da00d3ff7be33c5dc87ad1a62b5aba320bec09 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 6 Feb 2024 12:25:25 +0100 Subject: [PATCH 02/47] Use MCOPY when copying byte arrays --- Changelog.md | 1 + libsolidity/codegen/YulUtilFunctions.cpp | 32 ++++++------ .../debug_info_in_yul_snippet_escaping/output | 2 + .../args | 1 + .../input.sol | 10 ++++ .../output | 51 +++++++++++++++++++ .../args | 1 + .../input.sol | 9 ++++ .../output | 51 +++++++++++++++++++ .../yul_string_format_ascii/output.json | 2 + .../yul_string_format_ascii_long/output.json | 2 + .../semanticTests/various/address_code.sol | 2 +- .../sizeLimits/bytecode_too_large.sol | 4 +- 13 files changed, 150 insertions(+), 18 deletions(-) create mode 100644 test/cmdlineTests/mcopy_bytes_array_returned_from_function/args create mode 100644 test/cmdlineTests/mcopy_bytes_array_returned_from_function/input.sol create mode 100644 test/cmdlineTests/mcopy_bytes_array_returned_from_function/output create mode 100644 test/cmdlineTests/mcopy_string_literal_returned_from_function/args create mode 100644 test/cmdlineTests/mcopy_string_literal_returned_from_function/input.sol create mode 100644 test/cmdlineTests/mcopy_string_literal_returned_from_function/output diff --git a/Changelog.md b/Changelog.md index d20c266d83..3d64b1b80e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * Code Generator: Use ``MCOPY`` instead of ``MLOAD``/``MSTORE`` loop when copying byte arrays. Bugfixes: diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 35fea8ac4b..0dabc8a369 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -88,34 +88,36 @@ std::string YulUtilFunctions::copyToMemoryFunction(bool _fromCalldata, bool _cle "_to_memory"s + (_cleanup ? "_with_cleanup"s : ""s); - return m_functionCollector.createFunction(functionName, [&]() { + return m_functionCollector.createFunction(functionName, [&](std::vector& _args, std::vector&) { + _args = {"src", "dst", "length"}; + if (_fromCalldata) - { return Whiskers(R"( - function (src, dst, length) { - calldatacopy(dst, src, length) - mstore(add(dst, length), 0) - } + calldatacopy(dst, src, length) + mstore(add(dst, length), 0) )") - ("functionName", functionName) ("cleanup", _cleanup) .render(); - } else { - return Whiskers(R"( - function (src, dst, length) { + if (m_evmVersion.hasMcopy()) + return Whiskers(R"( + mcopy(dst, src, length) + mstore(add(dst, length), 0) + )") + ("cleanup", _cleanup) + .render(); + else + return Whiskers(R"( let i := 0 for { } lt(i, length) { i := add(i, 32) } { mstore(add(dst, i), mload(add(src, i))) } mstore(add(dst, length), 0) - } - )") - ("functionName", functionName) - ("cleanup", _cleanup) - .render(); + )") + ("cleanup", _cleanup) + .render(); } }); } diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index 94dfb86426..4c90d9054d 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -180,12 +180,14 @@ object "D_27" { } function copy_memory_to_memory_with_cleanup(src, dst, length) { + let i := 0 for { } lt(i, length) { i := add(i, 32) } { mstore(add(dst, i), mload(add(src, i))) } mstore(add(dst, length), 0) + } function round_up_to_mul_of_32(value) -> result { diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args new file mode 100644 index 0000000000..c74711ba8a --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args @@ -0,0 +1 @@ +--evm-version cancun --no-cbor-metadata --via-ir --optimize --ir-optimized --debug-info none diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/input.sol b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/input.sol new file mode 100644 index 0000000000..05f24d64e7 --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/input.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + function foo() external pure returns (bytes memory) + { + bytes memory ret = "aaaaa"; + return ret; + } +} diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output new file mode 100644 index 0000000000..2441357d97 --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output @@ -0,0 +1,51 @@ +Optimized IR: +/// @use-src 0:"mcopy_bytes_array_returned_from_function/input.sol" +object "C_14" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_14_deployed") + codecopy(_1, dataoffset("C_14_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"mcopy_bytes_array_returned_from_function/input.sol" + object "C_14_deployed" { + code { + { + let _1 := memoryguard(0x80) + if iszero(lt(calldatasize(), 4)) + { + if eq(0xc2985578, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let _2 := 64 + let newFreePtr := add(_1, _2) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 36) + } + mstore(_2, newFreePtr) + mstore(_1, 5) + let _3 := add(_1, 0x20) + mstore(_3, "aaaaa") + let memPos := mload(_2) + mstore(memPos, 0x20) + let length := mload(_1) + mstore(add(memPos, 0x20), length) + mcopy(add(memPos, _2), _3, length) + mstore(add(add(memPos, length), _2), 0) + return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/args b/test/cmdlineTests/mcopy_string_literal_returned_from_function/args new file mode 100644 index 0000000000..c74711ba8a --- /dev/null +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/args @@ -0,0 +1 @@ +--evm-version cancun --no-cbor-metadata --via-ir --optimize --ir-optimized --debug-info none diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/input.sol b/test/cmdlineTests/mcopy_string_literal_returned_from_function/input.sol new file mode 100644 index 0000000000..0251c7cec9 --- /dev/null +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + function foo() external pure returns (string memory) + { + return "MCOPY on Cancun vacation."; + } +} diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/output b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output new file mode 100644 index 0000000000..02740ec0d6 --- /dev/null +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output @@ -0,0 +1,51 @@ +Optimized IR: +/// @use-src 0:"mcopy_string_literal_returned_from_function/input.sol" +object "C_10" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_10_deployed") + codecopy(_1, dataoffset("C_10_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"mcopy_string_literal_returned_from_function/input.sol" + object "C_10_deployed" { + code { + { + let _1 := memoryguard(0x80) + if iszero(lt(calldatasize(), 4)) + { + if eq(0xc2985578, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let _2 := 64 + let newFreePtr := add(_1, _2) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 0x24) + } + mstore(_2, newFreePtr) + mstore(_1, 25) + let _3 := add(_1, 0x20) + mstore(_3, "MCOPY on Cancun vacation.") + let memPos := mload(_2) + mstore(memPos, 0x20) + let length := mload(_1) + mstore(add(memPos, 0x20), length) + mcopy(add(memPos, _2), _3, length) + mstore(add(add(memPos, length), _2), 0) + return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/yul_string_format_ascii/output.json b/test/cmdlineTests/yul_string_format_ascii/output.json index aa830d1abe..1a9612c777 100644 --- a/test/cmdlineTests/yul_string_format_ascii/output.json +++ b/test/cmdlineTests/yul_string_format_ascii/output.json @@ -96,12 +96,14 @@ object \"C_11\" { } function copy_memory_to_memory_with_cleanup(src, dst, length) { + let i := 0 for { } lt(i, length) { i := add(i, 32) } { mstore(add(dst, i), mload(add(src, i))) } mstore(add(dst, length), 0) + } function round_up_to_mul_of_32(value) -> result { diff --git a/test/cmdlineTests/yul_string_format_ascii_long/output.json b/test/cmdlineTests/yul_string_format_ascii_long/output.json index 348e5a0b57..5adeabfdff 100644 --- a/test/cmdlineTests/yul_string_format_ascii_long/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_long/output.json @@ -96,12 +96,14 @@ object \"C_11\" { } function copy_memory_to_memory_with_cleanup(src, dst, length) { + let i := 0 for { } lt(i, length) { i := add(i, 32) } { mstore(add(dst, i), mload(add(src, i))) } mstore(add(dst, length), 0) + } function round_up_to_mul_of_32(value) -> result { diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 80daf116cd..7e48b00ca8 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -8,7 +8,7 @@ contract C { } // To avoid dependency on exact length. - function f() public view returns (bool) { return address(this).code.length > 400; } + function f() public view returns (bool) { return address(this).code.length > 380; } function g() public view returns (uint) { return address(0).code.length; } function h() public view returns (uint) { return address(1).code.length; } } diff --git a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol index 21c48cc433..f22b9755d6 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol @@ -7,6 +7,6 @@ contract test { } } // ==== -// EVMVersion: >=shanghai +// EVMVersion: >=cancun // ---- -// Warning 5574: (21-27154): Contract code size is 27187 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 5574: (21-27154): Contract code size is 27164 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. From 3122d35a4e8b0d49e20cb71833798d15d6e9ea73 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 14 Feb 2024 14:41:26 +0100 Subject: [PATCH 03/47] ABI decode test case --- .../mcopy_bytes_array_abi_decode/args | 1 + .../mcopy_bytes_array_abi_decode/err | 5 + .../mcopy_bytes_array_abi_decode/input.sol | 9 + .../mcopy_bytes_array_abi_decode/output | 230 ++++++++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 test/cmdlineTests/mcopy_bytes_array_abi_decode/args create mode 100644 test/cmdlineTests/mcopy_bytes_array_abi_decode/err create mode 100644 test/cmdlineTests/mcopy_bytes_array_abi_decode/input.sol create mode 100644 test/cmdlineTests/mcopy_bytes_array_abi_decode/output diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/args b/test/cmdlineTests/mcopy_bytes_array_abi_decode/args new file mode 100644 index 0000000000..4a03d8d932 --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/args @@ -0,0 +1 @@ +--evm-version cancun --no-cbor-metadata --via-ir --ir --debug-info none diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/err b/test/cmdlineTests/mcopy_bytes_array_abi_decode/err new file mode 100644 index 0000000000..de32e66295 --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/err @@ -0,0 +1,5 @@ +Warning: Statement has no effect. + --> mcopy_bytes_array_abi_decode/input.sol:7:9: + | +7 | abi.decode("abcd", (bytes)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/input.sol b/test/cmdlineTests/mcopy_bytes_array_abi_decode/input.sol new file mode 100644 index 0000000000..07d66f800e --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + function foo() external pure + { + abi.decode("abcd", (bytes)); + } +} diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/output b/test/cmdlineTests/mcopy_bytes_array_abi_decode/output new file mode 100644 index 0000000000..2a24ec834f --- /dev/null +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/output @@ -0,0 +1,230 @@ +IR: + +/// @use-src 0:"mcopy_bytes_array_abi_decode/input.sol" +object "C_15" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_15() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_15_deployed"), datasize("C_15_deployed")) + + return(_1, datasize("C_15_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_15() { + + } + + } + /// @use-src 0:"mcopy_bytes_array_abi_decode/input.sol" + object "C_15_deployed" { + code { + + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xc2985578 + { + // foo() + + external_fun_foo_14() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_foo_14() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_foo_14() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function round_up_to_mul_of_32(value) -> result { + result := and(add(value, 31), not(31)) + } + + function panic_error_0x41() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x41) + revert(0, 0x24) + } + + function finalize_allocation(memPtr, size) { + let newFreePtr := add(memPtr, round_up_to_mul_of_32(size)) + // protect against overflow + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() } + mstore(64, newFreePtr) + } + + function allocate_memory(size) -> memPtr { + memPtr := allocate_unbounded() + finalize_allocation(memPtr, size) + } + + function array_allocation_size_t_string_memory_ptr(length) -> size { + // Make sure we can allocate memory without overflow + if gt(length, 0xffffffffffffffff) { panic_error_0x41() } + + size := round_up_to_mul_of_32(length) + + // add length slot + size := add(size, 0x20) + + } + + function allocate_memory_array_t_string_memory_ptr(length) -> memPtr { + let allocSize := array_allocation_size_t_string_memory_ptr(length) + memPtr := allocate_memory(allocSize) + + mstore(memPtr, length) + + } + + function store_literal_in_memory_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77(memPtr) { + + mstore(add(memPtr, 0), "abcd") + + } + + function copy_literal_to_memory_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77() -> memPtr { + memPtr := allocate_memory_array_t_string_memory_ptr(4) + store_literal_in_memory_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77(add(memPtr, 32)) + } + + function convert_t_stringliteral_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77_to_t_bytes_memory_ptr() -> converted { + converted := copy_literal_to_memory_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77() + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d() { + revert(0, 0) + } + + function revert_error_987264b3b1d58a9c7f8255e93e81c77d86d6299019c33110a076957a3e06e2ae() { + revert(0, 0) + } + + function array_allocation_size_t_bytes_memory_ptr(length) -> size { + // Make sure we can allocate memory without overflow + if gt(length, 0xffffffffffffffff) { panic_error_0x41() } + + size := round_up_to_mul_of_32(length) + + // add length slot + size := add(size, 0x20) + + } + + function copy_memory_to_memory_with_cleanup(src, dst, length) { + + mcopy(dst, src, length) + mstore(add(dst, length), 0) + + } + + function abi_decode_available_length_t_bytes_memory_ptr_fromMemory(src, length, end) -> array { + array := allocate_memory(array_allocation_size_t_bytes_memory_ptr(length)) + mstore(array, length) + let dst := add(array, 0x20) + if gt(add(src, length), end) { revert_error_987264b3b1d58a9c7f8255e93e81c77d86d6299019c33110a076957a3e06e2ae() } + copy_memory_to_memory_with_cleanup(src, dst, length) + } + + // bytes + function abi_decode_t_bytes_memory_ptr_fromMemory(offset, end) -> array { + if iszero(slt(add(offset, 0x1f), end)) { revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d() } + let length := mload(offset) + array := abi_decode_available_length_t_bytes_memory_ptr_fromMemory(add(offset, 0x20), length, end) + } + + function abi_decode_tuple_t_bytes_memory_ptr_fromMemory(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := mload(add(headStart, 0)) + if gt(offset, 0xffffffffffffffff) { revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() } + + value0 := abi_decode_t_bytes_memory_ptr_fromMemory(add(headStart, offset), dataEnd) + } + + } + + function array_length_t_bytes_memory_ptr(value) -> length { + + length := mload(value) + + } + + function fun_foo_14() { + + let _1_mpos := convert_t_stringliteral_48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77_to_t_bytes_memory_ptr() + + let expr_11_mpos := abi_decode_tuple_t_bytes_memory_ptr_fromMemory(add(_1_mpos, 32), add(add(_1_mpos, 32), array_length_t_bytes_memory_ptr(_1_mpos))) + + } + + } + + data ".metadata" hex"" + } + +} From 4032b5946cc0ae48baf4a65dd35e9401a3d612eb Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Sat, 10 Feb 2024 01:47:07 +0100 Subject: [PATCH 04/47] Add DebugData to AssemblyItem. --- libevmasm/Assembly.cpp | 2 +- libevmasm/AssemblyItem.h | 45 ++++++++--- libevmasm/CommonSubexpressionEliminator.cpp | 76 ++++++++++--------- libevmasm/CommonSubexpressionEliminator.h | 4 +- libevmasm/ControlFlowGraph.cpp | 2 +- libevmasm/ExpressionClasses.cpp | 7 +- libevmasm/ExpressionClasses.h | 2 +- libevmasm/KnownState.cpp | 62 +++++++-------- libevmasm/KnownState.h | 16 ++-- libevmasm/PeepholeOptimiser.cpp | 14 ++-- libevmasm/SimplificationRules.cpp | 12 +-- libevmasm/SimplificationRules.h | 4 +- liblangutil/CMakeLists.txt | 1 + liblangutil/DebugData.h | 70 +++++++++++++++++ libyul/AST.h | 72 +++++------------- libyul/ASTForward.h | 1 - libyul/AsmParser.cpp | 26 +++---- libyul/AsmParser.h | 8 +- libyul/AsmPrinter.cpp | 2 +- libyul/AsmPrinter.h | 4 +- libyul/backends/evm/ConstantOptimiser.h | 6 +- libyul/backends/evm/ControlFlowGraph.h | 22 +++--- .../backends/evm/ControlFlowGraphBuilder.cpp | 8 +- libyul/backends/evm/ControlFlowGraphBuilder.h | 4 +- .../evm/OptimizedEVMCodeTransform.cpp | 2 +- .../backends/evm/OptimizedEVMCodeTransform.h | 2 +- libyul/optimiser/ConditionalSimplifier.cpp | 2 +- libyul/optimiser/ControlFlowSimplifier.cpp | 4 +- libyul/optimiser/ExpressionSplitter.cpp | 2 +- libyul/optimiser/ForLoopConditionIntoBody.cpp | 2 +- .../optimiser/ForLoopConditionOutOfBody.cpp | 2 +- libyul/optimiser/SSATransform.cpp | 4 +- libyul/optimiser/SimplificationRules.cpp | 2 +- libyul/optimiser/SimplificationRules.h | 6 +- libyul/optimiser/StackToMemoryMover.cpp | 4 +- test/tools/yulInterpreter/Inspector.cpp | 4 +- test/tools/yulInterpreter/Inspector.h | 6 +- 37 files changed, 289 insertions(+), 223 deletions(-) create mode 100644 liblangutil/DebugData.h diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index b6e4d0006c..424d3229ca 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -180,7 +180,7 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std: if (c_instructions.count(name)) { - AssemblyItem item{c_instructions.at(name), location}; + AssemblyItem item{c_instructions.at(name), langutil::DebugData::create(location)}; if (!jumpType.empty()) { if (item.instruction() == Instruction::JUMP || item.instruction() == Instruction::JUMPI) diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 93be394733..c2b3603c63 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -24,7 +24,8 @@ #include #include -#include +#include +#include #include #include #include @@ -64,16 +65,16 @@ class AssemblyItem public: enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; - AssemblyItem(u256 _push, langutil::SourceLocation _location = langutil::SourceLocation()): - AssemblyItem(Push, std::move(_push), std::move(_location)) { } - AssemblyItem(Instruction _i, langutil::SourceLocation _location = langutil::SourceLocation()): + AssemblyItem(u256 _push, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): + AssemblyItem(Push, std::move(_push), std::move(_debugData)) { } + AssemblyItem(Instruction _i, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): m_type(Operation), m_instruction(_i), - m_location(std::move(_location)) + m_debugData(std::move(_debugData)) {} - AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::SourceLocation _location = langutil::SourceLocation()): + AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): m_type(_type), - m_location(std::move(_location)) + m_debugData(std::move(_debugData)) { if (m_type == Operation) m_instruction = Instruction(uint8_t(_data)); @@ -83,7 +84,8 @@ class AssemblyItem explicit AssemblyItem(bytes _verbatimData, size_t _arguments, size_t _returnVariables): m_type(VerbatimBytecode), m_instruction{}, - m_verbatimBytecode{{_arguments, _returnVariables, std::move(_verbatimData)}} + m_verbatimBytecode{{_arguments, _returnVariables, std::move(_verbatimData)}}, + m_debugData{langutil::DebugData::create()} {} AssemblyItem(AssemblyItem const&) = default; @@ -170,8 +172,29 @@ class AssemblyItem /// @returns true if the assembly item can be used in a functional context. bool canBeFunctional() const; - void setLocation(langutil::SourceLocation const& _location) { m_location = _location; } - langutil::SourceLocation const& location() const { return m_location; } + void setLocation(langutil::SourceLocation const& _location) + { + solAssert(m_debugData); + m_debugData = langutil::DebugData::create( + _location, + m_debugData->originLocation, + m_debugData->astID + ); + } + + langutil::SourceLocation const& location() const + { + solAssert(m_debugData); + return m_debugData->nativeLocation; + } + + void setDebugData(langutil::DebugData::ConstPtr _debugData) + { + solAssert(_debugData); + m_debugData = std::move(_debugData); + } + + langutil::DebugData::ConstPtr debugData() const { return m_debugData; } void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; } static std::optional parseJumpType(std::string const& _jumpType); @@ -196,7 +219,7 @@ class AssemblyItem /// If m_type == VerbatimBytecode, this holds number of arguments, number of /// return variables and verbatim bytecode. std::optional> m_verbatimBytecode; - langutil::SourceLocation m_location; + langutil::DebugData::ConstPtr m_debugData; JumpType m_jumpType = JumpType::Ordinary; /// Pushed value for operations with data to be determined during assembly stage, /// e.g. PushSubSize, PushTag, PushSub, etc. diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index de1e5a364a..cb4eaebff3 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -29,6 +29,7 @@ #include #include +#include using namespace solidity; using namespace solidity::evmasm; @@ -57,9 +58,9 @@ std::vector CommonSubexpressionEliminator::getOptimizedItems() if (!m_state.stackElements().empty()) minHeight = std::min(minHeight, m_state.stackElements().begin()->first); for (int height = minHeight; height <= m_initialState.stackHeight(); ++height) - initialStackContents[height] = m_initialState.stackElement(height, SourceLocation()); + initialStackContents[height] = m_initialState.stackElement(height, langutil::DebugData::create()); for (int height = minHeight; height <= m_state.stackHeight(); ++height) - targetStackContents[height] = m_state.stackElement(height, SourceLocation()); + targetStackContents[height] = m_state.stackElement(height, langutil::DebugData::create()); AssemblyItems items = CSECodeGenerator(m_state.expressionClasses(), m_storeOperations).generateCode( m_initialState.sequenceNumber(), @@ -87,23 +88,24 @@ void CommonSubexpressionEliminator::optimizeBreakingItem() ExpressionClasses& classes = m_state.expressionClasses(); SourceLocation const& itemLocation = m_breakingItem->location(); + langutil::DebugData::ConstPtr debugData{langutil::DebugData::create(itemLocation)}; if (*m_breakingItem == AssemblyItem(Instruction::JUMPI)) { AssemblyItem::JumpType jumpType = m_breakingItem->getJumpType(); - Id condition = m_state.stackElement(m_state.stackHeight() - 1, itemLocation); + Id condition = m_state.stackElement(m_state.stackHeight() - 1, debugData); if (classes.knownNonZero(condition)) { - feedItem(AssemblyItem(Instruction::SWAP1, itemLocation), true); - feedItem(AssemblyItem(Instruction::POP, itemLocation), true); + feedItem(AssemblyItem(Instruction::SWAP1, debugData), true); + feedItem(AssemblyItem(Instruction::POP, debugData), true); - AssemblyItem item(Instruction::JUMP, itemLocation); + AssemblyItem item(Instruction::JUMP, debugData); item.setJumpType(jumpType); m_breakingItem = classes.storeItem(item); } else if (classes.knownZero(condition)) { - AssemblyItem it(Instruction::POP, itemLocation); + AssemblyItem it(Instruction::POP, debugData); feedItem(it, true); feedItem(it, true); m_breakingItem = nullptr; @@ -111,12 +113,12 @@ void CommonSubexpressionEliminator::optimizeBreakingItem() } else if (*m_breakingItem == AssemblyItem(Instruction::RETURN)) { - Id size = m_state.stackElement(m_state.stackHeight() - 1, itemLocation); + Id size = m_state.stackElement(m_state.stackHeight() - 1, debugData); if (classes.knownZero(size)) { - feedItem(AssemblyItem(Instruction::POP, itemLocation), true); - feedItem(AssemblyItem(Instruction::POP, itemLocation), true); - AssemblyItem item(Instruction::STOP, itemLocation); + feedItem(AssemblyItem(Instruction::POP, debugData), true); + feedItem(AssemblyItem(Instruction::POP, debugData), true); + AssemblyItem item(Instruction::STOP, debugData); m_breakingItem = classes.storeItem(item); } } @@ -181,16 +183,16 @@ AssemblyItems CSECodeGenerator::generateCode( assertThrow(!m_classPositions[targetItem.second].empty(), OptimizerException, ""); if (m_classPositions[targetItem.second].count(targetItem.first)) continue; - SourceLocation sourceLocation; + langutil::DebugData::ConstPtr debugData; if (m_expressionClasses.representative(targetItem.second).item) - sourceLocation = m_expressionClasses.representative(targetItem.second).item->location(); + debugData = m_expressionClasses.representative(targetItem.second).item->debugData(); int position = classElementPosition(targetItem.second); if (position < targetItem.first) // it is already at its target, we need another copy - appendDup(position, sourceLocation); + appendDup(position, debugData); else - appendOrRemoveSwap(position, sourceLocation); - appendOrRemoveSwap(targetItem.first, sourceLocation); + appendOrRemoveSwap(position, debugData); + appendOrRemoveSwap(targetItem.first, debugData); } // remove surplus elements @@ -263,7 +265,7 @@ void CSECodeGenerator::addDependencies(Id _c) case Instruction::KECCAK256: { Id length = expr.arguments.at(1); - AssemblyItem offsetInstr(Instruction::SUB, expr.item->location()); + AssemblyItem offsetInstr(Instruction::SUB, expr.item->debugData()); Id offsetToStart = m_expressionClasses.find(offsetInstr, {slot, slotToLoadFrom}); u256 const* o = m_expressionClasses.knownConstant(offsetToStart); u256 const* l = m_expressionClasses.knownConstant(length); @@ -334,7 +336,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) for (Id arg: arguments | ranges::views::reverse) generateClassElement(arg); - SourceLocation const& itemLocation = expr.item->location(); + langutil::DebugData::ConstPtr itemDebugData = expr.item->debugData(); // The arguments are somewhere on the stack now, so it remains to move them at the correct place. // This is quite difficult as sometimes, the values also have to removed in this process // (if canBeRemoved() returns true) and the two arguments can be equal. For now, this is @@ -342,42 +344,42 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) if (arguments.size() == 1) { if (canBeRemoved(arguments[0], _c)) - appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation); + appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData); else - appendDup(classElementPosition(arguments[0]), itemLocation); + appendDup(classElementPosition(arguments[0]), itemDebugData); } else if (arguments.size() == 2) { if (canBeRemoved(arguments[1], _c)) { - appendOrRemoveSwap(classElementPosition(arguments[1]), itemLocation); + appendOrRemoveSwap(classElementPosition(arguments[1]), itemDebugData); if (arguments[0] == arguments[1]) - appendDup(m_stackHeight, itemLocation); + appendDup(m_stackHeight, itemDebugData); else if (canBeRemoved(arguments[0], _c)) { - appendOrRemoveSwap(m_stackHeight - 1, itemLocation); - appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation); + appendOrRemoveSwap(m_stackHeight - 1, itemDebugData); + appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData); } else - appendDup(classElementPosition(arguments[0]), itemLocation); + appendDup(classElementPosition(arguments[0]), itemDebugData); } else { if (arguments[0] == arguments[1]) { - appendDup(classElementPosition(arguments[0]), itemLocation); - appendDup(m_stackHeight, itemLocation); + appendDup(classElementPosition(arguments[0]), itemDebugData); + appendDup(m_stackHeight, itemDebugData); } else if (canBeRemoved(arguments[0], _c)) { - appendOrRemoveSwap(classElementPosition(arguments[0]), itemLocation); - appendDup(classElementPosition(arguments[1]), itemLocation); - appendOrRemoveSwap(m_stackHeight - 1, itemLocation); + appendOrRemoveSwap(classElementPosition(arguments[0]), itemDebugData); + appendDup(classElementPosition(arguments[1]), itemDebugData); + appendOrRemoveSwap(m_stackHeight - 1, itemDebugData); } else { - appendDup(classElementPosition(arguments[1]), itemLocation); - appendDup(classElementPosition(arguments[0]), itemLocation); + appendDup(classElementPosition(arguments[1]), itemDebugData); + appendDup(classElementPosition(arguments[0]), itemDebugData); } } } @@ -398,7 +400,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) !m_generatedItems.empty() && m_generatedItems.back() == AssemblyItem(Instruction::SWAP1)) // this will not append a swap but remove the one that is already there - appendOrRemoveSwap(m_stackHeight - 1, itemLocation); + appendOrRemoveSwap(m_stackHeight - 1, itemDebugData); for (size_t i = 0; i < arguments.size(); ++i) { m_classPositions[m_stack[m_stackHeight - static_cast(i)]].erase(m_stackHeight - static_cast(i)); @@ -467,18 +469,18 @@ bool CSECodeGenerator::removeStackTopIfPossible() return true; } -void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _location) +void CSECodeGenerator::appendDup(int _fromPosition, langutil::DebugData::ConstPtr _debugData) { assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); int instructionNum = 1 + m_stackHeight - _fromPosition; assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); - appendItem(AssemblyItem(dupInstruction(static_cast(instructionNum)), _location)); + appendItem(AssemblyItem(dupInstruction(static_cast(instructionNum)), std::move(_debugData))); m_stack[m_stackHeight] = m_stack[_fromPosition]; m_classPositions[m_stack[m_stackHeight]].insert(m_stackHeight); } -void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location) +void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, langutil::DebugData::ConstPtr _debugData) { assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); if (_fromPosition == m_stackHeight) @@ -486,7 +488,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation cons int instructionNum = m_stackHeight - _fromPosition; assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); - appendItem(AssemblyItem(swapInstruction(static_cast(instructionNum)), _location)); + appendItem(AssemblyItem(swapInstruction(static_cast(instructionNum)), std::move(_debugData))); if (m_stack[m_stackHeight] != m_stack[_fromPosition]) { diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index b0810a9a1d..3e963838a4 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -142,10 +142,10 @@ class CSECodeGenerator bool removeStackTopIfPossible(); /// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position. - void appendDup(int _fromPosition, langutil::SourceLocation const& _location); + void appendDup(int _fromPosition, langutil::DebugData::ConstPtr _debugData); /// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position. /// @note this might also remove the last item if it exactly the same swap instruction. - void appendOrRemoveSwap(int _fromPosition, langutil::SourceLocation const& _location); + void appendOrRemoveSwap(int _fromPosition, langutil::DebugData::ConstPtr _debugData); /// Appends the given assembly item. void appendItem(AssemblyItem const& _item); diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index 9d2927ed9c..5b73fb6d5b 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -275,7 +275,7 @@ void ControlFlowGraph::gatherKnowledge() //@todo in the case of JUMPI, add knowledge about the condition to the state // (for both values of the condition) std::set tags = state->tagsInExpression( - state->stackElement(state->stackHeight(), langutil::SourceLocation{}) + state->stackElement(state->stackHeight(), langutil::DebugData::create()) ); state->feedItem(m_items.at(pc++)); diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index dd66eea328..74de0ae3f4 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -33,6 +33,7 @@ #include #include #include +#include using namespace solidity; using namespace solidity::evmasm; @@ -134,11 +135,11 @@ void ExpressionClasses::forceEqual( m_expressions.insert(exp); } -ExpressionClasses::Id ExpressionClasses::newClass(SourceLocation const& _location) +ExpressionClasses::Id ExpressionClasses::newClass(langutil::DebugData::ConstPtr _debugData) { Expression exp; exp.id = static_cast(m_representatives.size()); - exp.item = storeItem(AssemblyItem(UndefinedItem, (u256(1) << 255) + exp.id, _location)); + exp.item = storeItem(AssemblyItem(UndefinedItem, (u256(1) << 255) + exp.id, std::move(_debugData))); m_representatives.push_back(exp); m_expressions.insert(exp); return exp.id; @@ -226,7 +227,7 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr) std::cout << "to " << match->action().toString() << std::endl; } - return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->location())); + return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->debugData())); } return std::numeric_limits::max(); diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h index 8d4159fc7b..510302e4c7 100644 --- a/libevmasm/ExpressionClasses.h +++ b/libevmasm/ExpressionClasses.h @@ -92,7 +92,7 @@ class ExpressionClasses void forceEqual(Id _id, AssemblyItem const& _item, Ids const& _arguments, bool _copyItem = true); /// @returns the id of a new class which is different to all other classes. - Id newClass(langutil::SourceLocation const& _location); + Id newClass(langutil::DebugData::ConstPtr _debugData); /// @returns true if the values of the given classes are known to be different (on every input). /// @note that this function might still return false for some different inputs. diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 91f798bf38..3878ae0fdd 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -27,6 +27,7 @@ #include #include +#include using namespace solidity; using namespace solidity::evmasm; @@ -114,7 +115,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool for (size_t i = 0; i < _item.returnValues(); ++i) setStackElement( m_stackHeight - static_cast(i), - m_expressionClasses->newClass(_item.location()) + m_expressionClasses->newClass(_item.debugData()) ); } else if (_item.type() != Operation) @@ -137,44 +138,44 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool m_stackHeight + 1, stackElement( m_stackHeight - static_cast(instruction) + static_cast(Instruction::DUP1), - _item.location() + _item.debugData() ) ); else if (SemanticInformation::isSwapInstruction(_item)) swapStackElements( m_stackHeight, m_stackHeight - 1 - static_cast(instruction) + static_cast(Instruction::SWAP1), - _item.location() + _item.debugData() ); else if (instruction != Instruction::POP) { std::vector arguments(static_cast(info.args)); for (size_t i = 0; i < static_cast(info.args); ++i) - arguments[i] = stackElement(m_stackHeight - static_cast(i), _item.location()); + arguments[i] = stackElement(m_stackHeight - static_cast(i), _item.debugData()); switch (_item.instruction()) { case Instruction::SSTORE: - op = storeInStorage(arguments[0], arguments[1], _item.location()); + op = storeInStorage(arguments[0], arguments[1], _item.debugData()); break; case Instruction::SLOAD: setStackElement( m_stackHeight + static_cast(_item.deposit()), - loadFromStorage(arguments[0], _item.location()) + loadFromStorage(arguments[0], _item.debugData()) ); break; case Instruction::MSTORE: - op = storeInMemory(arguments[0], arguments[1], _item.location()); + op = storeInMemory(arguments[0], arguments[1], _item.debugData()); break; case Instruction::MLOAD: setStackElement( m_stackHeight + static_cast(_item.deposit()), - loadFromMemory(arguments[0], _item.location()) + loadFromMemory(arguments[0], _item.debugData()) ); break; case Instruction::KECCAK256: setStackElement( m_stackHeight + static_cast(_item.deposit()), - applyKeccak256(arguments.at(0), arguments.at(1), _item.location()) + applyKeccak256(arguments.at(0), arguments.at(1), _item.debugData()) ); break; default: @@ -276,18 +277,18 @@ bool KnownState::operator==(KnownState const& _other) const return (thisIt == m_stackElements.cend() && otherIt == _other.m_stackElements.cend()); } -ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation const& _location) +ExpressionClasses::Id KnownState::stackElement(int _stackHeight, langutil::DebugData::ConstPtr _debugData) { if (m_stackElements.count(_stackHeight)) return m_stackElements.at(_stackHeight); // Stack element not found (not assigned yet), create new unknown equivalence class. return m_stackElements[_stackHeight] = - m_expressionClasses->find(AssemblyItem(UndefinedItem, _stackHeight, _location)); + m_expressionClasses->find(AssemblyItem(UndefinedItem, _stackHeight, std::move(_debugData))); } -KnownState::Id KnownState::relativeStackElement(int _stackOffset, SourceLocation const& _location) +KnownState::Id KnownState::relativeStackElement(int _stackOffset, langutil::DebugData::ConstPtr _debugData) { - return stackElement(m_stackHeight + _stackOffset, _location); + return stackElement(m_stackHeight + _stackOffset, std::move(_debugData)); } void KnownState::clearTagUnions() @@ -307,13 +308,13 @@ void KnownState::setStackElement(int _stackHeight, Id _class) void KnownState::swapStackElements( int _stackHeightA, int _stackHeightB, - SourceLocation const& _location + langutil::DebugData::ConstPtr _debugData ) { assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements."); // ensure they are created - stackElement(_stackHeightA, _location); - stackElement(_stackHeightB, _location); + stackElement(_stackHeightA, _debugData); + stackElement(_stackHeightB, _debugData); std::swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]); } @@ -321,7 +322,8 @@ void KnownState::swapStackElements( KnownState::StoreOperation KnownState::storeInStorage( Id _slot, Id _value, - SourceLocation const& _location) + langutil::DebugData::ConstPtr _debugData +) { if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value) // do not execute the storage if we know that the value is already there @@ -336,7 +338,7 @@ KnownState::StoreOperation KnownState::storeInStorage( storageContents.insert(storageItem); m_storageContent = std::move(storageContents); - AssemblyItem item(Instruction::SSTORE, _location); + AssemblyItem item(Instruction::SSTORE, std::move(_debugData)); Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber); StoreOperation operation{StoreOperation::Storage, _slot, m_sequenceNumber, id}; m_storageContent[_slot] = _value; @@ -346,16 +348,16 @@ KnownState::StoreOperation KnownState::storeInStorage( return operation; } -ExpressionClasses::Id KnownState::loadFromStorage(Id _slot, SourceLocation const& _location) +ExpressionClasses::Id KnownState::loadFromStorage(Id _slot, langutil::DebugData::ConstPtr _debugData) { if (m_storageContent.count(_slot)) return m_storageContent.at(_slot); - AssemblyItem item(Instruction::SLOAD, _location); + AssemblyItem item(Instruction::SLOAD, std::move(_debugData)); return m_storageContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber); } -KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, SourceLocation const& _location) +KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, langutil::DebugData::ConstPtr _debugData) { if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value) // do not execute the store if we know that the value is already there @@ -368,7 +370,7 @@ KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, Source memoryContents.insert(memoryItem); m_memoryContent = std::move(memoryContents); - AssemblyItem item(Instruction::MSTORE, _location); + AssemblyItem item(Instruction::MSTORE, std::move(_debugData)); Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber); StoreOperation operation{StoreOperation::Memory, _slot, m_sequenceNumber, id}; m_memoryContent[_slot] = _value; @@ -377,22 +379,22 @@ KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, Source return operation; } -ExpressionClasses::Id KnownState::loadFromMemory(Id _slot, SourceLocation const& _location) +ExpressionClasses::Id KnownState::loadFromMemory(Id _slot, langutil::DebugData::ConstPtr _debugData) { if (m_memoryContent.count(_slot)) return m_memoryContent.at(_slot); - AssemblyItem item(Instruction::MLOAD, _location); + AssemblyItem item(Instruction::MLOAD, std::move(_debugData)); return m_memoryContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber); } KnownState::Id KnownState::applyKeccak256( Id _start, Id _length, - SourceLocation const& _location + langutil::DebugData::ConstPtr _debugData ) { - AssemblyItem keccak256Item(Instruction::KECCAK256, _location); + AssemblyItem keccak256Item(Instruction::KECCAK256, _debugData); // Special logic if length is a short constant, otherwise we cannot tell. u256 const* l = m_expressionClasses->knownConstant(_length); // unknown or too large length @@ -403,10 +405,10 @@ KnownState::Id KnownState::applyKeccak256( for (unsigned i = 0; i < length; i += 32) { Id slot = m_expressionClasses->find( - AssemblyItem(Instruction::ADD, _location), + AssemblyItem(Instruction::ADD, _debugData), {_start, m_expressionClasses->find(u256(i))} ); - arguments.push_back(loadFromMemory(slot, _location)); + arguments.push_back(loadFromMemory(slot, _debugData)); } if (m_knownKeccak256Hashes.count({arguments, length})) return m_knownKeccak256Hashes.at({arguments, length}); @@ -418,7 +420,7 @@ KnownState::Id KnownState::applyKeccak256( for (Id a: arguments) data += toBigEndian(*m_expressionClasses->knownConstant(a)); data.resize(length); - v = m_expressionClasses->find(AssemblyItem(u256(util::keccak256(data)), _location)); + v = m_expressionClasses->find(AssemblyItem(u256(util::keccak256(data)), _debugData)); } else v = m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber); @@ -443,7 +445,7 @@ KnownState::Id KnownState::tagUnion(std::set _tags) return m_tagUnions.right.at(_tags); else { - Id id = m_expressionClasses->newClass(SourceLocation()); + Id id = m_expressionClasses->newClass(langutil::DebugData::create()); m_tagUnions.right.insert(make_pair(_tags, id)); return id; } diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h index 9cc22710fa..79426c36f4 100644 --- a/libevmasm/KnownState.h +++ b/libevmasm/KnownState.h @@ -134,9 +134,9 @@ class KnownState /// Retrieves the current equivalence class for the given stack element (or generates a new /// one if it does not exist yet). - Id stackElement(int _stackHeight, langutil::SourceLocation const& _location); + Id stackElement(int _stackHeight, langutil::DebugData::ConstPtr _debugData); /// @returns the stackElement relative to the current stack height. - Id relativeStackElement(int _stackOffset, langutil::SourceLocation const& _location = {}); + Id relativeStackElement(int _stackOffset, langutil::DebugData::ConstPtr _debugData = {}); /// @returns its set of tags if the given expression class is a known tag union; returns a set /// containing the tag if it is a PushTag expression and the empty set otherwise. @@ -155,22 +155,22 @@ class KnownState /// Assigns a new equivalence class to the next sequence number of the given stack element. void setStackElement(int _stackHeight, Id _class); /// Swaps the given stack elements in their next sequence number. - void swapStackElements(int _stackHeightA, int _stackHeightB, langutil::SourceLocation const& _location); + void swapStackElements(int _stackHeightA, int _stackHeightB, langutil::DebugData::ConstPtr _debugData); /// Increments the sequence number, deletes all storage information that might be overwritten /// and stores the new value at the given slot. /// @returns the store operation, which might be invalid if storage was not modified - StoreOperation storeInStorage(Id _slot, Id _value, langutil::SourceLocation const& _location); + StoreOperation storeInStorage(Id _slot, Id _value,langutil::DebugData::ConstPtr _debugData); /// Retrieves the current value at the given slot in storage or creates a new special sload class. - Id loadFromStorage(Id _slot, langutil::SourceLocation const& _location); + Id loadFromStorage(Id _slot, langutil::DebugData::ConstPtr _debugData); /// Increments the sequence number, deletes all memory information that might be overwritten /// and stores the new value at the given slot. /// @returns the store operation, which might be invalid if memory was not modified - StoreOperation storeInMemory(Id _slot, Id _value, langutil::SourceLocation const& _location); + StoreOperation storeInMemory(Id _slot, Id _value, langutil::DebugData::ConstPtr _debugData); /// Retrieves the current value at the given slot in memory or creates a new special mload class. - Id loadFromMemory(Id _slot, langutil::SourceLocation const& _location); + Id loadFromMemory(Id _slot, langutil::DebugData::ConstPtr _debugData); /// Finds or creates a new expression that applies the Keccak-256 hash function to the contents in memory. - Id applyKeccak256(Id _start, Id _length, langutil::SourceLocation const& _location); + Id applyKeccak256(Id _start, Id _length, langutil::DebugData::ConstPtr _debugData); /// @returns a new or already used Id representing the given set of tags. Id tagUnion(std::set _tags); diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index e9231c0a56..257a3727c0 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -119,7 +119,7 @@ struct OpPop: SimplePeepholeOptimizerMethod if (instructionInfo(instr, langutil::EVMVersion()).ret == 1 && !instructionInfo(instr, langutil::EVMVersion()).sideEffects) { for (int j = 0; j < instructionInfo(instr, langutil::EVMVersion()).args; j++) - *_out = {Instruction::POP, _op.location()}; + *_out = {Instruction::POP, _op.debugData()}; return true; } } @@ -142,13 +142,13 @@ struct OpStop: SimplePeepholeOptimizerMethod Instruction instr = _op.instruction(); if (!instructionInfo(instr, langutil::EVMVersion()).sideEffects) { - *_out = {Instruction::STOP, _op.location()}; + *_out = {Instruction::STOP, _op.debugData()}; return true; } } else if (_op.type() == Push) { - *_out = {Instruction::STOP, _op.location()}; + *_out = {Instruction::STOP, _op.debugData()}; return true; } } @@ -208,7 +208,7 @@ struct DoublePush: SimplePeepholeOptimizerMethod if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data()) { *_out = _push1; - *_out = {Instruction::DUP1, _push2.location()}; + *_out = {Instruction::DUP1, _push2.debugData()}; return true; } else @@ -334,7 +334,7 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod _jumpi == Instruction::JUMPI ) { - *_out = AssemblyItem(Instruction::SUB, _eq.location()); + *_out = AssemblyItem(Instruction::SUB, _eq.debugData()); *_out = _pushTag; *_out = _jumpi; return true; @@ -365,7 +365,7 @@ struct DoubleJump: SimplePeepholeOptimizerMethod _pushTag1.data() == _tag1.data() ) { - *_out = AssemblyItem(Instruction::ISZERO, _jumpi.location()); + *_out = AssemblyItem(Instruction::ISZERO, _jumpi.debugData()); *_out = _pushTag2; *_out = _jumpi; *_out = _tag1; @@ -393,7 +393,7 @@ struct JumpToNext: SimplePeepholeOptimizerMethod ) { if (_jump == Instruction::JUMPI) - *_out = AssemblyItem(Instruction::POP, _jump.location()); + *_out = AssemblyItem(Instruction::POP, _jump.debugData()); *_out = _tag; return true; } diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index ef2d68c7fd..5085b2c3c8 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -126,12 +126,12 @@ bool Pattern::matches(Expression const& _expr, ExpressionClasses const& _classes return true; } -AssemblyItem Pattern::toAssemblyItem(SourceLocation const& _location) const +AssemblyItem Pattern::toAssemblyItem(langutil::DebugData::ConstPtr _debugData) const { if (m_type == Operation) - return AssemblyItem(m_instruction, _location); + return AssemblyItem(m_instruction, std::move(_debugData)); else - return AssemblyItem(m_type, data(), _location); + return AssemblyItem(m_type, data(), std::move(_debugData)); } std::string Pattern::toString() const @@ -199,7 +199,7 @@ u256 const& Pattern::data() const return *m_data; } -ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location) +ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, langutil::DebugData::ConstPtr const& _debugData) { if (_pattern.matchGroup()) { @@ -209,10 +209,10 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation c else { hasId = false; - item = _pattern.toAssemblyItem(_location); + item = _pattern.toAssemblyItem(_debugData); } for (auto const& arg: _pattern.arguments()) - arguments.emplace_back(arg, _location); + arguments.emplace_back(arg, _debugData); } std::string ExpressionTemplate::toString() const diff --git a/libevmasm/SimplificationRules.h b/libevmasm/SimplificationRules.h index b3f8da3c7f..fadad36084 100644 --- a/libevmasm/SimplificationRules.h +++ b/libevmasm/SimplificationRules.h @@ -111,7 +111,7 @@ class Pattern unsigned matchGroup() const { return m_matchGroup; } bool matches(Expression const& _expr, ExpressionClasses const& _classes) const; - AssemblyItem toAssemblyItem(langutil::SourceLocation const& _location) const; + AssemblyItem toAssemblyItem(langutil::DebugData::ConstPtr _debugData) const; std::vector arguments() const { return m_arguments; } /// @returns the id of the matched expression if this pattern is part of a match group. @@ -149,7 +149,7 @@ struct ExpressionTemplate { using Expression = ExpressionClasses::Expression; using Id = ExpressionClasses::Id; - explicit ExpressionTemplate(Pattern const& _pattern, langutil::SourceLocation const& _location); + explicit ExpressionTemplate(Pattern const& _pattern, langutil::DebugData::ConstPtr const& _debugData); std::string toString() const; bool hasId = false; /// Id of the matched expression, if available. diff --git a/liblangutil/CMakeLists.txt b/liblangutil/CMakeLists.txt index 53be57e79d..054d01d918 100644 --- a/liblangutil/CMakeLists.txt +++ b/liblangutil/CMakeLists.txt @@ -3,6 +3,7 @@ set(sources Common.h CharStream.cpp CharStream.h + DebugData.h DebugInfoSelection.cpp DebugInfoSelection.h ErrorReporter.cpp diff --git a/liblangutil/DebugData.h b/liblangutil/DebugData.h new file mode 100644 index 0000000000..70259bd039 --- /dev/null +++ b/liblangutil/DebugData.h @@ -0,0 +1,70 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include +#include +#include + +namespace solidity::langutil +{ + +struct DebugData +{ + typedef typename std::shared_ptr ConstPtr; + + explicit DebugData( + langutil::SourceLocation _nativeLocation = {}, + langutil::SourceLocation _originLocation = {}, + std::optional _astID = {} + ): + nativeLocation(std::move(_nativeLocation)), + originLocation(std::move(_originLocation)), + astID(_astID) + {} + + static DebugData::ConstPtr create( + langutil::SourceLocation _nativeLocation, + langutil::SourceLocation _originLocation = {}, + std::optional _astID = {} + ) + { + return std::make_shared( + std::move(_nativeLocation), + std::move(_originLocation), + _astID + ); + } + + static DebugData::ConstPtr create() + { + static DebugData::ConstPtr emptyDebugData = create({}); + return emptyDebugData; + } + + /// Location in the Yul code. + langutil::SourceLocation nativeLocation; + /// Location in the original source that the Yul code was produced from. + /// Optional. Only present if the Yul source contains location annotations. + langutil::SourceLocation originLocation; + /// ID in the (Solidity) source AST. + std::optional astID; +}; + +} // namespace solidity::langutil diff --git a/libyul/AST.h b/libyul/AST.h index 71419d807f..4e3e92de3d 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include @@ -36,77 +36,43 @@ namespace solidity::yul using Type = YulString; -struct DebugData -{ - explicit DebugData( - langutil::SourceLocation _nativeLocation, - langutil::SourceLocation _originLocation = {}, - std::optional _astID = {} - ): - nativeLocation(std::move(_nativeLocation)), - originLocation(std::move(_originLocation)), - astID(std::move(_astID)) - {} - - static std::shared_ptr create( - langutil::SourceLocation _nativeLocation = {}, - langutil::SourceLocation _originLocation = {}, - std::optional _astID = {} - ) - { - return std::make_shared( - std::move(_nativeLocation), - std::move(_originLocation), - std::move(_astID) - ); - } - - /// Location in the Yul code. - langutil::SourceLocation nativeLocation; - /// Location in the original source that the Yul code was produced from. - /// Optional. Only present if the Yul source contains location annotations. - langutil::SourceLocation originLocation; - /// ID in the (Solidity) source AST. - std::optional astID; -}; - -struct TypedName { std::shared_ptr debugData; YulString name; Type type; }; +struct TypedName { langutil::DebugData::ConstPtr debugData; YulString name; Type type; }; using TypedNameList = std::vector; /// Literal number or string (up to 32 bytes) enum class LiteralKind { Number, Boolean, String }; -struct Literal { std::shared_ptr debugData; LiteralKind kind; YulString value; Type type; }; +struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; YulString value; Type type; }; /// External / internal identifier or label reference -struct Identifier { std::shared_ptr debugData; YulString name; }; +struct Identifier { langutil::DebugData::ConstPtr debugData; YulString name; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// /// Multiple assignment ("x, y := f()"), where the left hand side variables each occupy /// a single stack slot and expects a single expression on the right hand returning /// the same amount of items as the number of variables. -struct Assignment { std::shared_ptr debugData; std::vector variableNames; std::unique_ptr value; }; -struct FunctionCall { std::shared_ptr debugData; Identifier functionName; std::vector arguments; }; +struct Assignment { langutil::DebugData::ConstPtr debugData; std::vector variableNames; std::unique_ptr value; }; +struct FunctionCall { langutil::DebugData::ConstPtr debugData; Identifier functionName; std::vector arguments; }; /// Statement that contains only a single expression -struct ExpressionStatement { std::shared_ptr debugData; Expression expression; }; +struct ExpressionStatement { langutil::DebugData::ConstPtr debugData; Expression expression; }; /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted -struct VariableDeclaration { std::shared_ptr debugData; TypedNameList variables; std::unique_ptr value; }; +struct VariableDeclaration { langutil::DebugData::ConstPtr debugData; TypedNameList variables; std::unique_ptr value; }; /// Block that creates a scope (frees declared stack variables) -struct Block { std::shared_ptr debugData; std::vector statements; }; +struct Block { langutil::DebugData::ConstPtr debugData; std::vector statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") -struct FunctionDefinition { std::shared_ptr debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; +struct FunctionDefinition { langutil::DebugData::ConstPtr debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; /// Conditional execution without "else" part. -struct If { std::shared_ptr debugData; std::unique_ptr condition; Block body; }; +struct If { langutil::DebugData::ConstPtr debugData; std::unique_ptr condition; Block body; }; /// Switch case or default case -struct Case { std::shared_ptr debugData; std::unique_ptr value; Block body; }; +struct Case { langutil::DebugData::ConstPtr debugData; std::unique_ptr value; Block body; }; /// Switch statement -struct Switch { std::shared_ptr debugData; std::unique_ptr expression; std::vector cases; }; -struct ForLoop { std::shared_ptr debugData; Block pre; std::unique_ptr condition; Block post; Block body; }; +struct Switch { langutil::DebugData::ConstPtr debugData; std::unique_ptr expression; std::vector cases; }; +struct ForLoop { langutil::DebugData::ConstPtr debugData; Block pre; std::unique_ptr condition; Block post; Block body; }; /// Break statement (valid within for loop) -struct Break { std::shared_ptr debugData; }; +struct Break { langutil::DebugData::ConstPtr debugData; }; /// Continue statement (valid within for loop) -struct Continue { std::shared_ptr debugData; }; +struct Continue { langutil::DebugData::ConstPtr debugData; }; /// Leave statement (valid within function) -struct Leave { std::shared_ptr debugData; }; +struct Leave { langutil::DebugData::ConstPtr debugData; }; /// Extracts the IR source location from a Yul node. template inline langutil::SourceLocation nativeLocationOf(T const& _node) @@ -133,13 +99,13 @@ template inline langutil::SourceLocation originLocationOf(std::v } /// Extracts the debug data from a Yul node. -template inline std::shared_ptr debugDataOf(T const& _node) +template inline langutil::DebugData::ConstPtr debugDataOf(T const& _node) { return _node.debugData; } /// Extracts the debug data from a Yul node. -template inline std::shared_ptr debugDataOf(std::variant const& _node) +template inline langutil::DebugData::ConstPtr debugDataOf(std::variant const& _node) { return std::visit([](auto const& _arg) { return debugDataOf(_arg); }, _node); } diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index 0e61c6ca12..a4dc5be3f8 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -28,7 +28,6 @@ namespace solidity::yul { -struct DebugData; enum class LiteralKind; struct Literal; struct Label; diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 5d3ec84a4b..3635b096af 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -59,7 +59,7 @@ std::optional toInt(std::string const& _value) } -std::shared_ptr Parser::createDebugData() const +langutil::DebugData::ConstPtr Parser::createDebugData() const { switch (m_useSourceLocationFrom) { @@ -74,7 +74,7 @@ std::shared_ptr Parser::createDebugData() const } void Parser::updateLocationEndFrom( - std::shared_ptr& _debugData, + langutil::DebugData::ConstPtr& _debugData, SourceLocation const& _location ) const { @@ -286,7 +286,7 @@ std::optional>> Parser::parseASTI Block Parser::parseBlock() { RecursionGuard recursionGuard(*this); - Block block = createWithLocation(); + Block block = createWithDebugData(); expectToken(Token::LBrace); while (currentToken() != Token::RBrace) block.statements.emplace_back(parseStatement()); @@ -308,7 +308,7 @@ Statement Parser::parseStatement() return parseBlock(); case Token::If: { - If _if = createWithLocation(); + If _if = createWithDebugData(); advance(); _if.condition = std::make_unique(parseExpression()); _if.body = parseBlock(); @@ -317,7 +317,7 @@ Statement Parser::parseStatement() } case Token::Switch: { - Switch _switch = createWithLocation(); + Switch _switch = createWithDebugData(); advance(); _switch.expression = std::make_unique(parseExpression()); while (currentToken() == Token::Case) @@ -337,21 +337,21 @@ Statement Parser::parseStatement() return parseForLoop(); case Token::Break: { - Statement stmt{createWithLocation()}; + Statement stmt{createWithDebugData()}; checkBreakContinuePosition("break"); advance(); return stmt; } case Token::Continue: { - Statement stmt{createWithLocation()}; + Statement stmt{createWithDebugData()}; checkBreakContinuePosition("continue"); advance(); return stmt; } case Token::Leave: { - Statement stmt{createWithLocation()}; + Statement stmt{createWithDebugData()}; if (!m_insideFunction) m_errorReporter.syntaxError(8149_error, currentLocation(), "Keyword \"leave\" can only be used inside a function."); advance(); @@ -428,7 +428,7 @@ Statement Parser::parseStatement() Case Parser::parseCase() { RecursionGuard recursionGuard(*this); - Case _case = createWithLocation(); + Case _case = createWithDebugData(); if (currentToken() == Token::Default) advance(); else if (currentToken() == Token::Case) @@ -452,7 +452,7 @@ ForLoop Parser::parseForLoop() ForLoopComponent outerForLoopComponent = m_currentForLoopComponent; - ForLoop forLoop = createWithLocation(); + ForLoop forLoop = createWithDebugData(); expectToken(Token::For); m_currentForLoopComponent = ForLoopComponent::ForLoopPre; forLoop.pre = parseBlock(); @@ -559,7 +559,7 @@ std::variant Parser::parseLiteralOrIdentifier() VariableDeclaration Parser::parseVariableDeclaration() { RecursionGuard recursionGuard(*this); - VariableDeclaration varDecl = createWithLocation(); + VariableDeclaration varDecl = createWithDebugData(); expectToken(Token::Let); while (true) { @@ -595,7 +595,7 @@ FunctionDefinition Parser::parseFunctionDefinition() ForLoopComponent outerForLoopComponent = m_currentForLoopComponent; m_currentForLoopComponent = ForLoopComponent::None; - FunctionDefinition funDef = createWithLocation(); + FunctionDefinition funDef = createWithDebugData(); expectToken(Token::Function); funDef.name = expectAsmIdentifier(); expectToken(Token::LParen); @@ -657,7 +657,7 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) TypedName Parser::parseTypedName() { RecursionGuard recursionGuard(*this); - TypedName typedName = createWithLocation(); + TypedName typedName = createWithDebugData(); typedName.name = expectAsmIdentifier(); if (currentToken() == Token::Colon) { diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index da4f09ed22..3e0af66acc 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -118,15 +118,15 @@ class Parser: public langutil::ParserBase ); /// Creates a DebugData object with the correct source location set. - std::shared_ptr createDebugData() const; + langutil::DebugData::ConstPtr createDebugData() const; void updateLocationEndFrom( - std::shared_ptr& _debugData, + langutil::DebugData::ConstPtr& _debugData, langutil::SourceLocation const& _location ) const; - /// Creates an inline assembly node with the current source location. - template T createWithLocation() const + /// Creates an inline assembly node with the current debug data. + template T createWithDebugData() const { T r; r.debugData = createDebugData(); diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index bee213f8ca..b27af03713 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -305,7 +305,7 @@ std::string AsmPrinter::formatSourceLocation( return sourceLocation + (solidityCodeSnippet.empty() ? "" : " ") + solidityCodeSnippet; } -std::string AsmPrinter::formatDebugData(std::shared_ptr const& _debugData, bool _statement) +std::string AsmPrinter::formatDebugData(langutil::DebugData::ConstPtr const& _debugData, bool _statement) { if (!_debugData || m_debugInfoSelection.none()) return ""; diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 7c67c14acf..d3f80b9a09 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -30,7 +30,7 @@ #include #include -#include +#include #include @@ -93,7 +93,7 @@ class AsmPrinter private: std::string formatTypedName(TypedName _variable); std::string appendTypeName(YulString _type, bool _isBoolLiteral = false) const; - std::string formatDebugData(std::shared_ptr const& _debugData, bool _statement); + std::string formatDebugData(langutil::DebugData::ConstPtr const& _debugData, bool _statement); template std::string formatDebugData(T const& _node) { diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index a60d2b2f56..280f50bf9b 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include @@ -74,7 +74,7 @@ class RepresentationFinder RepresentationFinder( EVMDialect const& _dialect, GasMeter const& _meter, - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, std::map& _cache ): m_dialect(_dialect), @@ -100,7 +100,7 @@ class RepresentationFinder EVMDialect const& m_dialect; GasMeter const& m_meter; - std::shared_ptr m_debugData; + langutil::DebugData::ConstPtr m_debugData; /// Counter for the complexity of optimization, will stop when it reaches zero. size_t m_maxSteps = 10000; std::map& m_cache; diff --git a/libyul/backends/evm/ControlFlowGraph.h b/libyul/backends/evm/ControlFlowGraph.h index 853a9e705d..980787c522 100644 --- a/libyul/backends/evm/ControlFlowGraph.h +++ b/libyul/backends/evm/ControlFlowGraph.h @@ -76,7 +76,7 @@ struct FunctionReturnLabelSlot struct VariableSlot { std::reference_wrapper variable; - std::shared_ptr debugData{}; + langutil::DebugData::ConstPtr debugData{}; bool operator==(VariableSlot const& _rhs) const { return &variable.get() == &_rhs.variable.get(); } bool operator<(VariableSlot const& _rhs) const { return &variable.get() < &_rhs.variable.get(); } static constexpr bool canBeFreelyGenerated = false; @@ -85,7 +85,7 @@ struct VariableSlot struct LiteralSlot { u256 value; - std::shared_ptr debugData{}; + langutil::DebugData::ConstPtr debugData{}; bool operator==(LiteralSlot const& _rhs) const { return value == _rhs.value; } bool operator<(LiteralSlot const& _rhs) const { return value < _rhs.value; } static constexpr bool canBeFreelyGenerated = true; @@ -132,7 +132,7 @@ struct CFG struct BuiltinCall { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; std::reference_wrapper builtin; std::reference_wrapper functionCall; /// Number of proper arguments with a position on the stack, excluding literal arguments. @@ -142,7 +142,7 @@ struct CFG }; struct FunctionCall { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; std::reference_wrapper function; std::reference_wrapper functionCall; /// True, if the call is recursive, i.e. entering the function involves a control flow path (potentially involving @@ -153,7 +153,7 @@ struct CFG }; struct Assignment { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; /// The variables being assigned to also occur as ``output`` in the ``Operation`` containing /// the assignment, but are also stored here for convenience. std::vector variables; @@ -176,25 +176,25 @@ struct CFG struct MainExit {}; struct ConditionalJump { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; StackSlot condition; BasicBlock* nonZero = nullptr; BasicBlock* zero = nullptr; }; struct Jump { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; BasicBlock* target = nullptr; /// The only backwards jumps are jumps from loop post to loop condition. bool backwards = false; }; struct FunctionReturn { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; CFG::FunctionInfo* info = nullptr; }; struct Terminated {}; - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; std::vector entries; std::vector operations; /// True, if the block is the beginning of a disconnected subgraph. That is, if no block that is reachable @@ -210,7 +210,7 @@ struct CFG struct FunctionInfo { - std::shared_ptr debugData; + langutil::DebugData::ConstPtr debugData; Scope::Function const& function; FunctionDefinition const& functionDefinition; BasicBlock* entry = nullptr; @@ -238,7 +238,7 @@ struct CFG /// the switch case literals when transforming the control flow of a switch to a sequence of conditional jumps. std::list ghostCalls; - BasicBlock& makeBlock(std::shared_ptr _debugData) + BasicBlock& makeBlock(langutil::DebugData::ConstPtr _debugData) { return blocks.emplace_back(BasicBlock{std::move(_debugData), {}, {}}); } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 9a0a73b35f..4b0da1e80d 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -333,7 +333,7 @@ void ControlFlowGraphBuilder::operator()(If const& _if) void ControlFlowGraphBuilder::operator()(Switch const& _switch) { yulAssert(m_currentBlock, ""); - std::shared_ptr preSwitchDebugData = debugDataOf(_switch); + langutil::DebugData::ConstPtr preSwitchDebugData = debugDataOf(_switch); auto ghostVariableId = m_graph.ghostVariables.size(); YulString ghostVariableName("GHOST[" + std::to_string(ghostVariableId) + "]"); @@ -393,7 +393,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) void ControlFlowGraphBuilder::operator()(ForLoop const& _loop) { - std::shared_ptr preLoopDebugData = debugDataOf(_loop); + langutil::DebugData::ConstPtr preLoopDebugData = debugDataOf(_loop); ScopedSaveAndRestore scopeRestore(m_scope, m_info.scopes.at(&_loop.pre).get()); (*this)(_loop.pre); @@ -608,7 +608,7 @@ Scope::Variable const& ControlFlowGraphBuilder::lookupVariable(YulString _name) } void ControlFlowGraphBuilder::makeConditionalJump( - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, StackSlot _condition, CFG::BasicBlock& _nonZero, CFG::BasicBlock& _zero @@ -627,7 +627,7 @@ void ControlFlowGraphBuilder::makeConditionalJump( } void ControlFlowGraphBuilder::jump( - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, CFG::BasicBlock& _target, bool backwards ) diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index ffe935b0dd..5007d36108 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -67,13 +67,13 @@ class ControlFlowGraphBuilder Scope::Variable const& lookupVariable(YulString _name) const; /// Resets m_currentBlock to enforce a subsequent explicit reassignment. void makeConditionalJump( - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, StackSlot _condition, CFG::BasicBlock& _nonZero, CFG::BasicBlock& _zero ); void jump( - std::shared_ptr _debugData, + langutil::DebugData::ConstPtr _debugData, CFG::BasicBlock& _target, bool _backwards = false ); diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 3df75bb88f..a3052a542f 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -237,7 +237,7 @@ void OptimizedEVMCodeTransform::validateSlot(StackSlot const& _slot, Expression }, _expression); } -void OptimizedEVMCodeTransform::createStackLayout(std::shared_ptr _debugData, Stack _targetStack) +void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr _debugData, Stack _targetStack) { static constexpr auto slotVariableName = [](StackSlot const& _slot) { return std::visit(util::GenericVisitor{ diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.h b/libyul/backends/evm/OptimizedEVMCodeTransform.h index ed03c14530..7e648ca964 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.h +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.h @@ -83,7 +83,7 @@ class OptimizedEVMCodeTransform /// Shuffles m_stack to the desired @a _targetStack while emitting the shuffling code to m_assembly. /// Sets the source locations to the one in @a _debugData. - void createStackLayout(std::shared_ptr _debugData, Stack _targetStack); + void createStackLayout(langutil::DebugData::ConstPtr _debugData, Stack _targetStack); /// Generate code for the given block @a _block. /// Expects the current stack layout m_stack to be a stack layout that is compatible with the diff --git a/libyul/optimiser/ConditionalSimplifier.cpp b/libyul/optimiser/ConditionalSimplifier.cpp index b08b113de0..7119091257 100644 --- a/libyul/optimiser/ConditionalSimplifier.cpp +++ b/libyul/optimiser/ConditionalSimplifier.cpp @@ -78,7 +78,7 @@ void ConditionalSimplifier::operator()(Block& _block) ) { YulString condition = std::get(*_if.condition).name; - std::shared_ptr debugData = _if.debugData; + langutil::DebugData::ConstPtr debugData = _if.debugData; return make_vector( std::move(_s), Assignment{ diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 771b4e86bf..10f479a421 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -37,7 +37,7 @@ namespace { ExpressionStatement makeDiscardCall( - std::shared_ptr const& _debugData, + langutil::DebugData::ConstPtr const& _debugData, BuiltinFunction const& _discardFunction, Expression&& _expression ) @@ -196,7 +196,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch yulAssert(_switchStmt.cases.size() == 1, "Expected only one case!"); auto& switchCase = _switchStmt.cases.front(); - std::shared_ptr debugData = debugDataOf(*_switchStmt.expression); + langutil::DebugData::ConstPtr debugData = debugDataOf(*_switchStmt.expression); YulString type = m_typeInfo.typeOf(*_switchStmt.expression); if (switchCase.value) { diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 986bcb097f..6f0834d776 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -98,7 +98,7 @@ void ExpressionSplitter::outlineExpression(Expression& _expr) visit(_expr); - std::shared_ptr debugData = debugDataOf(_expr); + langutil::DebugData::ConstPtr debugData = debugDataOf(_expr); YulString var = m_nameDispenser.newName({}); YulString type = m_typeInfo.typeOf(_expr); m_statementsToPrefix.emplace_back(VariableDeclaration{ diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index 2dd0832c42..33d8496f08 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -38,7 +38,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) !std::holds_alternative(*_forLoop.condition) ) { - std::shared_ptr debugData = debugDataOf(*_forLoop.condition); + langutil::DebugData::ConstPtr debugData = debugDataOf(*_forLoop.condition); _forLoop.body.statements.emplace( begin(_forLoop.body.statements), diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index 363ecdf0c0..e2451bc6c6 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -54,7 +54,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) return; YulString iszero = m_dialect.booleanNegationFunction()->name; - std::shared_ptr debugData = debugDataOf(*firstStatement.condition); + langutil::DebugData::ConstPtr debugData = debugDataOf(*firstStatement.condition); if ( std::holds_alternative(*firstStatement.condition) && diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index 74a7701494..675d21acc3 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -84,7 +84,7 @@ void IntroduceSSA::operator()(Block& _block) // Replace "let a := v" by "let a_1 := v let a := a_1" // Replace "let a, b := v" by "let a_1, b_1 := v let a := a_1 let b := b_2" - std::shared_ptr debugData = varDecl.debugData; + langutil::DebugData::ConstPtr debugData = varDecl.debugData; std::vector statements; statements.emplace_back(VariableDeclaration{debugData, {}, std::move(varDecl.value)}); TypedNameList newVariables; @@ -111,7 +111,7 @@ void IntroduceSSA::operator()(Block& _block) // Replace "a := v" by "let a_1 := v a := v" // Replace "a, b := v" by "let a_1, b_1 := v a := a_1 b := b_2" - std::shared_ptr debugData = assignment.debugData; + langutil::DebugData::ConstPtr debugData = assignment.debugData; std::vector statements; statements.emplace_back(VariableDeclaration{debugData, {}, std::move(assignment.value)}); TypedNameList newVariables; diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index f8bbcf678a..7fe56026ac 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -234,7 +234,7 @@ evmasm::Instruction Pattern::instruction() const return m_instruction; } -Expression Pattern::toExpression(std::shared_ptr const& _debugData, langutil::EVMVersion _evmVersion) const +Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const { if (matchGroup()) return ASTCopier().translate(matchGroupValue()); diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index e36730f054..5e498bd5c9 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include @@ -42,6 +42,8 @@ struct Dialect; struct AssignedValue; class Pattern; +using DebugData = langutil::DebugData; + /** * Container for all simplification rules. */ @@ -131,7 +133,7 @@ class Pattern /// Turns this pattern into an actual expression. Should only be called /// for patterns resulting from an action, i.e. with match groups assigned. - Expression toExpression(std::shared_ptr const& _debugData, langutil::EVMVersion _evmVersion) const; + Expression toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const; private: Expression const& matchGroupValue() const; diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index ab39669b2d..dedb5cd382 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -36,7 +36,7 @@ namespace { std::vector generateMemoryStore( Dialect const& _dialect, - std::shared_ptr const& _debugData, + langutil::DebugData::ConstPtr const& _debugData, YulString _mpos, Expression _value ) @@ -55,7 +55,7 @@ std::vector generateMemoryStore( return result; } -FunctionCall generateMemoryLoad(Dialect const& _dialect, std::shared_ptr const& _debugData, YulString _mpos) +FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, YulString _mpos) { BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType); yulAssert(memoryLoadFunction, ""); diff --git a/test/tools/yulInterpreter/Inspector.cpp b/test/tools/yulInterpreter/Inspector.cpp index 9c4701d00a..7746483a36 100644 --- a/test/tools/yulInterpreter/Inspector.cpp +++ b/test/tools/yulInterpreter/Inspector.cpp @@ -56,7 +56,7 @@ void InspectedInterpreter::run( InspectedInterpreter{_inspector, _state, _dialect, scope, _disableExternalCalls, _disableMemoryTrace}(_ast); } -Inspector::NodeAction Inspector::queryUser(DebugData const& _data, std::map const& _variables) +Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std::map const& _variables) { if (m_stepMode == NodeAction::RunNode) { @@ -131,7 +131,7 @@ Inspector::NodeAction Inspector::queryUser(DebugData const& _data, std::map(_data.nativeLocation.start), diff --git a/test/tools/yulInterpreter/Inspector.h b/test/tools/yulInterpreter/Inspector.h index 611279c6fe..f4518c7087 100644 --- a/test/tools/yulInterpreter/Inspector.h +++ b/test/tools/yulInterpreter/Inspector.h @@ -53,13 +53,13 @@ class Inspector * @returns NodeAction::RunNode if the current AST node (and all children nodes!) should be * processed without stopping, else NodeAction::StepThroughNode. */ - NodeAction queryUser(DebugData const& _data, std::map const& _variables); + NodeAction queryUser(langutil::DebugData const& _data, std::map const& _variables); void stepMode(NodeAction _action) { m_stepMode = _action; } std::string const& source() const { return m_source; } - void interactiveVisit(DebugData const& _debugData, std::map const& _variables, std::function _visitNode) + void interactiveVisit(langutil::DebugData const& _debugData, std::map const& _variables, std::function _visitNode) { Inspector::NodeAction action = queryUser(_debugData, _variables); @@ -78,7 +78,7 @@ class Inspector } private: - std::string currentSource(DebugData const& _data) const; + std::string currentSource(langutil::DebugData const& _data) const; /// Source of the file std::string const& m_source; From c7b8dcc52f28d68862ef298a94c7ce44f8080346 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Fri, 16 Feb 2024 20:40:05 +0100 Subject: [PATCH 05/47] [test] Add /usr/local/lib to search paths for macOS. --- test/Common.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/Common.cpp b/test/Common.cpp index 14d90d837e..bb4d2db7eb 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -78,7 +78,10 @@ std::optional findInDefaultPath(std::string const& lib_name) fs::current_path() / ".." / "deps" / "lib", fs::current_path() / ".." / ".." / "deps", fs::current_path() / ".." / ".." / "deps" / "lib", - fs::current_path() + fs::current_path(), +#ifdef __APPLE__ + fs::current_path().root_path() / fs::path("usr") / "local" / "lib", +#endif }; for (auto const& basePath: searchPath) { From 9b8ed03823569a48005f0826175a08d5e1281f80 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Sun, 18 Feb 2024 20:53:03 +0100 Subject: [PATCH 06/47] Fix typo in Assembly::fromJSON(..). --- libevmasm/Assembly.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index b6e4d0006c..ab6ac2c63f 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -555,7 +555,7 @@ std::pair, std::vector> Assembly::fromJSO result->importAssemblyItemsFromJSON(_json[".code"], _level == 0 ? parsedSourceList : _sourceList); - if (_json[".auxdata"]) + if (_json.isMember(".auxdata")) { solRequire(_json[".auxdata"].isString(), AssemblyImportException, "Optional member '.auxdata' is not a string."); result->m_auxiliaryData = fromHex(_json[".auxdata"].asString()); From 5aed7515efd427b8f13f0abf3313539166292a3c Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 19 Feb 2024 10:22:12 +0100 Subject: [PATCH 07/47] Use ethers version 6.11.0 on openzeppelin external tests --- test/externalTests/zeppelin.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 64e6f5f0ec..9f72aa4ec9 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -110,6 +110,13 @@ function zeppelin_test # Maybe related to the use of dynamic imports here: https://github.com/NomicFoundation/hardhat/commit/16ae15642951ac324ef7093a3342f7cf3a2a49a4 npm install @nomicfoundation/hardhat-chai-matchers@2.0.3 + # TODO: Remove when OpenZeppelin update to ethers 6.11.1+ + # Prior versions of ethers accepts an object instead of a string as an argument to the toUtf8Bytes function. + # However, starting from Ethers version 6.11.1, string arguments are enforced, + # which causes the introduced assertion to fail in some OpenZeppelin tests. + # See: https://github.com/ethers-io/ethers.js/issues/4583 + npm install ethers@6.11.0 + replace_version_pragmas for preset in $SELECTED_PRESETS; do From c21490f3c2e5c66e224029fc7f9cb482168bd7fe Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 19 Feb 2024 13:34:15 +0100 Subject: [PATCH 08/47] [ci] Remove usage of ETH_EVMONE environment variable. --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b29c46bf8b..f3843a6898 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -498,7 +498,6 @@ defaults: TERM: xterm MAKEFLAGS: -j5 CPUs: 5 - ETH_EVMONE: /usr/local/lib/libevmone.dylib - base_python_small: &base_python_small docker: From 18cabee1e4f60aae045ee9a0a0f2aba6d0d2c279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 9 Jan 2024 14:08:38 +0100 Subject: [PATCH 09/47] CompilerStack: Don't swallow details include in OptimizerException - By catching and asserting it we hide the line number and message. - OptimizerException inherits from util::Exception so just letting it through will have the same effect as asserting. --- libsolidity/interface/CompilerStack.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9b5c87818b..6939441758 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1480,15 +1480,8 @@ void CompilerStack::compileContract( solAssert(!m_viaIR, ""); bytes cborEncodedMetadata = createCBORMetadata(compiledContract, /* _forIR */ false); - try - { - // Run optimiser and compile the contract. - compiler->compileContract(_contract, _otherCompilers, cborEncodedMetadata); - } - catch(evmasm::OptimizerException const&) - { - solAssert(false, "Optimizer exception during compilation"); - } + // Run optimiser and compile the contract. + compiler->compileContract(_contract, _otherCompilers, cborEncodedMetadata); _otherCompilers[compiledContract.contract] = compiler; From f5188158f7edbc672cfc2b5b9125730bbf1886b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 9 Jan 2024 16:44:27 +0100 Subject: [PATCH 10/47] Remove obsolete gas cost tiers - They're no longer used because the cost depends on the EVM version. --- libevmasm/Assembly.cpp | 1 - libevmasm/GasMeter.cpp | 24 +++++++++++++----------- libevmasm/Instruction.cpp | 12 ++++++------ libevmasm/Instruction.h | 2 -- solc/CommandLineInterface.cpp | 2 -- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ab6ac2c63f..3f067ff6bc 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 5982b8a080..e237e32a26 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -274,18 +274,20 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer switch (instructionInfo(_instruction, _evmVersion).gasPriceTier) { - case Tier::Zero: return GasCosts::tier0Gas; - case Tier::Base: return GasCosts::tier1Gas; - case Tier::VeryLow: return GasCosts::tier2Gas; - case Tier::Low: return GasCosts::tier3Gas; - case Tier::Mid: return GasCosts::tier4Gas; - case Tier::High: return GasCosts::tier5Gas; - case Tier::Ext: return GasCosts::tier6Gas; - case Tier::WarmAccess: return GasCosts::warmStorageReadCost; - default: break; + case Tier::Zero: return GasCosts::tier0Gas; + case Tier::Base: return GasCosts::tier1Gas; + case Tier::VeryLow: return GasCosts::tier2Gas; + case Tier::Low: return GasCosts::tier3Gas; + case Tier::Mid: return GasCosts::tier4Gas; + case Tier::High: return GasCosts::tier5Gas; + case Tier::Ext: return GasCosts::tier6Gas; + case Tier::WarmAccess: return GasCosts::warmStorageReadCost; + + case Tier::Special: + case Tier::Invalid: + assertThrow(false, OptimizerException, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); } - assertThrow(false, OptimizerException, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); - return 0; + util::unreachable(); } u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersion _evmVersion) diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index a21f33e183..4e0684b6b4 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -211,7 +211,7 @@ static std::map const c_instructionInfo = { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } }, { Instruction::KECCAK256, { "KECCAK256", 0, 2, 1, true, Tier::Special } }, { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false, Tier::Base } }, - { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, Tier::Balance } }, + { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, Tier::Special } }, { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false, Tier::Base } }, { Instruction::CALLER, { "CALLER", 0, 0, 1, false, Tier::Base } }, { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false, Tier::Base } }, @@ -221,12 +221,12 @@ static std::map const c_instructionInfo = { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false, Tier::Base } }, { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true, Tier::VeryLow } }, { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false, Tier::Base } }, - { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, Tier::ExtCode } }, - { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::ExtCode } }, - { Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } }, - { Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } }, + { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, Tier::Special } }, + { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::Special } }, + { Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } }, + { Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } }, { Instruction::MCOPY, { "MCOPY", 0, 3, 0, true, Tier::VeryLow } }, - { Instruction::EXTCODEHASH, { "EXTCODEHASH", 0, 1, 1, false, Tier::Balance } }, + { Instruction::EXTCODEHASH, { "EXTCODEHASH", 0, 1, 1, false, Tier::Special } }, { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::Ext } }, { Instruction::BLOBHASH, { "BLOBHASH", 0, 1, 1, false, Tier::VeryLow } }, { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 1733863aa5..d29a6feca7 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -297,8 +297,6 @@ enum class Tier High, // 10, Slow Ext, // 20, Ext WarmAccess, // 100, Warm Access - ExtCode, // 700, Extcode - Balance, // 400, Balance Special, // multiparam or otherwise special Invalid // Invalid. }; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 7181bfd4cc..4c08efb51a 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -43,9 +43,7 @@ #include -#include #include -#include #include #include From 686f5cd455c837d6a54f819c8cff66733e2ecc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 9 Jan 2024 15:54:03 +0100 Subject: [PATCH 11/47] Document the Tier enum and constants that come from Execution Specs --- libevmasm/GasMeter.h | 56 +++++++++++++++++++++-------------------- libevmasm/Instruction.h | 25 ++++++++++-------- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index ec19466447..e4bb199257 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -43,32 +43,34 @@ class KnownState; namespace GasCosts { + /// NOTE: The GAS_... constants referenced by comments are defined for each EVM version in the Execution Specs: + /// https://ethereum.github.io/execution-specs/autoapi/ethereum//vm/gas/index.html + static unsigned const stackLimit = 1024; - static unsigned const tier0Gas = 0; - static unsigned const tier1Gas = 2; - static unsigned const tier2Gas = 3; - static unsigned const tier3Gas = 5; - static unsigned const tier4Gas = 8; - static unsigned const tier5Gas = 10; - static unsigned const tier6Gas = 20; - static unsigned const tier7Gas = 0; - static unsigned const expGas = 10; + static unsigned const tier0Gas = 0; // GAS_ZERO (in Execution Specs) + static unsigned const tier1Gas = 2; // GAS_BASE + static unsigned const tier2Gas = 3; // GAS_VERY_LOW + static unsigned const tier3Gas = 5; // GAS_LOW / GAS_FAST_STEP + static unsigned const tier4Gas = 8; // GAS_MID + static unsigned const tier5Gas = 10; // GAS_HIGH + static unsigned const tier6Gas = 20; // GAS_BLOCK_HASH + static unsigned const expGas = 10; // GAS_EXPONENTIATION inline unsigned expByteGas(langutil::EVMVersion _evmVersion) { - return _evmVersion >= langutil::EVMVersion::spuriousDragon() ? 50 : 10; + return _evmVersion >= langutil::EVMVersion::spuriousDragon() ? 50 : 10; // GAS_EXPONENTIATION_PER_BYTE } - static unsigned const keccak256Gas = 30; - static unsigned const keccak256WordGas = 6; + static unsigned const keccak256Gas = 30; // GAS_KECCAK256 + static unsigned const keccak256WordGas = 6; // GAS_KECCAK256_WORD /// Corresponds to ACCESS_LIST_ADDRESS_COST from EIP-2930 static unsigned const accessListAddressCost = 2400; /// Corresponds to ACCESS_LIST_STORAGE_COST from EIP-2930 static unsigned const accessListStorageKeyCost = 1900; /// Corresponds to COLD_SLOAD_COST from EIP-2929 - static unsigned const coldSloadCost = 2100; + static unsigned const coldSloadCost = 2100; // GAS_COLD_SLOAD /// Corresponds to COLD_ACCOUNT_ACCESS_COST from EIP-2929 - static unsigned const coldAccountAccessCost = 2600; + static unsigned const coldAccountAccessCost = 2600; // GAS_COLD_ACCOUNT_ACCESS /// Corresponds to WARM_STORAGE_READ_COST from EIP-2929 - static unsigned const warmStorageReadCost = 100; + static unsigned const warmStorageReadCost = 100; // GAS_WARM_ACCESS inline unsigned sloadGas(langutil::EVMVersion _evmVersion) { if (_evmVersion >= langutil::EVMVersion::berlin()) @@ -81,7 +83,7 @@ namespace GasCosts return 50; } /// Corresponds to SSTORE_SET_GAS - static unsigned const sstoreSetGas = 20000; + static unsigned const sstoreSetGas = 20000; // GAS_STORAGE_SET /// Corresponds to SSTORE_RESET_GAS from EIP-2929 static unsigned const sstoreResetGas = 5000 - coldSloadCost; /// Corresponds to SSTORE_CLEARS_SCHEDULE from EIP-2200 @@ -130,11 +132,11 @@ namespace GasCosts else return 20; } - static unsigned const jumpdestGas = 1; - static unsigned const logGas = 375; - static unsigned const logDataGas = 8; - static unsigned const logTopicGas = 375; - static unsigned const createGas = 32000; + static unsigned const jumpdestGas = 1; // GAS_JUMPDEST + static unsigned const logGas = 375; // GAS_LOG + static unsigned const logDataGas = 8; // GAS_LOG_DATA + static unsigned const logTopicGas = 375; // GAS_LOG_TOPIC + static unsigned const createGas = 32000; // GAS_CREATE inline unsigned callGas(langutil::EVMVersion _evmVersion) { if (_evmVersion >= langutil::EVMVersion::berlin()) @@ -144,10 +146,10 @@ namespace GasCosts else return 40; } - static unsigned const callStipend = 2300; - static unsigned const callValueTransferGas = 9000; - static unsigned const callNewAccountGas = 25000; - inline unsigned selfdestructGas(langutil::EVMVersion _evmVersion) + static unsigned const callStipend = 2300; // GAS_CALL_STIPEND + static unsigned const callValueTransferGas = 9000; // GAS_CALL_VALUE + static unsigned const callNewAccountGas = 25000; // GAS_NEW_ACCOUNT / GAS_SELF_DESTRUCT_NEW_ACCOUNT + inline unsigned selfdestructGas(langutil::EVMVersion _evmVersion) // GAS_SELF_DESTRUCT { if (_evmVersion >= langutil::EVMVersion::berlin()) return coldAccountAccessCost; @@ -164,9 +166,9 @@ namespace GasCosts else return 24000; } - static unsigned const memoryGas = 3; + static unsigned const memoryGas = 3; // GAS_MEMORY / GAS_COPY / GAS_RETURN_DATA_COPY static unsigned const quadCoeffDiv = 512; - static unsigned const createDataGas = 200; + static unsigned const createDataGas = 200; // GAS_CODE_DEPOSIT static unsigned const txGas = 21000; static unsigned const txCreateGas = 53000; static unsigned const txDataZeroGas = 4; diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index d29a6feca7..7d551f71d7 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -287,18 +287,23 @@ inline Instruction logInstruction(unsigned _number) return Instruction(unsigned(Instruction::LOG0) + _number); } +/// Gas price tiers representing static cost of an instruction. +/// Opcodes whose cost is dynamic or depends on EVM version should use the `Special` tier and need +/// dedicated logic in GasMeter (especially in estimateMax()). +/// The tiers loosely follow opcode groups originally defined in the Yellow Paper. enum class Tier { - Zero = 0, // 0, Zero - Base, // 2, Quick - VeryLow, // 3, Fastest - Low, // 5, Fast - Mid, // 8, Mid - High, // 10, Slow - Ext, // 20, Ext - WarmAccess, // 100, Warm Access - Special, // multiparam or otherwise special - Invalid // Invalid. + // NOTE: Tiers should be ordered by cost, since we sometimes perform comparisons between them. + Zero = 0, // 0, Zero + Base, // 2, Quick + VeryLow, // 3, Fastest + Low, // 5, Fast + Mid, // 8, Mid + High, // 10, Slow + Ext, // 20, Ext + WarmAccess, // 100, Warm Access + Special, // multiparam or otherwise special + Invalid, // Invalid. }; /// Information structure for a particular instruction. From a973b4c6bffbd25497fb6b06fa1935ce4b63cbcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 9 Jan 2024 17:13:42 +0100 Subject: [PATCH 12/47] Rename Ext gas cost tier to BlockHash --- libevmasm/GasMeter.cpp | 2 +- libevmasm/Instruction.cpp | 2 +- libevmasm/Instruction.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index e237e32a26..b3d160585e 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -280,7 +280,7 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer case Tier::Low: return GasCosts::tier3Gas; case Tier::Mid: return GasCosts::tier4Gas; case Tier::High: return GasCosts::tier5Gas; - case Tier::Ext: return GasCosts::tier6Gas; + case Tier::BlockHash: return GasCosts::tier6Gas; case Tier::WarmAccess: return GasCosts::warmStorageReadCost; case Tier::Special: diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 4e0684b6b4..ca0dff185a 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -227,7 +227,7 @@ static std::map const c_instructionInfo = { Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } }, { Instruction::MCOPY, { "MCOPY", 0, 3, 0, true, Tier::VeryLow } }, { Instruction::EXTCODEHASH, { "EXTCODEHASH", 0, 1, 1, false, Tier::Special } }, - { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::Ext } }, + { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::BlockHash } }, { Instruction::BLOBHASH, { "BLOBHASH", 0, 1, 1, false, Tier::VeryLow } }, { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } }, { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 7d551f71d7..289469b5ef 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -300,7 +300,7 @@ enum class Tier Low, // 5, Fast Mid, // 8, Mid High, // 10, Slow - Ext, // 20, Ext + BlockHash, // 20 WarmAccess, // 100, Warm Access Special, // multiparam or otherwise special Invalid, // Invalid. From 88ee7d8bb57075c94df3d70fce115357f1290b0c Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 19 Feb 2024 16:28:08 +0100 Subject: [PATCH 13/47] [ci] Remove code signature from universal binary. --- .circleci/config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index b29c46bf8b..672b77c96d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -242,6 +242,13 @@ commands: # -------------------------------------------------------------------------- # Artifact Commands + remove_signature_from_universal_binary: + description: Remove signature from universal binary + steps: + - run: + name: Remove signature from universal binary + command: codesign --remove-signature build/solc/solc + store_artifacts_solc: description: Store compiled solc executable as artifact steps: @@ -1156,6 +1163,7 @@ jobs: - checkout - install_dependencies_osx - run_build + - remove_signature_from_universal_binary - store_artifacts_solc - store_artifacts_yul_phaser - persist_executables_to_workspace_osx From ac54fe1972f25227f9932c8b224ef119360b0e2d Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 11 Jan 2024 13:58:23 +0100 Subject: [PATCH 14/47] Purge using namespace std from test --- scripts/check_style.sh | 1 + test/Common.cpp | 34 +++++++------- test/CommonSyntaxTest.cpp | 69 ++++++++++++++-------------- test/EVMHost.cpp | 55 +++++++++++------------ test/ExecutionFramework.cpp | 45 +++++++++---------- test/FilesystemUtils.cpp | 17 ++++--- test/Metadata.cpp | 24 +++++----- test/TestCase.cpp | 35 +++++++-------- test/TestCaseReader.cpp | 89 ++++++++++++++++++------------------- test/soltest.cpp | 21 +++++---- 10 files changed, 192 insertions(+), 198 deletions(-) diff --git a/scripts/check_style.sh b/scripts/check_style.sh index fe4d19734f..3c9acf86ca 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -39,6 +39,7 @@ NAMESPACE_STD_FREE_FILES=( libyul/backends/evm/* libyul/optimiser/* solc/* + test/* test/contracts/* test/libevmasm/* test/liblangutil/* diff --git a/test/Common.cpp b/test/Common.cpp index bb4d2db7eb..ae725774c4 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -32,8 +32,6 @@ namespace fs = boost::filesystem; namespace po = boost::program_options; -using namespace std; - namespace solidity::test { @@ -147,15 +145,15 @@ void CommonOptions::validate() const ); if (!enforceGasTest) - cout << endl << "WARNING :: Gas cost expectations are not being enforced" << endl << endl; + std::cout << std::endl << "WARNING :: Gas cost expectations are not being enforced" << std::endl << std::endl; else if (evmVersion() != langutil::EVMVersion{} || useABIEncoderV1) { - cout << endl << "WARNING :: Enforcing gas cost expectations with non-standard settings:" << endl; + std::cout << std::endl << "WARNING :: Enforcing gas cost expectations with non-standard settings:" << std::endl; if (evmVersion() != langutil::EVMVersion{}) - cout << "- EVM version: " << evmVersion().name() << " (default: " << langutil::EVMVersion{}.name() << ")" << endl; + std::cout << "- EVM version: " << evmVersion().name() << " (default: " << langutil::EVMVersion{}.name() << ")" << std::endl; if (useABIEncoderV1) - cout << "- ABI coder: v1 (default: v2)" << endl; - cout << endl << "DO NOT COMMIT THE UPDATED EXPECTATIONS." << endl << endl; + std::cout << "- ABI coder: v1 (default: v2)" << std::endl; + std::cout << std::endl << "DO NOT COMMIT THE UPDATED EXPECTATIONS." << std::endl << std::endl; } } @@ -176,7 +174,7 @@ bool CommonOptions::parse(int argc, char const* const* argv) // Request as uint64_t, since uint8_t will be parsed as character by boost. uint64_t eofVersion = arguments["eof-version"].as(); if (eofVersion != 1) - BOOST_THROW_EXCEPTION(std::runtime_error("Invalid EOF version: " + to_string(eofVersion))); + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid EOF version: " + std::to_string(eofVersion))); m_eofVersion = 1; } @@ -213,18 +211,18 @@ bool CommonOptions::parse(int argc, char const* const* argv) return true; } -string CommonOptions::toString(vector const& _selectedOptions) const +std::string CommonOptions::toString(std::vector const& _selectedOptions) const { if (_selectedOptions.empty()) return ""; - auto boolToString = [](bool _value) -> string { return _value ? "true" : "false"; }; + auto boolToString = [](bool _value) -> std::string { return _value ? "true" : "false"; }; // Using std::map to avoid if-else/switch-case block - map optionValueMap = { + std::map optionValueMap = { {"evmVersion", evmVersion().name()}, {"optimize", boolToString(optimize)}, {"useABIEncoderV1", boolToString(useABIEncoderV1)}, - {"batch", to_string(selectedBatch + 1) + "/" + to_string(batches)}, + {"batch", std::to_string(selectedBatch + 1) + "/" + std::to_string(batches)}, {"enforceGasTest", boolToString(enforceGasTest)}, {"enforceGasTestMinValue", enforceGasTestMinValue.str()}, {"disableSemanticTests", boolToString(disableSemanticTests)}, @@ -233,18 +231,18 @@ string CommonOptions::toString(vector const& _selectedOptions) const {"showMetadata", boolToString(showMetadata)} }; - soltestAssert(ranges::all_of(_selectedOptions, [&optionValueMap](string const& _option) { return optionValueMap.count(_option) > 0; })); + soltestAssert(ranges::all_of(_selectedOptions, [&optionValueMap](std::string const& _option) { return optionValueMap.count(_option) > 0; })); - vector optionsWithValues = _selectedOptions | - ranges::views::transform([&optionValueMap](string const& _option) { return _option + "=" + optionValueMap.at(_option); }) | - ranges::to(); + std::vector optionsWithValues = _selectedOptions | + ranges::views::transform([&optionValueMap](std::string const& _option) { return _option + "=" + optionValueMap.at(_option); }) | + ranges::to(); return solidity::util::joinHumanReadable(optionsWithValues); } -void CommonOptions::printSelectedOptions(ostream& _stream, string const& _linePrefix, vector const& _selectedOptions) const +void CommonOptions::printSelectedOptions(std::ostream& _stream, std::string const& _linePrefix, std::vector const& _selectedOptions) const { - _stream << _linePrefix << "Run Settings: " << toString(_selectedOptions) << endl; + _stream << _linePrefix << "Run Settings: " << toString(_selectedOptions) << std::endl; } langutil::EVMVersion CommonOptions::evmVersion() const diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index 0dedd1fb04..3cb908118e 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -34,7 +34,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::util::formatting; @@ -48,10 +47,10 @@ namespace fs = boost::filesystem; namespace { -int parseUnsignedInteger(string::iterator& _it, string::iterator _end) +int parseUnsignedInteger(std::string::iterator& _it, std::string::iterator _end) { if (_it == _end || !util::isDigit(*_it)) - BOOST_THROW_EXCEPTION(runtime_error("Invalid test expectation. Source location expected.")); + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid test expectation. Source location expected.")); int result = 0; while (_it != _end && util::isDigit(*_it)) { @@ -64,7 +63,7 @@ int parseUnsignedInteger(string::iterator& _it, string::iterator _end) } -CommonSyntaxTest::CommonSyntaxTest(string const& _filename, langutil::EVMVersion _evmVersion): +CommonSyntaxTest::CommonSyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion): EVMVersionRestrictedTestCase(_filename), m_sources(m_reader.sources()), m_expectations(parseExpectations(m_reader.stream())), @@ -72,7 +71,7 @@ CommonSyntaxTest::CommonSyntaxTest(string const& _filename, langutil::EVMVersion { } -TestCase::TestResult CommonSyntaxTest::run(ostream& _stream, string const& _linePrefix, bool _formatted) +TestCase::TestResult CommonSyntaxTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { parseCustomExpectations(m_reader.stream()); parseAndAnalyze(); @@ -80,7 +79,7 @@ TestCase::TestResult CommonSyntaxTest::run(ostream& _stream, string const& _line return conclude(_stream, _linePrefix, _formatted); } -TestCase::TestResult CommonSyntaxTest::conclude(ostream& _stream, string const& _linePrefix, bool _formatted) +TestCase::TestResult CommonSyntaxTest::conclude(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { if (expectationsMatch()) return TestResult::Success; @@ -89,16 +88,16 @@ TestCase::TestResult CommonSyntaxTest::conclude(ostream& _stream, string const& return TestResult::Failure; } -void CommonSyntaxTest::printExpectationAndError(ostream& _stream, string const& _linePrefix, bool _formatted) +void CommonSyntaxTest::printExpectationAndError(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - string nextIndentLevel = _linePrefix + " "; - util::AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl; + std::string nextIndentLevel = _linePrefix + " "; + util::AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << std::endl; printExpectedResult(_stream, nextIndentLevel, _formatted); - util::AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl; + util::AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << std::endl; printObtainedResult(_stream, nextIndentLevel, _formatted); } -void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, bool _formatted) const +void CommonSyntaxTest::printSource(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const { if (m_sources.sources.empty()) return; @@ -113,8 +112,8 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, continue; if (outputSourceNames) - _stream << _linePrefix << util::formatting::CYAN << "==== Source: " << name << " ====" << util::formatting::RESET << endl; - vector sourceFormatting(source.length(), util::formatting::RESET); + _stream << _linePrefix << util::formatting::CYAN << "==== Source: " << name << " ====" << util::formatting::RESET << std::endl; + std::vector sourceFormatting(source.length(), util::formatting::RESET); for (auto const& error: m_errorList) if (error.sourceName == name && error.locationStart >= 0 && error.locationEnd >= 0) { @@ -143,7 +142,7 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, _stream << source[i]; else { - _stream << util::formatting::RESET << endl; + _stream << util::formatting::RESET << std::endl; if (i + 1 < source.length()) _stream << _linePrefix << sourceFormatting[i]; } @@ -158,9 +157,9 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, } } -void CommonSyntaxTest::parseCustomExpectations(istream& _stream) +void CommonSyntaxTest::parseCustomExpectations(std::istream& _stream) { - string remainingExpectations = boost::trim_copy(readUntilEnd(_stream)); + std::string remainingExpectations = boost::trim_copy(readUntilEnd(_stream)); soltestAssert( remainingExpectations.empty(), "Found custom expectations not supported by the test case:\n" + remainingExpectations @@ -172,27 +171,27 @@ bool CommonSyntaxTest::expectationsMatch() return m_expectations == m_errorList; } -void CommonSyntaxTest::printExpectedResult(ostream& _stream, string const& _linePrefix, bool _formatted) const +void CommonSyntaxTest::printExpectedResult(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const { printErrorList(_stream, m_expectations, _linePrefix, _formatted); } -void CommonSyntaxTest::printObtainedResult(ostream& _stream, string const& _linePrefix, bool _formatted) const +void CommonSyntaxTest::printObtainedResult(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const { printErrorList(_stream, m_errorList, _linePrefix, _formatted); } void CommonSyntaxTest::printErrorList( - ostream& _stream, - vector const& _errorList, - string const& _linePrefix, + std::ostream& _stream, + std::vector const& _errorList, + std::string const& _linePrefix, bool _formatted ) { if (_errorList.empty()) { if (_formatted) - util::AnsiColorized(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << endl; + util::AnsiColorized(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << std::endl; } else for (auto const& error: _errorList) @@ -220,11 +219,11 @@ void CommonSyntaxTest::printErrorList( _stream << error.locationEnd; _stream << "): "; } - _stream << error.message << endl; + _stream << error.message << std::endl; } } -string CommonSyntaxTest::errorMessage(util::Exception const& _e) +std::string CommonSyntaxTest::errorMessage(util::Exception const& _e) { if (_e.comment() && !_e.comment()->empty()) return boost::replace_all_copy(*_e.comment(), "\n", "\\n"); @@ -232,13 +231,13 @@ string CommonSyntaxTest::errorMessage(util::Exception const& _e) return "NONE"; } -vector CommonSyntaxTest::parseExpectations(istream& _stream) +std::vector CommonSyntaxTest::parseExpectations(std::istream& _stream) { - static string const customExpectationsDelimiter("// ----"); + static std::string const customExpectationsDelimiter("// ----"); - vector expectations; - string line; - while (getline(_stream, line)) + std::vector expectations; + std::string line; + while (std::getline(_stream, line)) { auto it = line.begin(); @@ -254,17 +253,17 @@ vector CommonSyntaxTest::parseExpectations(istream& _stream) if (it == line.end()) continue; auto typeBegin = it; - while (it != line.end() && isalpha(*it, locale::classic())) + while (it != line.end() && isalpha(*it, std::locale::classic())) ++it; - string errorTypeStr(typeBegin, it); - optional errorType = Error::parseErrorType(errorTypeStr); + std::string errorTypeStr(typeBegin, it); + std::optional errorType = Error::parseErrorType(errorTypeStr); if (!errorType.has_value()) - BOOST_THROW_EXCEPTION(runtime_error("Invalid error type: " + errorTypeStr)); + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid error type: " + errorTypeStr)); skipWhitespace(it, line.end()); - optional errorId; + std::optional errorId; if (it != line.end() && util::isDigit(*it)) errorId = ErrorId{static_cast(parseUnsignedInteger(it, line.end()))}; @@ -295,7 +294,7 @@ vector CommonSyntaxTest::parseExpectations(istream& _stream) skipWhitespace(it, line.end()); - string errorMessage(it, line.end()); + std::string errorMessage(it, line.end()); expectations.emplace_back(SyntaxTestError{ errorType.value(), std::move(errorId), diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 7e05ceec3e..9af4d7099d 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -31,16 +31,15 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::test; using namespace evmc::literals; -evmc::VM& EVMHost::getVM(string const& _path) +evmc::VM& EVMHost::getVM(std::string const& _path) { static evmc::VM NullVM{nullptr}; - static map> vms; + static std::map> vms; if (vms.count(_path) == 0) { evmc_loader_error_code errorCode = {}; @@ -48,16 +47,16 @@ evmc::VM& EVMHost::getVM(string const& _path) if (vm && errorCode == EVMC_LOADER_SUCCESS) { if (vm.get_capabilities() & (EVMC_CAPABILITY_EVM1)) - vms[_path] = make_unique(evmc::VM(std::move(vm))); + vms[_path] = std::make_unique(evmc::VM(std::move(vm))); else - cerr << "VM loaded does not support EVM1" << endl; + std::cerr << "VM loaded does not support EVM1" << std::endl; } else { - cerr << "Error loading VM from " << _path; + std::cerr << "Error loading VM from " << _path; if (char const* errorMsg = evmc_last_error_msg()) - cerr << ":" << endl << errorMsg; - cerr << endl; + std::cerr << ":" << std::endl << errorMsg; + std::cerr << std::endl; } } @@ -67,7 +66,7 @@ evmc::VM& EVMHost::getVM(string const& _path) return NullVM; } -bool EVMHost::checkVmPaths(vector const& _vmPaths) +bool EVMHost::checkVmPaths(std::vector const& _vmPaths) { bool evmVmFound = false; for (auto const& path: _vmPaths) @@ -79,7 +78,7 @@ bool EVMHost::checkVmPaths(vector const& _vmPaths) if (vm.has_capability(EVMC_CAPABILITY_EVM1)) { if (evmVmFound) - BOOST_THROW_EXCEPTION(runtime_error("Multiple evm1 evmc vms defined. Please only define one evm1 evmc vm.")); + BOOST_THROW_EXCEPTION(std::runtime_error("Multiple evm1 evmc vms defined. Please only define one evm1 evmc vm.")); evmVmFound = true; } } @@ -92,7 +91,7 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): { if (!m_vm) { - cerr << "Unable to find evmone library" << endl; + std::cerr << "Unable to find evmone library" << std::endl; assertThrow(false, Exception, ""); } @@ -319,7 +318,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept h160 createAddress(keccak256( bytes{static_cast(0xc0 + 21 + encodedNonce.size())} + bytes{0x94} + - bytes(begin(message.sender.bytes), end(message.sender.bytes)) + + bytes(std::begin(message.sender.bytes), std::end(message.sender.bytes)) + encodedNonce ), h160::AlignRight); @@ -332,8 +331,8 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept { h160 createAddress(keccak256( bytes{0xff} + - bytes(begin(message.sender.bytes), end(message.sender.bytes)) + - bytes(begin(message.create2_salt.bytes), end(message.create2_salt.bytes)) + + bytes(std::begin(message.sender.bytes), std::end(message.sender.bytes)) + + bytes(std::begin(message.create2_salt.bytes), std::end(message.create2_salt.bytes)) + keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes() ), h160::AlignRight); @@ -421,7 +420,7 @@ evmc::bytes32 EVMHost::get_block_hash(int64_t _number) const noexcept h160 EVMHost::convertFromEVMC(evmc::address const& _addr) { - return h160(bytes(begin(_addr.bytes), end(_addr.bytes))); + return h160(bytes(std::begin(_addr.bytes), std::end(_addr.bytes))); } evmc::address EVMHost::convertToEVMC(h160 const& _addr) @@ -434,7 +433,7 @@ evmc::address EVMHost::convertToEVMC(h160 const& _addr) h256 EVMHost::convertFromEVMC(evmc::bytes32 const& _data) { - return h256(bytes(begin(_data.bytes), end(_data.bytes))); + return h256(bytes(std::begin(_data.bytes), std::end(_data.bytes))); } evmc::bytes32 EVMHost::convertToEVMC(h256 const& _data) @@ -452,7 +451,7 @@ evmc::Result EVMHost::precompileECRecover(evmc_message const& _message) noexcept // Fixed cost of 3000 gas. constexpr int64_t gas_cost = 3000; - static map const inputOutput{ + static std::map const inputOutput{ { fromHex( "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c" @@ -509,7 +508,7 @@ evmc::Result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept return 600 + 120 * ((size + 31) / 32); }; - static map const inputOutput{ + static std::map const inputOutput{ { bytes{}, { @@ -628,7 +627,7 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex // Fixed 500 or 150 gas. int64_t gas_cost = (Revision < EVMC_ISTANBUL) ? 500 : 150; - static map const inputOutput{ + static std::map const inputOutput{ { fromHex( "0000000000000000000000000000000000000000000000000000000000000000" @@ -896,7 +895,7 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex // Fixed 40000 or 6000 gas. int64_t gas_cost = (Revision < EVMC_ISTANBUL) ? 40000 : 6000; - static map const inputOutput{ + static std::map const inputOutput{ { fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"), { @@ -990,7 +989,7 @@ evmc::Result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess }; // NOTE this is a partial implementation for some inputs. - static map const inputOutput{ + static std::map const inputOutput{ { fromHex( "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa9" @@ -1155,7 +1154,7 @@ evmc::Result EVMHost::precompileBlake2f(evmc_message const&) noexcept evmc::Result EVMHost::precompileGeneric( evmc_message const& _message, - map const& _inOut) noexcept + std::map const& _inOut) noexcept { bytes input(_message.input_data, _message.input_data + _message.input_size); if (_inOut.count(input)) @@ -1202,7 +1201,7 @@ StorageMap const& EVMHost::get_address_storage(evmc::address const& _addr) return accounts[_addr].storage; } -string EVMHostPrinter::state() +std::string EVMHostPrinter::state() { // Print state and execution trace. if (m_host.account_exists(m_account)) @@ -1225,14 +1224,14 @@ void EVMHostPrinter::storage() << m_host.convertFromEVMC(slot) << ": " << m_host.convertFromEVMC(value.current) - << endl; + << std::endl; } void EVMHostPrinter::balance() { m_stateStream << "BALANCE " << m_host.convertFromEVMC(m_host.get_balance(m_account)) - << endl; + << std::endl; } void EVMHostPrinter::selfdestructRecords() @@ -1242,12 +1241,12 @@ void EVMHostPrinter::selfdestructRecords() m_stateStream << "SELFDESTRUCT" << " BENEFICIARY " << m_host.convertFromEVMC(beneficiary) - << endl; + << std::endl; } void EVMHostPrinter::callRecords() { - static auto constexpr callKind = [](evmc_call_kind _kind) -> string + static auto constexpr callKind = [](evmc_call_kind _kind) -> std::string { switch (_kind) { @@ -1270,5 +1269,5 @@ void EVMHostPrinter::callRecords() m_stateStream << callKind(record.kind) << " VALUE " << m_host.convertFromEVMC(record.value) - << endl; + << std::endl; } diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index a18a73de06..9fc36440b3 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -41,7 +41,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::test; @@ -52,7 +51,7 @@ ExecutionFramework::ExecutionFramework(): { } -ExecutionFramework::ExecutionFramework(langutil::EVMVersion _evmVersion, vector const& _vmPaths): +ExecutionFramework::ExecutionFramework(langutil::EVMVersion _evmVersion, std::vector const& _vmPaths): m_evmVersion(_evmVersion), m_optimiserSettings(solidity::frontend::OptimiserSettings::minimal()), m_showMessages(solidity::test::CommonOptions::get().showMessages), @@ -71,7 +70,7 @@ void ExecutionFramework::selectVM(evmc_capabilities _cap) evmc::VM& vm = EVMHost::getVM(path.string()); if (vm.has_capability(_cap)) { - m_evmcHost = make_unique(m_evmVersion, vm); + m_evmcHost = std::make_unique(m_evmVersion, vm); break; } } @@ -87,7 +86,7 @@ void ExecutionFramework::reset() EVMHost::convertToEVMC(u256(1) << 100); } -std::pair ExecutionFramework::compareAndCreateMessage( +std::pair ExecutionFramework::compareAndCreateMessage( bytes const& _result, bytes const& _expectation ) @@ -101,8 +100,8 @@ std::pair ExecutionFramework::compareAndCreateMessage( auto expectedHex = boost::replace_all_copy(util::toHex(_expectation), "0", "."); for (size_t i = 0; i < std::max(resultHex.size(), expectedHex.size()); i += 0x40) { - std::string result{i >= resultHex.size() ? string{} : resultHex.substr(i, 0x40)}; - std::string expected{i > expectedHex.size() ? string{} : expectedHex.substr(i, 0x40)}; + std::string result{i >= resultHex.size() ? std::string{} : resultHex.substr(i, 0x40)}; + std::string expected{i > expectedHex.size() ? std::string{} : expectedHex.substr(i, 0x40)}; message += (result == expected ? " " : " X ") + result + @@ -137,7 +136,7 @@ u256 ExecutionFramework::gasPrice() const u256 ExecutionFramework::blockHash(u256 const& _number) const { return u256{EVMHost::convertFromEVMC( - m_evmcHost->get_block_hash(static_cast(_number & numeric_limits::max())) + m_evmcHost->get_block_hash(static_cast(_number & std::numeric_limits::max())) )}; } @@ -153,12 +152,12 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 if (m_showMessages) { if (_isCreation) - cout << "CREATE " << m_sender.hex() << ":" << endl; + std::cout << "CREATE " << m_sender.hex() << ":" << std::endl; else - cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << endl; + std::cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << std::endl; if (_value > 0) - cout << " value: " << _value << endl; - cout << " in: " << util::toHex(_data) << endl; + std::cout << " value: " << _value << std::endl; + std::cout << " in: " << util::toHex(_data) << std::endl; } evmc_message message{}; message.input_data = _data.data(); @@ -189,19 +188,19 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 unsigned const refundRatio = (m_evmVersion >= langutil::EVMVersion::london() ? 5 : 2); auto const totalGasUsed = InitialGas - result.gas_left; - auto const gasRefund = min(u256(result.gas_refund), totalGasUsed / refundRatio); + auto const gasRefund = std::min(u256(result.gas_refund), totalGasUsed / refundRatio); m_gasUsed = totalGasUsed - gasRefund; m_transactionSuccessful = (result.status_code == EVMC_SUCCESS); if (m_showMessages) { - cout << " out: " << util::toHex(m_output) << endl; - cout << " result: " << static_cast(result.status_code) << endl; - cout << " gas used: " << m_gasUsed.str() << endl; - cout << " gas used (without refund): " << totalGasUsed.str() << endl; - cout << " gas refund (total): " << result.gas_refund << endl; - cout << " gas refund (bound): " << gasRefund.str() << endl; + std::cout << " out: " << util::toHex(m_output) << std::endl; + std::cout << " result: " << static_cast(result.status_code) << std::endl; + std::cout << " gas used: " << m_gasUsed.str() << std::endl; + std::cout << " gas used (without refund): " << totalGasUsed.str() << std::endl; + std::cout << " gas refund (total): " << result.gas_refund << std::endl; + std::cout << " gas refund (bound): " << gasRefund.str() << std::endl; } } @@ -211,9 +210,9 @@ void ExecutionFramework::sendEther(h160 const& _addr, u256 const& _amount) if (m_showMessages) { - cout << "SEND_ETHER " << m_sender.hex() << " -> " << _addr.hex() << ":" << endl; + std::cout << "SEND_ETHER " << m_sender.hex() << " -> " << _addr.hex() << ":" << std::endl; if (_amount > 0) - cout << " value: " << _amount << endl; + std::cout << " value: " << _amount << std::endl; } evmc_message message{}; message.sender = EVMHost::convertToEVMC(m_sender); @@ -294,14 +293,14 @@ bool ExecutionFramework::storageEmpty(h160 const& _addr) const return true; } -vector ExecutionFramework::recordedLogs() const +std::vector ExecutionFramework::recordedLogs() const { - vector logs; + std::vector logs; for (evmc::MockedHost::log_record const& logRecord: m_evmcHost->recorded_logs) logs.emplace_back( EVMHost::convertFromEVMC(logRecord.creator), bytes{logRecord.data.begin(), logRecord.data.end()}, - logRecord.topics | ranges::views::transform([](evmc::bytes32 _bytes) { return EVMHost::convertFromEVMC(_bytes); }) | ranges::to + logRecord.topics | ranges::views::transform([](evmc::bytes32 _bytes) { return EVMHost::convertFromEVMC(_bytes); }) | ranges::to ); return logs; } diff --git a/test/FilesystemUtils.cpp b/test/FilesystemUtils.cpp index 7506d677ec..2d917485d6 100644 --- a/test/FilesystemUtils.cpp +++ b/test/FilesystemUtils.cpp @@ -22,11 +22,10 @@ #include -using namespace std; using namespace solidity; using namespace solidity::test; -void solidity::test::createFilesWithParentDirs(set const& _paths, string const& _content) +void solidity::test::createFilesWithParentDirs(std::set const& _paths, std::string const& _content) { for (boost::filesystem::path const& path: _paths) { @@ -34,23 +33,23 @@ void solidity::test::createFilesWithParentDirs(set cons boost::filesystem::create_directories(path.parent_path()); // Use binary mode to avoid line ending conversion on Windows. - ofstream newFile(path.string(), std::ofstream::binary); + std::ofstream newFile(path.string(), std::ofstream::binary); newFile << _content; if (newFile.fail() || !boost::filesystem::exists(path)) - BOOST_THROW_EXCEPTION(runtime_error("Failed to create an empty file: \"" + path.string() + "\".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create an empty file: \"" + path.string() + "\".")); } } -void solidity::test::createFileWithContent(boost::filesystem::path const& _path, string const& _content) +void solidity::test::createFileWithContent(boost::filesystem::path const& _path, std::string const& _content) { if (boost::filesystem::is_regular_file(_path)) - BOOST_THROW_EXCEPTION(runtime_error("File already exists: \"" + _path.string() + "\".")); \ + BOOST_THROW_EXCEPTION(std::runtime_error("File already exists: \"" + _path.string() + "\".")); \ // Use binary mode to avoid line ending conversion on Windows. - ofstream newFile(_path.string(), std::ofstream::binary); + std::ofstream newFile(_path.string(), std::ofstream::binary); if (newFile.fail() || !boost::filesystem::is_regular_file(_path)) - BOOST_THROW_EXCEPTION(runtime_error("Failed to create a file: \"" + _path.string() + "\".")); \ + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create a file: \"" + _path.string() + "\".")); \ newFile << _content; } @@ -80,7 +79,7 @@ bool solidity::test::createSymlinkIfSupportedByFilesystem( ) return false; else - BOOST_THROW_EXCEPTION(runtime_error( + BOOST_THROW_EXCEPTION(std::runtime_error( "Failed to create a symbolic link: \"" + _linkName.string() + "\"" " -> " + _targetPath.string() + "\"." " " + symlinkCreationError.message() + "." diff --git a/test/Metadata.cpp b/test/Metadata.cpp index 88a1f7b42f..2fea65c65b 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -26,8 +26,6 @@ #include #include -using namespace std; - namespace solidity::test { @@ -54,7 +52,7 @@ bytes bytecodeSansMetadata(bytes const& _bytecode) return bytes(_bytecode.begin(), _bytecode.end() - static_cast(metadataSize) - 2); } -string bytecodeSansMetadata(string const& _bytecode) +std::string bytecodeSansMetadata(std::string const& _bytecode) { return util::toHex(bytecodeSansMetadata(fromHex(_bytecode, util::WhenError::Throw))); } @@ -73,11 +71,11 @@ class TinyCBORParser assertThrow(nextType() == MajorType::Map, CBORException, "Fixed-length map expected."); return readLength(); } - string readKey() + std::string readKey() { return readString(); } - string readValue() + std::string readValue() { switch(nextType()) { @@ -132,7 +130,7 @@ class TinyCBORParser if (length == 24) return m_metadata.at(m_pos++); // Unsupported length kind. (Only by this parser.) - assertThrow(false, CBORException, string("Unsupported length ") + to_string(length)); + assertThrow(false, CBORException, std::string("Unsupported length ") + std::to_string(length)); } bytes readBytes(unsigned length) { @@ -140,28 +138,28 @@ class TinyCBORParser m_pos += length; return ret; } - string readString() + std::string readString() { // Expect a text string. assertThrow(nextType() == MajorType::TextString, CBORException, "String expected."); bytes tmp{readBytes(readLength())}; - return string{tmp.begin(), tmp.end()}; + return std::string{tmp.begin(), tmp.end()}; } unsigned m_pos; bytes const& m_metadata; }; -std::optional> parseCBORMetadata(bytes const& _metadata) +std::optional> parseCBORMetadata(bytes const& _metadata) { try { TinyCBORParser parser(_metadata); - map ret; + std::map ret; unsigned count = parser.mapItemCount(); for (unsigned i = 0; i < count; i++) { - string key = parser.readKey(); - string value = parser.readValue(); + std::string key = parser.readKey(); + std::string value = parser.readValue(); ret[std::move(key)] = std::move(value); } return ret; @@ -172,7 +170,7 @@ std::optional> parseCBORMetadata(bytes const& _metadata) } } -bool isValidMetadata(string const& _serialisedMetadata) +bool isValidMetadata(std::string const& _serialisedMetadata) { Json::Value metadata; if (!util::jsonParseStrict(_serialisedMetadata, metadata)) diff --git a/test/TestCase.cpp b/test/TestCase.cpp index 51608bd4a3..ae89bb56f3 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -27,21 +27,20 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::frontend; using namespace solidity::frontend::test; using namespace solidity::util; -void TestCase::printSettings(ostream& _stream, const string& _linePrefix, const bool) +void TestCase::printSettings(std::ostream& _stream, const std::string& _linePrefix, const bool) { auto& settings = m_reader.settings(); if (settings.empty()) return; - _stream << _linePrefix << "// ====" << endl; + _stream << _linePrefix << "// ====" << std::endl; for (auto const& setting: settings) - _stream << _linePrefix << "// " << setting.first << ": " << setting.second << endl; + _stream << _linePrefix << "// " << setting.first << ": " << setting.second << std::endl; } void TestCase::printUpdatedSettings(std::ostream& _stream, std::string const& _linePrefix) @@ -51,7 +50,7 @@ void TestCase::printUpdatedSettings(std::ostream& _stream, std::string const& _l bool TestCase::isTestFilename(boost::filesystem::path const& _filename) { - string extension = _filename.extension().string(); + std::string extension = _filename.extension().string(); return (extension == ".sol" || extension == ".yul" || extension == ".stack") && !boost::starts_with(_filename.string(), "~") && !boost::starts_with(_filename.string(), "."); @@ -63,19 +62,19 @@ bool TestCase::shouldRun() return m_shouldRun; } -void TestCase::expect(string::iterator& _it, string::iterator _end, string::value_type _c) +void TestCase::expect(std::string::iterator& _it, std::string::iterator _end, std::string::value_type _c) { if (_it == _end || *_it != _c) - BOOST_THROW_EXCEPTION(runtime_error(string("Invalid test expectation. Expected: \"") + _c + "\".")); + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Invalid test expectation. Expected: \"") + _c + "\".")); ++_it; } -void TestCase::printSource(ostream& _stream, string const& _linePrefix, bool const) const +void TestCase::printSource(std::ostream& _stream, std::string const& _linePrefix, bool const) const { printPrefixed(_stream, m_source, _linePrefix); } -void TestCase::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const +void TestCase::printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const { printPrefixed(_stream, m_obtainedResult, _linePrefix); } @@ -84,30 +83,30 @@ TestCase::TestResult TestCase::checkResult(std::ostream& _stream, const std::str { if (m_expectation != m_obtainedResult) { - string nextIndentLevel = _linePrefix + " "; + std::string nextIndentLevel = _linePrefix + " "; util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) - << _linePrefix << "Expected result:" << endl; + << _linePrefix << "Expected result:" << std::endl; // TODO could compute a simple diff with highlighted lines printPrefixed(_stream, m_expectation, nextIndentLevel); util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) - << _linePrefix << "Obtained result:" << endl; + << _linePrefix << "Obtained result:" << std::endl; printPrefixed(_stream, m_obtainedResult, nextIndentLevel); return TestResult::Failure; } return TestResult::Success; } -EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(string const& _filename): +EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _filename): TestCase(_filename) { - string versionString = m_reader.stringSetting("EVMVersion", "any"); + std::string versionString = m_reader.stringSetting("EVMVersion", "any"); if (versionString == "any") return; - string comparator; + std::string comparator; size_t versionBegin = 0; for (auto character: versionString) - if (!isalpha(character, locale::classic())) + if (!isalpha(character, std::locale::classic())) { comparator += character; versionBegin++; @@ -118,7 +117,7 @@ EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(string const& _filena versionString = versionString.substr(versionBegin); std::optional version = langutil::EVMVersion::fromString(versionString); if (!version) - BOOST_THROW_EXCEPTION(runtime_error{"Invalid EVM version: \"" + versionString + "\""}); + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid EVM version: \"" + versionString + "\""}); langutil::EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); bool comparisonResult; @@ -135,7 +134,7 @@ EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(string const& _filena else if (comparator == "!") comparisonResult = !(evmVersion == version); else - BOOST_THROW_EXCEPTION(runtime_error{"Invalid EVM comparator: \"" + comparator + "\""}); + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid EVM comparator: \"" + comparator + "\""}); if (!comparisonResult) m_shouldRun = false; diff --git a/test/TestCaseReader.cpp b/test/TestCaseReader.cpp index 7ad752ef81..da6174cbe9 100644 --- a/test/TestCaseReader.cpp +++ b/test/TestCaseReader.cpp @@ -23,36 +23,35 @@ #include #include -using namespace std; using namespace solidity::frontend::test; namespace fs = boost::filesystem; -TestCaseReader::TestCaseReader(string const& _filename): m_fileStream(_filename), m_fileName(_filename) +TestCaseReader::TestCaseReader(std::string const& _filename): m_fileStream(_filename), m_fileName(_filename) { if (!m_fileStream) - BOOST_THROW_EXCEPTION(runtime_error("Cannot open file: \"" + _filename + "\".")); - m_fileStream.exceptions(ios::badbit); + BOOST_THROW_EXCEPTION(std::runtime_error("Cannot open file: \"" + _filename + "\".")); + m_fileStream.exceptions(std::ios::badbit); - tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber(m_fileStream); + std::tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber(m_fileStream); m_unreadSettings = m_settings; } -TestCaseReader::TestCaseReader(istringstream const& _str) +TestCaseReader::TestCaseReader(std::istringstream const& _str) { - tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber( - static_cast(const_cast(_str)) + std::tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber( + static_cast(const_cast(_str)) ); } -string const& TestCaseReader::source() const +std::string const& TestCaseReader::source() const { if (m_sources.sources.size() != 1) - BOOST_THROW_EXCEPTION(runtime_error("Expected single source definition, but got multiple sources.")); + BOOST_THROW_EXCEPTION(std::runtime_error("Expected single source definition, but got multiple sources.")); return m_sources.sources.at(m_sources.mainSourceFile); } -string TestCaseReader::simpleExpectations() +std::string TestCaseReader::simpleExpectations() { return parseSimpleExpectations(m_fileStream); } @@ -63,13 +62,13 @@ bool TestCaseReader::boolSetting(std::string const& _name, bool _defaultValue) return _defaultValue; m_unreadSettings.erase(_name); - string value = m_settings.at(_name); + std::string value = m_settings.at(_name); if (value == "false") return false; if (value == "true") return true; - BOOST_THROW_EXCEPTION(runtime_error("Invalid Boolean value: " + value + ".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid Boolean value: " + value + ".")); } size_t TestCaseReader::sizetSetting(std::string const& _name, size_t _defaultValue) @@ -83,7 +82,7 @@ size_t TestCaseReader::sizetSetting(std::string const& _name, size_t _defaultVal return stoul(m_settings.at(_name)); } -string TestCaseReader::stringSetting(string const& _name, string const& _defaultValue) +std::string TestCaseReader::stringSetting(std::string const& _name, std::string const& _defaultValue) { if (m_settings.count(_name) == 0) return _defaultValue; @@ -95,26 +94,26 @@ string TestCaseReader::stringSetting(string const& _name, string const& _default void TestCaseReader::ensureAllSettingsRead() const { if (!m_unreadSettings.empty()) - BOOST_THROW_EXCEPTION(runtime_error( + BOOST_THROW_EXCEPTION(std::runtime_error( "Unknown setting(s): " + util::joinHumanReadable(m_unreadSettings | ranges::views::keys) )); } -pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(istream& _stream) +std::pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(std::istream& _stream) { - map sources; - map externalSources; - string currentSourceName; - string currentSource; - string line; + std::map sources; + std::map externalSources; + std::string currentSourceName; + std::string currentSource; + std::string line; size_t lineNumber = 1; - static string const externalSourceDelimiterStart("==== ExternalSource:"); - static string const sourceDelimiterStart("==== Source:"); - static string const sourceDelimiterEnd("===="); - static string const comment("// "); - static string const settingsDelimiter("// ===="); - static string const expectationsDelimiter("// ----"); + static std::string const externalSourceDelimiterStart("==== ExternalSource:"); + static std::string const sourceDelimiterStart("==== Source:"); + static std::string const sourceDelimiterEnd("===="); + static std::string const comment("// "); + static std::string const settingsDelimiter("// ===="); + static std::string const expectationsDelimiter("// ----"); bool sourcePart = true; while (getline(_stream, line)) { @@ -138,19 +137,19 @@ pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(is line.size() - sourceDelimiterEnd.size() - sourceDelimiterStart.size() )); if (sources.count(currentSourceName)) - BOOST_THROW_EXCEPTION(runtime_error("Multiple definitions of test source \"" + currentSourceName + "\".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Multiple definitions of test source \"" + currentSourceName + "\".")); } else if (boost::algorithm::starts_with(line, externalSourceDelimiterStart) && boost::algorithm::ends_with(line, sourceDelimiterEnd)) { - string externalSourceString = boost::trim_copy(line.substr( + std::string externalSourceString = boost::trim_copy(line.substr( externalSourceDelimiterStart.size(), line.size() - sourceDelimiterEnd.size() - externalSourceDelimiterStart.size() )); - string externalSourceName; + std::string externalSourceName; size_t remappingPos = externalSourceString.find('='); // Does the external source define a remapping? - if (remappingPos != string::npos) + if (remappingPos != std::string::npos) { externalSourceName = boost::trim_copy(externalSourceString.substr(0, remappingPos)); externalSourceString = boost::trim_copy(externalSourceString.substr(remappingPos + 1)); @@ -164,16 +163,16 @@ pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(is if (!externalSourceTarget.is_relative() || !externalSourceTarget.root_path().empty()) // NOTE: UNC paths (ones starting with // or \\) are considered relative by Boost // since they have an empty root directory (but non-empty root name). - BOOST_THROW_EXCEPTION(runtime_error("External Source paths need to be relative to the location of the test case.")); + BOOST_THROW_EXCEPTION(std::runtime_error("External Source paths need to be relative to the location of the test case.")); fs::path externalSourceFullPath = testCaseParentDir / externalSourceTarget; - string externalSourceContent; + std::string externalSourceContent; if (!fs::exists(externalSourceFullPath)) - BOOST_THROW_EXCEPTION(runtime_error("External Source '" + externalSourceTarget.string() + "' not found.")); + BOOST_THROW_EXCEPTION(std::runtime_error("External Source '" + externalSourceTarget.string() + "' not found.")); else externalSourceContent = util::readFileAsString(externalSourceFullPath); if (sources.count(externalSourceName)) - BOOST_THROW_EXCEPTION(runtime_error("Multiple definitions of test source \"" + externalSourceName + "\".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Multiple definitions of test source \"" + externalSourceName + "\".")); sources[externalSourceName] = externalSourceContent; externalSources[externalSourceName] = externalSourceTarget; } @@ -183,32 +182,32 @@ pair TestCaseReader::parseSourcesAndSettingsWithLineNumber(is else if (boost::algorithm::starts_with(line, comment)) { size_t colon = line.find(':'); - if (colon == string::npos) - BOOST_THROW_EXCEPTION(runtime_error(string("Expected \":\" inside setting."))); - string key = line.substr(comment.size(), colon - comment.size()); - string value = line.substr(colon + 1); + if (colon == std::string::npos) + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Expected \":\" inside setting."))); + std::string key = line.substr(comment.size(), colon - comment.size()); + std::string value = line.substr(colon + 1); boost::algorithm::trim(key); boost::algorithm::trim(value); m_settings[key] = value; } else - BOOST_THROW_EXCEPTION(runtime_error(string("Expected \"//\" or \"// ---\" to terminate settings and source."))); + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Expected \"//\" or \"// ---\" to terminate settings and source."))); } // Register the last source as the main one sources[currentSourceName] = currentSource; return {{std::move(sources), std::move(externalSources), std::move(currentSourceName)}, lineNumber}; } -string TestCaseReader::parseSimpleExpectations(istream& _file) +std::string TestCaseReader::parseSimpleExpectations(std::istream& _file) { - string result; - string line; - while (getline(_file, line)) + std::string result; + std::string line; + while (std::getline(_file, line)) if (boost::algorithm::starts_with(line, "// ")) result += line.substr(3) + "\n"; else if (line == "//") result += "\n"; else - BOOST_THROW_EXCEPTION(runtime_error("Test expectations must start with \"// \".")); + BOOST_THROW_EXCEPTION(std::runtime_error("Test expectations must start with \"// \".")); return result; } diff --git a/test/soltest.cpp b/test/soltest.cpp index 443c4c5de3..5fde4bda56 100644 --- a/test/soltest.cpp +++ b/test/soltest.cpp @@ -35,6 +35,7 @@ #pragma warning(pop) #endif +#pragma GCC diagnostic pop #pragma GCC diagnostic pop #include @@ -49,7 +50,6 @@ using namespace boost::unit_test; using namespace solidity::frontend::test; namespace fs = boost::filesystem; -using namespace std; namespace { @@ -100,7 +100,7 @@ void runTestCase(TestCase::Config const& _config, TestCase::TestCaseCreator cons { try { - stringstream errorStream; + std::stringstream errorStream; auto testCase = _testCaseCreator(_config); if (testCase->shouldRun()) switch (testCase->run(errorStream)) @@ -133,7 +133,7 @@ int registerTests( boost::unit_test::test_suite& _suite, boost::filesystem::path const& _basepath, boost::filesystem::path const& _path, - vector const& _labels, + std::vector const& _labels, TestCase::TestCaseCreator _testCaseCreator, solidity::test::Batcher& _batcher ) @@ -176,9 +176,9 @@ int registerTests( // This must be a vector of unique_ptrs because Boost.Test keeps the equivalent of a string_view to the filename // that is passed in. If the strings were stored directly in the vector, pointers/references to them would be // invalidated on reallocation. - static vector> filenames; + static std::vector> filenames; - filenames.emplace_back(make_unique(_path.string())); + filenames.emplace_back(std::make_unique(_path.string())); auto test_case = make_test_case( [config, _testCaseCreator] { @@ -236,11 +236,14 @@ test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) exit(EXIT_FAILURE); if (solidity::test::CommonOptions::get().disableSemanticTests) - cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl; + std::cout << std::endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << std::endl << std::endl; + + if (!solidity::test::CommonOptions::get().enforceGasTest) + std::cout << std::endl << "WARNING :: Gas Cost Expectations are not being enforced" << std::endl << std::endl; Batcher batcher(CommonOptions::get().selectedBatch, CommonOptions::get().batches); if (CommonOptions::get().batches > 1) - cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << endl; + std::cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << std::endl; // Batch the boost tests BoostBatcher boostBatcher(batcher); @@ -287,12 +290,12 @@ test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) } catch (solidity::test::ConfigException const& exception) { - cerr << exception.what() << endl; + std::cerr << exception.what() << std::endl; exit(EXIT_FAILURE); } catch (std::runtime_error const& exception) { - cerr << exception.what() << endl; + std::cerr << exception.what() << std::endl; exit(EXIT_FAILURE); } From ac398869ad8ab1191f5c52fc58703877e3766ebc Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 7 Feb 2024 12:38:41 +0100 Subject: [PATCH 15/47] SMTChecker: Respect signedness of integer type When creating zero-value expression, we need to respect the signedness of the passed type. --- libsolidity/formal/SymbolicTypes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 45b872b3d0..350e18bdcf 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -476,7 +476,7 @@ smtutil::Expression zeroValue(frontend::Type const* _type) if (isSupportedType(*_type)) { if (isNumber(*_type)) - return 0; + return isSigned(_type) ? smtutil::Expression(s256(0)) : smtutil::Expression(static_cast(0)); if (isBool(*_type)) return smtutil::Expression(false); if (isArray(*_type) || isMapping(*_type)) From 8770952466d9c7c16cabe534c843e29ef27f7a78 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 7 Feb 2024 12:39:04 +0100 Subject: [PATCH 16/47] SMTChecker: Unsigned number expressions should have unsigned type --- libsmtutil/SolverInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsmtutil/SolverInterface.h b/libsmtutil/SolverInterface.h index 4a21f18410..82f8111335 100644 --- a/libsmtutil/SolverInterface.h +++ b/libsmtutil/SolverInterface.h @@ -124,7 +124,7 @@ class Expression explicit Expression(std::string _name, std::vector _arguments, SortPointer _sort): name(std::move(_name)), arguments(std::move(_arguments)), sort(std::move(_sort)) {} Expression(size_t _number): Expression(std::to_string(_number), {}, SortProvider::uintSort) {} - Expression(u256 const& _number): Expression(_number.str(), {}, SortProvider::sintSort) {} + Expression(u256 const& _number): Expression(_number.str(), {}, SortProvider::uintSort) {} Expression(s256 const& _number): Expression( _number >= 0 ? _number.str() : "-", _number >= 0 ? From a1ad970aa10cb9dcf55af859a0de57ed41893722 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 9 Feb 2024 16:07:52 +0100 Subject: [PATCH 17/47] SMTChecker: Add test case --- test/libsolidity/smtCheckerTests/types/mapping_6.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/types/mapping_6.sol diff --git a/test/libsolidity/smtCheckerTests/types/mapping_6.sol b/test/libsolidity/smtCheckerTests/types/mapping_6.sol new file mode 100644 index 0000000000..f2b6d74d7a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_6.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0 + + +// Regression for handling signedness, see issues #14791 and #14792 +contract C { + mapping(bool => int240) internal v1; + mapping(bytes14 => bytes15) internal v; + + function f() public payable { + delete v["A"]; + } +} From 22da46c91ceaa4e1a8061b16b69123b5b4ca2457 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 9 Feb 2024 16:25:56 +0100 Subject: [PATCH 18/47] Update changelog --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 3d64b1b80e..a33421f1cc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: + * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. ### 0.8.24 (2024-01-25) From 4d163ff4bb6b84afff0dfd5817ad52b03e5aa521 Mon Sep 17 00:00:00 2001 From: Simon Perriard Date: Sun, 18 Feb 2024 20:13:37 +0100 Subject: [PATCH 19/47] Convert tagPos to a size for address size computation --- libevmasm/Assembly.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 203db8613d..acf6067697 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -861,8 +861,8 @@ LinkerObject const& Assembly::assemble() const immutableReferencesBySub = linkerObject.immutableReferences; } for (size_t tagPos: sub->m_tagPositionsInBytecode) - if (tagPos != std::numeric_limits::max() && tagPos > subTagSize) - subTagSize = tagPos; + if (tagPos != std::numeric_limits::max() && numberEncodingSize(tagPos) > subTagSize) + subTagSize = numberEncodingSize(tagPos); } bool setsImmutables = false; From 8e212553d6f96031d000914cd19550cfbc06eca6 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 19 Feb 2024 21:10:34 +0100 Subject: [PATCH 20/47] Account for subassemblies in tag size calculation, test adjustments and changelog entry. --- Changelog.md | 1 + libevmasm/Assembly.cpp | 12 ++++++++++++ test/cmdlineTests/function_debug_info/output | 2 +- .../output.json | 4 ++-- test/libsolidity/GasCosts.cpp | 16 ++++++++-------- .../semanticTests/arithmetics/check_var_init.sol | 2 +- .../array/constant_var_as_array_length.sol | 2 +- ...leanup_during_multi_element_per_slot_copy.sol | 6 +++--- .../array/fixed_arrays_in_constructors.sol | 2 +- .../semanticTests/array/reusing_memory.sol | 2 +- .../byte_array_to_storage_cleanup.sol | 6 +++--- .../constructor/arrays_in_constructors.sol | 2 +- .../constructor/bytes_in_constructors_packer.sol | 2 +- .../bytes_in_constructors_unpacker.sol | 2 +- .../constructor_arguments_external.sol | 4 ++-- .../constructor_static_array_argument.sol | 2 +- .../constructor_inheritance_init_order.sol | 2 +- .../constructor_inheritance_init_order_2.sol | 6 +++--- .../semanticTests/constructor_with_params.sol | 4 ++-- ...nstructor_with_params_diamond_inheritance.sol | 4 ++-- .../constructor_with_params_inheritance.sol | 4 ++-- .../events/event_emit_from_other_contract.sol | 6 +++--- .../externalContracts/FixedFeeRegistrar.sol | 6 +++--- .../semanticTests/externalContracts/base64.sol | 6 +++--- .../externalContracts/deposit_contract.sol | 4 ++-- .../externalContracts/prbmath_signed.sol | 6 +++--- .../externalContracts/prbmath_unsigned.sol | 6 +++--- .../externalContracts/ramanujan_pi.sol | 6 +++--- .../semanticTests/externalContracts/strings.sol | 6 +++--- .../creation_function_call_with_args.sol | 6 +++--- .../creation_function_call_with_salt.sol | 6 +++--- .../functionCall/gas_and_value_basic.sol | 6 +++--- .../functionCall/gas_and_value_brace_syntax.sol | 6 +++--- .../functionCall/send_zero_ether.sol | 2 +- .../semanticTests/immutable/use_scratch.sol | 4 ++-- .../inheritance/member_notation_ctor.sol | 4 ++-- .../inheritance/value_for_constructor.sol | 4 ++-- .../isoltestTesting/balance_other_contract.sol | 6 +++--- .../salted_create/prediction_example.sol | 2 +- .../salted_create/salted_create_with_value.sol | 2 +- .../semanticTests/smoke/constructor.sol | 6 +++--- .../semanticTests/state/blockhash_basic.sol | 6 +++--- .../semanticTests/userDefinedValueType/erc20.sol | 4 ++-- .../semanticTests/various/code_length.sol | 2 +- test/libsolidity/semanticTests/various/erc20.sol | 4 ++-- .../various/negative_stack_height.sol | 4 ++-- ...estruct_pre_cancun_multiple_beneficiaries.sol | 2 +- .../various/selfdestruct_pre_cancun_redeploy.sol | 6 +++--- .../semanticTests/various/senders_balance.sol | 6 +++--- .../semanticTests/various/value_complex.sol | 6 +++--- .../semanticTests/various/value_insane.sol | 6 +++--- .../sizeLimits/combined_too_large_shanghai.sol | 2 +- .../sizeLimits/initcode_too_large_shanghai.sol | 2 +- 53 files changed, 125 insertions(+), 112 deletions(-) diff --git a/Changelog.md b/Changelog.md index a33421f1cc..b2ac59c65a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: + * Assembler: Prevent incorrect calculation of tag sizes. * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index acf6067697..569ecda26a 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -890,6 +890,18 @@ LinkerObject const& Assembly::assemble() const std::multimap subRef; std::vector sizeRef; ///< Pointers to code locations where the size of the program is inserted unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode); + // Adjust bytesPerTag for references to sub assemblies. + for (AssemblyItem const& i: m_items) + if (i.type() == PushTag) + { + auto [subId, tagId] = i.splitForeignPushTag(); + if (subId == std::numeric_limits::max()) + continue; + assertThrow(subId < m_subs.size(), AssemblyException, "Invalid sub id"); + auto subTagPosition = m_subs[subId]->m_tagPositionsInBytecode.at(tagId); + assertThrow(subTagPosition != std::numeric_limits::max(), AssemblyException, "Reference to tag without position."); + bytesPerTag = std::max(bytesPerTag, numberEncodingSize(subTagPosition)); + } uint8_t tagPush = static_cast(pushInstruction(bytesPerTag)); unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1 + static_cast(m_auxiliaryData.size()); diff --git a/test/cmdlineTests/function_debug_info/output b/test/cmdlineTests/function_debug_info/output index b9ca3f3c40..c359d4e1c1 100644 --- a/test/cmdlineTests/function_debug_info/output +++ b/test/cmdlineTests/function_debug_info/output @@ -13,7 +13,7 @@ }, "abi_decode_tuple_t_uint256_fromMemory": { - "entryPoint": 92, + "entryPoint": 88, "parameterSlots": 2, "returnSlots": 1 } diff --git a/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json b/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json index 169e99961e..3a69e3e2d7 100644 --- a/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json +++ b/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json @@ -17,11 +17,11 @@ [ { "length": 20, - "start": 174 + "start": 173 }, { "length": 20, - "start": 350 + "start": 349 } ] } diff --git a/test/libsolidity/GasCosts.cpp b/test/libsolidity/GasCosts.cpp index 5207328101..d8dad9e027 100644 --- a/test/libsolidity/GasCosts.cpp +++ b/test/libsolidity/GasCosts.cpp @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(string_storage) if (CommonOptions::get().useABIEncoderV1) CHECK_DEPLOY_GAS(133045, 129731, evmVersion); else - CHECK_DEPLOY_GAS(144999, 121229, evmVersion); + CHECK_DEPLOY_GAS(144995, 121229, evmVersion); } // This is only correct on >=Constantinople. else if (!CommonOptions::get().useABIEncoderV1) @@ -110,22 +110,22 @@ BOOST_AUTO_TEST_CASE(string_storage) { // Costs with 0 are cases which cannot be triggered in tests. if (evmVersion < EVMVersion::istanbul()) - CHECK_DEPLOY_GAS(0, 109241, evmVersion); + CHECK_DEPLOY_GAS(0, 109237, evmVersion); else if (evmVersion < EVMVersion::shanghai()) - CHECK_DEPLOY_GAS(0, 97697, evmVersion); + CHECK_DEPLOY_GAS(0, 97693, evmVersion); // Shanghai is cheaper due to `push0` else - CHECK_DEPLOY_GAS(0, 97071, evmVersion); + CHECK_DEPLOY_GAS(0, 97067, evmVersion); } else { if (evmVersion < EVMVersion::istanbul()) - CHECK_DEPLOY_GAS(139013, 123969, evmVersion); + CHECK_DEPLOY_GAS(139009, 123969, evmVersion); else if (evmVersion < EVMVersion::shanghai()) - CHECK_DEPLOY_GAS(123361, 110969, evmVersion); + CHECK_DEPLOY_GAS(123357, 110969, evmVersion); // Shanghai is cheaper due to `push0` else - CHECK_DEPLOY_GAS(121493, 110969, evmVersion); + CHECK_DEPLOY_GAS(121489, 110969, evmVersion); } } else if (evmVersion < EVMVersion::istanbul()) @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(string_storage) else if (evmVersion < EVMVersion::shanghai()) CHECK_DEPLOY_GAS(114077, 96461, evmVersion); else - CHECK_DEPLOY_GAS(114077, 95835, evmVersion); + CHECK_DEPLOY_GAS(114077, 95831, evmVersion); if (evmVersion >= EVMVersion::byzantium()) { diff --git a/test/libsolidity/semanticTests/arithmetics/check_var_init.sol b/test/libsolidity/semanticTests/arithmetics/check_var_init.sol index 6cc02bd975..fc5418cb0e 100644 --- a/test/libsolidity/semanticTests/arithmetics/check_var_init.sol +++ b/test/libsolidity/semanticTests/arithmetics/check_var_init.sol @@ -16,4 +16,4 @@ contract D { // ---- // f() -> FAILURE, hex"4e487b71", 0x11 // g(), 100 wei -> 1 -// gas legacy: 100388 +// gas legacy: 100380 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 ca65f07065..45861babaa 100644 --- a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol +++ b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol @@ -8,7 +8,7 @@ contract C { } // ---- // constructor(): 1, 2, 3 -> -// gas irOptimized: 139656 +// gas irOptimized: 139616 // gas legacy: 180517 // gas legacyOptimized: 150462 // a(uint256): 0 -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol index d2361dac54..8be8328926 100644 --- a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol +++ b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol @@ -16,7 +16,7 @@ contract C { } // ---- // constructor() -// gas irOptimized: 226349 -// gas legacy: 215757 -// gas legacyOptimized: 181760 +// gas irOptimized: 226321 +// gas legacy: 215753 +// gas legacyOptimized: 181756 // f() -> 0 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol index ac11d779a5..c7b2dc77a3 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol @@ -9,7 +9,7 @@ contract Creator { } // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 126363 +// gas irOptimized: 126327 // gas legacy: 174186 // gas legacyOptimized: 128709 // r() -> 4 diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index 92b0c06bfb..8f6afe30ba 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -25,5 +25,5 @@ contract Main { // ---- // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 // gas irOptimized: 111924 -// gas legacy: 125162 +// gas legacy: 125154 // gas legacyOptimized: 113012 diff --git a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol index dc77f0dff8..877e2a1bce 100644 --- a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol +++ b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol @@ -28,9 +28,9 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 443406 -// gas legacy: 711299 -// gas legacyOptimized: 482382 +// gas irOptimized: 443402 +// gas legacy: 711295 +// gas legacyOptimized: 482378 // h() -> 0x20, 0x40, 0x00, 0 // ~ emit ev(uint256[],uint256): 0x40, 0x21, 0x02, 0x00, 0x00 // g() -> 0x20, 0x40, 0, 0x00 diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 3d9c1ffece..19d79b6c4f 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -25,5 +25,5 @@ contract Creator { // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 // gas irOptimized: 424526 -// gas legacy: 581443 +// gas legacy: 581426 // gas legacyOptimized: 444599 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 067a64e0e5..cfa74f016f 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -25,5 +25,5 @@ contract Creator { // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" // gas irOptimized: 275102 -// gas legacy: 418462 +// gas legacy: 418433 // gas legacyOptimized: 291960 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 0665cb807a..39da45e8a5 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -9,7 +9,7 @@ contract Test { // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> // gas irOptimized: 269225 -// gas legacy: 311324 +// gas legacy: 310820 // gas legacyOptimized: 258604 // 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 3037aaa317..714ae3e554 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol @@ -17,8 +17,8 @@ contract Main { } // ---- // constructor(): "abc", true -// gas irOptimized: 104394 +// gas irOptimized: 104374 // gas legacy: 143300 -// gas legacyOptimized: 102961 +// gas legacyOptimized: 102933 // 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 22acd1cc3f..a61192742d 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -9,7 +9,7 @@ contract C { } // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 171015 +// gas irOptimized: 170975 // gas legacy: 218378 // gas legacyOptimized: 176211 // a() -> 1 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol index 20cd8760b9..ece0cc31a6 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol @@ -14,5 +14,5 @@ contract B is A { // compileViaYul: true // ---- // constructor() -> -// gas irOptimized: 119640 +// gas irOptimized: 119636 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol index 820c56a4ee..654c9af56d 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol @@ -9,7 +9,7 @@ contract B is A { } // ---- // constructor() -> -// gas irOptimized: 119640 -// gas legacy: 133594 -// gas legacyOptimized: 115341 +// gas irOptimized: 119636 +// gas legacy: 133574 +// gas legacyOptimized: 115337 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_with_params.sol b/test/libsolidity/semanticTests/constructor_with_params.sol index 1916f692fd..e427f6d9ab 100644 --- a/test/libsolidity/semanticTests/constructor_with_params.sol +++ b/test/libsolidity/semanticTests/constructor_with_params.sol @@ -9,7 +9,7 @@ contract C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 101390 -// gas legacy: 115678 +// gas irOptimized: 101370 +// gas legacy: 115614 // 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 b2f66e4500..6507081447 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol @@ -21,9 +21,9 @@ contract D is B, C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 151966 +// gas irOptimized: 151950 // gas legacy: 168623 -// gas legacyOptimized: 144577 +// gas legacyOptimized: 144521 // 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 f5b20d9816..8cc7c69f68 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol @@ -12,8 +12,8 @@ contract D is C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 121805 +// gas irOptimized: 121781 // gas legacy: 137193 -// gas legacyOptimized: 118548 +// gas legacyOptimized: 118504 // 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 f8b5141b97..0c56cbb671 100644 --- a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol +++ b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol @@ -15,8 +15,8 @@ contract C { } // ---- // constructor() -> -// gas irOptimized: 165386 -// gas legacy: 244800 -// gas legacyOptimized: 171615 +// gas irOptimized: 165370 +// gas legacy: 244776 +// gas legacyOptimized: 171587 // deposit(bytes32), 18 wei: 0x1234 -> // ~ emit Deposit(address,bytes32,uint256) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: #0xc06afe3a8444fc0004668591e8306bfb9968e79e, #0x1234, 0x00 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index f9f53275bb..011fecbd34 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -74,9 +74,9 @@ contract FixedFeeRegistrar is Registrar { } // ---- // constructor() -// gas irOptimized: 384610 -// gas legacy: 913421 -// gas legacyOptimized: 476928 +// gas irOptimized: 384606 +// gas legacy: 913417 +// gas legacyOptimized: 476924 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 // gas irOptimized: 45967 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index 646601e6fb..ee2745d1ac 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -33,9 +33,9 @@ contract test { // EVMVersion: >=constantinople // ---- // constructor() -// gas irOptimized: 405832 -// gas legacy: 735054 -// gas legacyOptimized: 522722 +// gas irOptimized: 405828 +// gas legacy: 735050 +// gas legacyOptimized: 522718 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 4f3342dea7..caa7fc39c8 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -177,8 +177,8 @@ contract DepositContract is IDepositContract, ERC165 { // ---- // constructor() // gas irOptimized: 1386886 -// gas legacy: 2369061 -// gas legacyOptimized: 1740144 +// gas legacy: 2368733 +// gas legacyOptimized: 1740004 // 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 3311a8dcf4..ba7a208fd7 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -48,9 +48,9 @@ contract test { } // ---- // constructor() -// gas irOptimized: 1841740 -// gas legacy: 2414091 -// gas legacyOptimized: 1847616 +// gas irOptimized: 1841736 +// gas legacy: 2414087 +// gas legacyOptimized: 1847612 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22137 // gas legacy: 22767 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index fb1d1a4352..90b283db46 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -48,9 +48,9 @@ contract test { } // ---- // constructor() -// gas irOptimized: 1716327 -// gas legacy: 2193550 -// gas legacyOptimized: 1725061 +// gas irOptimized: 1716323 +// gas legacy: 2193546 +// gas legacyOptimized: 1725057 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22004 // gas legacy: 22497 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 3f555405dd..4442b6d479 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -33,9 +33,9 @@ contract test { } // ---- // constructor() -// gas irOptimized: 407507 -// gas legacy: 615090 -// gas legacyOptimized: 451871 +// gas irOptimized: 407503 +// gas legacy: 615086 +// gas legacyOptimized: 451867 // prb_pi() -> 3141592656369545286 // gas irOptimized: 57478 // gas legacy: 100947 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 18d6db37df..3f88fc39c6 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -49,9 +49,9 @@ contract test { } // ---- // constructor() -// gas irOptimized: 630224 -// gas legacy: 1061957 -// gas legacyOptimized: 718937 +// gas irOptimized: 630220 +// gas legacy: 1061953 +// gas legacyOptimized: 718933 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22660 // gas legacy: 23190 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 39592f4a48..34aac74efa 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -15,7 +15,7 @@ contract D { } // ---- // constructor(): 2 -> -// gas irOptimized: 192703 -// gas legacy: 241234 -// gas legacyOptimized: 192961 +// gas irOptimized: 192663 +// gas legacy: 241170 +// gas legacyOptimized: 192897 // 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 3850a0be7f..cb26a6e26a 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -17,7 +17,7 @@ contract D { // EVMVersion: >=constantinople // ---- // constructor(): 2 -> -// gas irOptimized: 192866 -// gas legacy: 241606 -// gas legacyOptimized: 193193 +// gas irOptimized: 192826 +// gas legacy: 241536 +// gas legacyOptimized: 193129 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index 79a829aa77..8396cb12db 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -38,9 +38,9 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 252642 -// gas legacy: 391588 -// gas legacyOptimized: 268089 +// gas irOptimized: 252626 +// gas legacy: 391568 +// gas legacyOptimized: 268069 // 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 71b6ebb2c7..9d9c3f603f 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -37,9 +37,9 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 252642 -// gas legacy: 391588 -// gas legacyOptimized: 268089 +// gas irOptimized: 252626 +// gas legacy: 391568 +// gas legacyOptimized: 268069 // 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 18a1997929..a737de5cd4 100644 --- a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol +++ b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol @@ -16,6 +16,6 @@ contract Main { // ---- // constructor(), 20 wei -> // gas irOptimized: 100264 -// gas legacy: 113411 +// gas legacy: 110555 // gas legacyOptimized: 100361 // s() -> true diff --git a/test/libsolidity/semanticTests/immutable/use_scratch.sol b/test/libsolidity/semanticTests/immutable/use_scratch.sol index 0a5ccf729f..a7c8ea6a50 100644 --- a/test/libsolidity/semanticTests/immutable/use_scratch.sol +++ b/test/libsolidity/semanticTests/immutable/use_scratch.sol @@ -15,8 +15,8 @@ contract C { } // ---- // constructor(): 3 -> -// gas irOptimized: 123542 +// gas irOptimized: 123526 // gas legacy: 197645 -// gas legacyOptimized: 137678 +// gas legacyOptimized: 137658 // f() -> 84, 23 // m(uint256): 3 -> 7 diff --git a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol index 33392e8d48..263588abab 100644 --- a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol +++ b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol @@ -19,6 +19,6 @@ contract A { } // ---- // g(int256): -1 -> -1 -// gas legacy: 102086 +// gas legacy: 102078 // g(int256): 10 -> 10 -// gas legacy: 101714 +// gas legacy: 101706 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index d8fd8766fe..9627ad025d 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -39,9 +39,9 @@ contract Main { } // ---- // constructor(), 22 wei -> -// gas irOptimized: 261888 +// gas irOptimized: 261864 // gas legacy: 392786 -// gas legacyOptimized: 261633 +// gas legacyOptimized: 261593 // 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 306bc35670..1a5c9b19b4 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -16,9 +16,9 @@ contract ClientReceipt { } // ---- // constructor(), 2000 wei -> -// gas irOptimized: 169915 -// gas legacy: 230038 -// gas legacyOptimized: 173883 +// gas irOptimized: 169907 +// gas legacy: 230018 +// gas legacyOptimized: 173867 // balance -> 1500 // gas irOptimized: 191881 // gas legacy: 235167 diff --git a/test/libsolidity/semanticTests/salted_create/prediction_example.sol b/test/libsolidity/semanticTests/salted_create/prediction_example.sol index 1c5ce63ad4..e7171536d6 100644 --- a/test/libsolidity/semanticTests/salted_create/prediction_example.sol +++ b/test/libsolidity/semanticTests/salted_create/prediction_example.sol @@ -26,4 +26,4 @@ contract C { // compileViaYul: also // ---- // createDSalted(bytes32,uint256): 42, 64 -> -// gas legacy: 102943 +// gas legacy: 102841 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index c4db174742..58b3f07603 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -23,4 +23,4 @@ contract A { // f(), 10 ether -> 3007, 3008, 3009 // gas irOptimized: 253005 // gas legacy: 381063 -// gas legacyOptimized: 279694 +// gas legacyOptimized: 279658 diff --git a/test/libsolidity/semanticTests/smoke/constructor.sol b/test/libsolidity/semanticTests/smoke/constructor.sol index 79b92867bc..55789b2f4b 100644 --- a/test/libsolidity/semanticTests/smoke/constructor.sol +++ b/test/libsolidity/semanticTests/smoke/constructor.sol @@ -12,9 +12,9 @@ contract C { } // ---- // constructor(), 2 wei: 3 -> -// gas irOptimized: 104412 -// gas legacy: 148308 -// gas legacyOptimized: 106727 +// gas irOptimized: 104396 +// gas legacy: 148256 +// gas legacyOptimized: 106699 // 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 01069aa0c6..03d6f9fe76 100644 --- a/test/libsolidity/semanticTests/state/blockhash_basic.sol +++ b/test/libsolidity/semanticTests/state/blockhash_basic.sol @@ -12,9 +12,9 @@ contract C { } // ---- // constructor() -// gas irOptimized: 108150 -// gas legacy: 152179 -// gas legacyOptimized: 106750 +// gas irOptimized: 108138 +// gas legacy: 152171 +// gas legacyOptimized: 106738 // 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 27ab530cd7..ac8609d713 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -113,8 +113,8 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 352698 -// gas legacy: 834932 +// gas irOptimized: 352682 +// gas legacy: 834752 // gas legacyOptimized: 412648 // totalSupply() -> 20 // gas irOptimized: 23415 diff --git a/test/libsolidity/semanticTests/various/code_length.sol b/test/libsolidity/semanticTests/various/code_length.sol index 97a7637976..a8aac5306f 100644 --- a/test/libsolidity/semanticTests/various/code_length.sol +++ b/test/libsolidity/semanticTests/various/code_length.sol @@ -59,5 +59,5 @@ contract C { } // ---- // constructor() -// gas legacy: 124168 +// gas legacy: 124136 // f(): true, true -> true, true diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index b752a52101..00c12fb18a 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -96,8 +96,8 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 353276 -// gas legacy: 807683 +// gas irOptimized: 353248 +// gas legacy: 807559 // gas legacyOptimized: 408718 // totalSupply() -> 20 // gas irOptimized: 23415 diff --git a/test/libsolidity/semanticTests/various/negative_stack_height.sol b/test/libsolidity/semanticTests/various/negative_stack_height.sol index 3c9130e9fd..7289d2bbd9 100644 --- a/test/libsolidity/semanticTests/various/negative_stack_height.sol +++ b/test/libsolidity/semanticTests/various/negative_stack_height.sol @@ -65,5 +65,5 @@ contract C { // compileViaYul: false // ---- // constructor() -> -// gas legacy: 575272 -// gas legacyOptimized: 345026 +// gas legacy: 575268 +// gas legacyOptimized: 345022 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol index 57b2d5c66a..87e81a2902 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol @@ -36,7 +36,7 @@ contract D { // ---- // constructor(), 2 ether -> // gas irOptimized: 223918 -// gas legacy: 374228 +// gas legacy: 374024 // gas legacyOptimized: 239815 // balance: 0x1111111111111111111111111111111111111111 -> 0 // balance: 0x2222222222222222222222222222222222222222 -> 0 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol index 9c9949854a..e0885782c2 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol @@ -79,9 +79,9 @@ contract D { // EVMVersion: =shanghai // ---- // constructor(), 1 ether -> -// gas irOptimized: 430265 -// gas legacy: 690264 -// gas legacyOptimized: 412819 +// gas irOptimized: 430253 +// gas legacy: 690244 +// gas legacyOptimized: 412799 // exists() -> false // test_deploy_and_terminate() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/various/senders_balance.sol b/test/libsolidity/semanticTests/various/senders_balance.sol index 6628454db9..a1c7d4147f 100644 --- a/test/libsolidity/semanticTests/various/senders_balance.sol +++ b/test/libsolidity/semanticTests/various/senders_balance.sol @@ -16,7 +16,7 @@ contract D { } // ---- // constructor(), 27 wei -> -// gas irOptimized: 167865 -// gas legacy: 218459 -// gas legacyOptimized: 167292 +// gas irOptimized: 167857 +// gas legacy: 218435 +// gas legacyOptimized: 167276 // f() -> 27 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol index 9f262fbdeb..2adac6bf4c 100644 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ b/test/libsolidity/semanticTests/various/value_complex.sol @@ -19,7 +19,7 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 172407 -// gas legacy: 252296 -// gas legacyOptimized: 180352 +// gas irOptimized: 172399 +// gas legacy: 252276 +// gas legacyOptimized: 180336 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/various/value_insane.sol b/test/libsolidity/semanticTests/various/value_insane.sol index 1e591050c3..87fa01485d 100644 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ b/test/libsolidity/semanticTests/various/value_insane.sol @@ -18,7 +18,7 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 173271 -// gas legacy: 253820 -// gas legacyOptimized: 180784 +// gas irOptimized: 173263 +// gas legacy: 253800 +// gas legacyOptimized: 180768 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol b/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol index 3fc466db39..32e8d9133b 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol @@ -29,4 +29,4 @@ contract test { // Warning 5574: (0-27130): Contract code size is 27187 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. // Warning 5574: (27132-27224): Contract code size is 27213 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. // Warning 5574: (27226-27319): Contract code size is 27212 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. -// Warning 3860: (27321-27398): Contract initcode size is 54628 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 3860: (27321-27398): Contract initcode size is 54618 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol b/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol index f82434d5d6..d48693db05 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol @@ -27,4 +27,4 @@ contract test { // ==== // EVMVersion: =shanghai // ---- -// Warning 3860: (20321-20415): Contract initcode size is 60896 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 3860: (20321-20415): Contract initcode size is 60882 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. From c49d84784e62082756b671bd1ed85c076185fe31 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 20 Feb 2024 07:27:58 +0100 Subject: [PATCH 21/47] Force install python3.12 for Window bytecode compare job --- .circleci/config.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5ab0b056a2..72d96fe4f8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1697,8 +1697,12 @@ jobs: # platforms so line ending conversions must absolutely be disabled. - run: git config --global core.autocrlf false - checkout - # Ensure windows has python3 alias required by prepare_bytecode_report - - run: ln -s /c/Python312/python /c/Python312/python3 + - run: + name: Force install python3.12.2 + command: choco install python3 --pre --force --version=3.12.2 + - run: + name: Create a symlink for python3 + command: ln -s /c/ProgramData/chocolatey/bin/python3.12 /c/ProgramData/chocolatey/bin/python3 - attach_workspace: at: build - prepare_bytecode_report: From 1185ad0400223a54777904d1521102eec599d666 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 20 Feb 2024 14:49:28 +0100 Subject: [PATCH 22/47] Build hardhat from latest release in t_ems_ext_hardhat --- .circleci/config.yml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5ab0b056a2..5b13a79456 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1386,7 +1386,31 @@ jobs: - checkout - attach_workspace: at: /tmp/workspace - - run: git clone --depth 1 https://github.com/nomiclabs/hardhat.git + - run: + name: Ensure pnpm is installed if npm is present + command: | + if command -v npm &> /dev/null; then + sudo npm install -g pnpm + fi + - run: + name: Retrieve Hardhat latest release tag + command: | + # Make authenticated requests when the Github token is available + if [[ -n "$GITHUB_ACCESS_TOKEN" ]]; then + EXTRA_HEADERS=(--header 'Authorization: Bearer '"${GITHUB_ACCESS_TOKEN}") + fi + HARDHAT_RELEASE_TAG=$( + curl \ + --silent \ + --location \ + --fail \ + --show-error \ + "${EXTRA_HEADERS[@]}" \ + https://api.github.com/repos/nomiclabs/hardhat/releases/latest \ + | jq --raw-output .tag_name \ + ) + echo "export HARDHAT_RELEASE_TAG='${HARDHAT_RELEASE_TAG}'" >> "$BASH_ENV" + - run: git clone --depth 1 https://github.com/nomiclabs/hardhat.git --branch $HARDHAT_RELEASE_TAG - run: name: Install dependencies command: | From d703b829b2f13d6a6d7b7bdd6271ec3fecdae4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 16:04:27 +0100 Subject: [PATCH 23/47] gas_diff_stats.py: Add basic unit tests --- .circleci/config.yml | 6 +- test/scripts/test_gas_diff_stats.py | 87 +++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 test/scripts/test_gas_diff_stats.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 72d96fe4f8..e14a4ec78c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -973,6 +973,10 @@ jobs: <<: *base_ubuntu2204_small steps: - checkout + - run: + # TODO: Add these to the base image + name: Install gas_diff_stats.py dependencies + command: python3 -m pip install --user parsec tabulate - run: name: Python unit tests command: python3 test/pyscriptTests.py @@ -985,7 +989,7 @@ jobs: - checkout - run: name: Install dependencies - command: python -m pip install --user requests + command: python -m pip install --user requests parsec tabulate - run: name: Python unit tests command: python.exe test/pyscriptTests.py diff --git a/test/scripts/test_gas_diff_stats.py b/test/scripts/test_gas_diff_stats.py new file mode 100644 index 0000000000..4980293aea --- /dev/null +++ b/test/scripts/test_gas_diff_stats.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python + +import unittest +from textwrap import dedent + +# NOTE: This test file file only works with scripts/ added to PYTHONPATH so pylint can't find the imports +# pragma pylint: disable=import-error +from gas_diff_stats import collect_statistics +# pragma pylint: enable=import-error + +class TestGasDiffStats(unittest.TestCase): + def test_collect_statistics_should_fail_on_empty_diff(self): + with self.assertRaises(RuntimeError): + self.assertEqual(collect_statistics(""), (0, 0, 0, 0, 0, 0)) + + def test_collect_statistics_should_accept_whitespace_only_diff(self): + # TODO: Should it really work this way? + # If we're rejecting empty diff, not sure why whitespace is accepted. + self.assertEqual(collect_statistics("\n"), (0, 0, 0, 0, 0, 0)) + self.assertEqual(collect_statistics("\n \n\t\n\n"), (0, 0, 0, 0, 0, 0)) + + def test_collect_statistics_should_report_sum_of_gas_costs(self): + diff_output = dedent(""" + diff --git a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol + index 1306529d4..77a330f3c 100644 + --- a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol + +++ b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol + @@ -38 +38,2 @@ contract D { + -// gas legacy: 102095 + +// gas legacy: 76495 + @@ -40,3 +41,6 @@ contract D { + -// gas irOptimized: 98438588 + -// gas legacy: 98438774 + -// gas legacyOptimized: 98438580 + +// gas irOptimized: 25388 + +// gas legacy: 98413174 + +// gas legacyOptimized: 25380 + @@ -44,3 +48,6 @@ contract D { + -// gas irOptimized: 98438589 + -// gas legacy: 98438774 + -// gas legacyOptimized: 98438580 + +// gas irOptimized: 25389 + +// gas legacy: 98413174 + +// gas legacyOptimized: 25380 + """).splitlines() + + self.assertEqual(collect_statistics(diff_output), ( + 98438588 + 98438589, # -irOptimized + 98438580 + 98438580, # -legacyOptimized + 102095 + 98438774 + 98438774, # -legacy + 25388 + 25389, # +irOptimized + 25380 + 25380, # +legacyOptimized + 76495 + 98413174 + 98413174, # +legacy + )) + + def test_collect_statistics_should_ignore_ir_costs(self): + diff_output = dedent(""" + -// gas legacy: 1 + -// gas ir: 2 + +// gas legacy: 3 + +// gas ir: 4 + """).splitlines() + + self.assertEqual(collect_statistics(diff_output), ( + 0, # -irOptimized + 0, # -legacyOptimized + 1, # -legacy + 0, # +irOptimized + 0, # +legacyOptimized + 3, # +legacy + )) + + def test_collect_statistics_should_ignore_unchanged_costs(self): + diff_output = dedent(""" + -// gas legacy: 1 + // gas legacyOptimized: 2 + +// gas legacy: 3 + """).splitlines() + + self.assertEqual(collect_statistics(diff_output), ( + 0, # -irOptimized + 0, # -legacyOptimized + 1, # -legacy + 0, # +irOptimized + 0, # +legacyOptimized + 3, # +legacy + )) From c6e23311cca599f25d1df87dcae8d2ce1f758793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 13:29:28 +0100 Subject: [PATCH 24/47] gas_diff_stats.py: Add a Python shebang - The script is executable but executes as a Bash script and fails. --- scripts/gas_diff_stats.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 234d42df0c..90a153cd31 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """A script to collect gas statistics and print it. Useful to summarize gas differences to semantic tests for a PR / branch. From e28a1d436a15e698b933f2a6cc5b160f2bcb3616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 13:31:42 +0100 Subject: [PATCH 25/47] gas_diff_stats.py: Print errors to stderr, not stdout --- scripts/gas_diff_stats.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 90a153cd31..b220485c00 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -18,7 +18,9 @@ repository. The changes are compared against ``origin/develop``. """ + import subprocess +import sys from pathlib import Path from enum import Enum from parsec import generate, ParseError, regex, string @@ -110,8 +112,8 @@ def try_parse_git_diff(fname): if diff_output: return collect_statistics(diff_output) except subprocess.CalledProcessError as e: - print("Error in the git diff:") - print(e.output) + print("Error in the git diff:", file=sys.stderr) + print(e.output, file=sys.stderr) return None def stat(old, new): return ((new - old) / old) * 100 if old else 0 From 5518a3074f0804e7d075122d27733b71812549c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 13:35:50 +0100 Subject: [PATCH 26/47] gas_diff_stats.py: Don't let shell evaluate file names and support names with spaces --- scripts/gas_diff_stats.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index b220485c00..6f8087d481 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -105,8 +105,7 @@ def semantictest_statistics(): def try_parse_git_diff(fname): try: diff_output = subprocess.check_output( - "git diff --unified=0 origin/develop HEAD " + fname, - shell=True, + ["git", "diff", "--unified=0", "origin/develop", "HEAD", fname], universal_newlines=True ).splitlines() if diff_output: From 39f3e7673f84f874a33515f383efca029b2abc49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 13:36:26 +0100 Subject: [PATCH 27/47] gas_diff_stats.py: Fail when the semantic test dir does not exist --- scripts/gas_diff_stats.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 6f8087d481..922aa7de45 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -35,6 +35,8 @@ class Diff(Enum): Minus = 1 Plus = 2 +SEMANTIC_TEST_DIR = Path("test/libsolidity/semanticTests/") + minus = string("-").result(Diff.Minus) plus = string("+").result(Diff.Plus) @@ -119,7 +121,10 @@ def stat(old, new): table = [] - for path in Path("test/libsolidity/semanticTests").rglob("*.sol"): + if not SEMANTIC_TEST_DIR.is_dir(): + sys.exit(f"Semantic tests not found. '{SEMANTIC_TEST_DIR.absolute()}' is missing or not a directory.") + + for path in SEMANTIC_TEST_DIR.rglob("*.sol"): fname = path.as_posix() parsed = try_parse_git_diff(fname) if parsed is None: From 855096b84b71aa5f5dd949f83e2dc90831f1e3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 15:17:41 +0100 Subject: [PATCH 28/47] gas_diff_stats.py: Skip non-gas lines to avoid having to silence parsing errors --- scripts/gas_diff_stats.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 922aa7de45..5d95d5a193 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -89,7 +89,12 @@ def try_parse(line): pass return None - out = [parsed for line in lines if (parsed := try_parse(line)) is not None] + out = [ + parsed + for line in lines + if line.startswith('+// gas ') or line.startswith('-// gas ') + if (parsed := try_parse(line)) is not None + ] diff_kinds = [Diff.Minus, Diff.Plus] codegen_kinds = [Kind.IrOptimized, Kind.LegacyOptimized, Kind.Legacy] return tuple( From b9c7b69c76ed73c57aef3681d6f29dd155d1607e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 15:57:36 +0100 Subject: [PATCH 29/47] gas_diff_stats.py: Explicitly ignore ir gas instead of failing to parse it --- scripts/gas_diff_stats.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 5d95d5a193..518d8c2c75 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -27,9 +27,10 @@ from tabulate import tabulate class Kind(Enum): - IrOptimized = 1 - Legacy = 2 - LegacyOptimized = 3 + Ir = 1 + IrOptimized = 2 + Legacy = 3 + LegacyOptimized = 4 class Diff(Enum): Minus = 1 @@ -44,6 +45,7 @@ class Diff(Enum): comment = string("//") colon = string(":") +gas_ir = string("gas ir").result(Kind.Ir) gas_ir_optimized = string("gas irOptimized").result(Kind.IrOptimized) gas_legacy_optimized = string("gas legacyOptimized").result(Kind.LegacyOptimized) gas_legacy = string("gas legacy").result(Kind.Legacy) @@ -64,7 +66,7 @@ def diff_string() -> (Kind, Diff, int): diff_kind = yield minus | plus yield comment yield space - codegen_kind = yield gas_ir_optimized ^ gas_legacy_optimized ^ gas_legacy + codegen_kind = yield gas_ir_optimized ^ gas_ir ^ gas_legacy_optimized ^ gas_legacy yield colon yield space val = yield number() From 65031d3b3e128cd30283afcec254d2326030069d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 15:22:17 +0100 Subject: [PATCH 30/47] gas_diff_stats.py: Handle errors instead of ignoring them - It's possible now that errors are something really exceptional and don't happen on every run. --- scripts/gas_diff_stats.py | 46 ++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 518d8c2c75..3527002524 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -84,18 +84,11 @@ def collect_statistics(lines) -> (int, int, int, int, int, int): if not lines: raise RuntimeError("Empty list") - def try_parse(line): - try: - return diff_string.parse(line) - except ParseError: - pass - return None - out = [ parsed for line in lines if line.startswith('+// gas ') or line.startswith('-// gas ') - if (parsed := try_parse(line)) is not None + if (parsed := diff_string.parse(line)) is not None ] diff_kinds = [Diff.Minus, Diff.Plus] codegen_kinds = [Kind.IrOptimized, Kind.LegacyOptimized, Kind.Legacy] @@ -111,18 +104,15 @@ def try_parse(line): def semantictest_statistics(): """Prints the tabulated statistics that can be pasted in github.""" - def try_parse_git_diff(fname): - try: - diff_output = subprocess.check_output( - ["git", "diff", "--unified=0", "origin/develop", "HEAD", fname], - universal_newlines=True - ).splitlines() - if diff_output: - return collect_statistics(diff_output) - except subprocess.CalledProcessError as e: - print("Error in the git diff:", file=sys.stderr) - print(e.output, file=sys.stderr) - return None + def parse_git_diff(fname): + diff_output = subprocess.check_output( + ["git", "diff", "--unified=0", "origin/develop", "HEAD", fname], + universal_newlines=True + ).splitlines() + if len(diff_output) == 0: + return None + return collect_statistics(diff_output) + def stat(old, new): return ((new - old) / old) * 100 if old else 0 @@ -133,7 +123,7 @@ def stat(old, new): for path in SEMANTIC_TEST_DIR.rglob("*.sol"): fname = path.as_posix() - parsed = try_parse_git_diff(fname) + parsed = parse_git_diff(fname) if parsed is None: continue ir_optimized = stat(parsed[0], parsed[3]) @@ -150,5 +140,17 @@ def stat(old, new): else: print("No differences found.") +def main(): + try: + semantictest_statistics() + except subprocess.CalledProcessError as exception: + sys.exit(f"Error in the git diff:\n{exception.output}") + except ParseError as exception: + sys.exit( + f"ParseError: {exception}\n\n" + f"{exception.text}\n" + f"{' ' * exception.index}^\n" + ) + if __name__ == "__main__": - semantictest_statistics() + main() From 43274fddef0ecc55f4026d089fef3928b0617680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 14:14:17 +0100 Subject: [PATCH 31/47] gas_diff_stats.py: Improve table and number formatting - Use blanks if percentage is infinite instead of misleadingly showing zero. - Round percentages to nearest integer (but indicate when numbers are only close to zero rather than exactly zero). Differences below one percent are rarely relevant, if ever. - Include % after the numbers. - Put file names in backticks to get them displayed using fixed-width font on github. --- scripts/gas_diff_stats.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 3527002524..0707b9857b 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -114,7 +114,16 @@ def parse_git_diff(fname): return collect_statistics(diff_output) def stat(old, new): - return ((new - old) / old) * 100 if old else 0 + if old == 0: + return '' + percentage = (new - old) / old * 100 + prefix = ( + # Distinguish actual zero from very small differences + '+' if round(percentage) == 0 and percentage > 0 else + '-' if round(percentage) == 0 and percentage < 0 else + '' + ) + return f'{prefix}{round(percentage)}%' table = [] @@ -129,12 +138,12 @@ def stat(old, new): ir_optimized = stat(parsed[0], parsed[3]) legacy_optimized = stat(parsed[1], parsed[4]) legacy = stat(parsed[2], parsed[5]) - fname = fname.split('/', 3)[-1] - table += [map(str, [fname, ir_optimized, legacy_optimized, legacy])] + fname = f"`{fname.split('/', 3)[-1]}`" + table += [[fname, ir_optimized, legacy_optimized, legacy]] if table: print("
Click for a table of gas differences\n") - table_header = ["File name", "IR-optimized (%)", "Legacy-Optimized (%)", "Legacy (%)"] + table_header = ["File name", "IR optimized", "Legacy optimized", "Legacy"] print(tabulate(table, headers=table_header, tablefmt="github")) print("
") else: From b88d690c66b963282a77e214001b160873434ddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 14:16:33 +0100 Subject: [PATCH 32/47] gas_diff_stats.py: Order rows in a deterministic way (by file path) --- scripts/gas_diff_stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 0707b9857b..7403b39172 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -144,7 +144,7 @@ def stat(old, new): if table: print("
Click for a table of gas differences\n") table_header = ["File name", "IR optimized", "Legacy optimized", "Legacy"] - print(tabulate(table, headers=table_header, tablefmt="github")) + print(tabulate(sorted(table), headers=table_header, tablefmt="github")) print("
") else: print("No differences found.") From 36f2d39282a9f951b0f4780193398f5084073874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 16:15:52 +0100 Subject: [PATCH 33/47] CI: Add a smoke test run for gas_diff_stats.py --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index e14a4ec78c..8a16effd0f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -980,6 +980,9 @@ jobs: - run: name: Python unit tests command: python3 test/pyscriptTests.py + - run: + name: Smoke test for gas_diff_stats.py + command: scripts/gas_diff_stats.py - matrix_notify_failure_unless_pr t_win_pyscripts: From a851c59bb9c6f226cfb483767a73ebf8b79e8329 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 21 Feb 2024 20:52:11 +0100 Subject: [PATCH 34/47] Fix ENS external test ensuring it applies memory-safe-assembly filter on files and not directories --- 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 aee291a1a4..178f468549 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -81,7 +81,7 @@ function ens_test sed -i "s|it\(('Cannot be called if CANNOT_CREATE_SUBDOMAIN is burned and is a new subdomain',\)|it.skip\1|g" test/wrapper/NameWrapper.js sed -i "s|it\(('Cannot be called if PARENT_CANNOT_CONTROL is burned and is an existing subdomain',\)|it.skip\1|g" test/wrapper/NameWrapper.js - find . -name "*.sol" -exec sed -i -e 's/^\(\s*\)\(assembly\)/\1\/\/\/ @solidity memory-safe-assembly\n\1\2/' '{}' \; + find . -name "*.sol" -type f -exec sed -i -e 's/^\(\s*\)\(assembly\)/\1\/\/\/ @solidity memory-safe-assembly\n\1\2/' '{}' \; for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn From d7aa37de2eaa20e5463d2a266d8804c5fa2c80e4 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 20 Feb 2024 18:35:07 +0100 Subject: [PATCH 35/47] Use latest release instead of main branch on external tests --- scripts/externalTests/common.sh | 39 +++++++++++++------------ scripts/externalTests/runners/base.py | 3 +- scripts/externalTests/test_helpers.py | 40 +++++++++++++++----------- test/externalTests/bleeps.sh | 3 +- test/externalTests/brink.sh | 12 ++------ test/externalTests/chainlink.sh | 3 +- test/externalTests/colony.sh | 3 +- test/externalTests/elementfi.sh | 5 ++-- test/externalTests/ens.sh | 3 +- test/externalTests/euler.sh | 3 +- test/externalTests/gnosis.sh | 6 ++-- test/externalTests/gp2.sh | 15 ++-------- test/externalTests/perpetual-pools.sh | 3 +- test/externalTests/pool-together.sh | 8 ++---- test/externalTests/prb-math.py | 3 +- test/externalTests/trident.sh | 3 +- test/externalTests/uniswap.sh | 3 +- test/externalTests/yield-liquidator.sh | 3 +- test/externalTests/zeppelin.sh | 18 ++---------- 19 files changed, 68 insertions(+), 108 deletions(-) diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 3bca968a5a..e49be6c8a0 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -106,25 +106,28 @@ function setup_solc function download_project { - local repo="$1" - local ref_type="$2" - local solcjs_ref="$3" - local test_dir="$4" - - [[ $ref_type == commit || $ref_type == branch || $ref_type == tag ]] || assertFail - - printLog "Cloning ${ref_type} ${solcjs_ref} of ${repo}..." - if [[ $ref_type == commit ]]; then - mkdir ext - cd ext - git init - git remote add origin "$repo" - git fetch --depth 1 origin "$solcjs_ref" - git reset --hard FETCH_HEAD - else - git clone --depth 1 "$repo" -b "$solcjs_ref" "$test_dir/ext" - cd ext + local repo_url="$1" + local ref="$2" + local test_dir="$3" + + printLog "Cloning ${repo_url}..." + # Clone the repo ignoring all blobs until needed by git. + # This allows access to commit history but with a fast initial clone + git clone --filter=blob:none "$repo_url" "$test_dir/ext" + cd "$test_dir/ext" + + # If the ref is '' try to use the latest tag as ref + # NOTE: Sadly this will not work with monorepos and may not always + # return the latest tag. + if [[ "$ref" == "" ]]; then + ref=$(git tag --sort=-v:refname | head --lines=1) fi + + [[ $ref != "" ]] || assertFail + + printLog "Using ref: ${ref}" + git checkout "$ref" + echo "Current commit hash: $(git rev-parse HEAD)" } diff --git a/scripts/externalTests/runners/base.py b/scripts/externalTests/runners/base.py index a79ed53442..c3807c528c 100644 --- a/scripts/externalTests/runners/base.py +++ b/scripts/externalTests/runners/base.py @@ -47,7 +47,6 @@ class TestConfig: name: str repo_url: str - ref_type: str ref: str compile_only_presets: List[SettingsPreset] = field(default_factory=list) settings_presets: List[SettingsPreset] = field(default_factory=lambda: list(SettingsPreset)) @@ -134,7 +133,7 @@ def run_test(runner: BaseRunner): print(f"Using compiler version {solc_version}") # Download project - download_project(runner.test_dir, runner.config.repo_url, runner.config.ref_type, runner.config.ref) + download_project(runner.test_dir, runner.config.repo_url, runner.config.ref) # Configure run environment runner.setup_environment() diff --git a/scripts/externalTests/test_helpers.py b/scripts/externalTests/test_helpers.py index 9a573d50ad..576db4429b 100644 --- a/scripts/externalTests/test_helpers.py +++ b/scripts/externalTests/test_helpers.py @@ -96,23 +96,29 @@ def parse_command_line(description: str, args: List[str]): return arg_parser.parse_args(args) -def download_project(test_dir: Path, repo_url: str, ref_type: str = "branch", ref: str = "master"): - assert ref_type in ("commit", "branch", "tag") - - print(f"Cloning {ref_type} {ref} of {repo_url}...") - if ref_type == "commit": - os.mkdir(test_dir) - os.chdir(test_dir) - subprocess.run(["git", "init"], check=True) - subprocess.run(["git", "remote", "add", "origin", repo_url], check=True) - subprocess.run(["git", "fetch", "--depth", "1", "origin", ref], check=True) - subprocess.run(["git", "reset", "--hard", "FETCH_HEAD"], check=True) - else: - os.chdir(test_dir.parent) - subprocess.run(["git", "clone", "--no-progress", "--depth", "1", repo_url, "-b", ref, test_dir.resolve()], check=True) - if not test_dir.exists(): - raise RuntimeError("Failed to clone the project.") - os.chdir(test_dir) +def download_project(test_dir: Path, repo_url: str, ref: str = ""): + print(f"Cloning {repo_url}...") + # Clone the repo ignoring all blobs until needed by git. + # This allows access to commit history but with a fast initial clone + subprocess.run(["git", "clone", "--filter", "blob:none", repo_url, test_dir.resolve()], check=True) + if not test_dir.exists(): + raise RuntimeError("Failed to clone the project.") + os.chdir(test_dir) + + # If the ref is '' try to use the latest tag as ref + # NOTE: Sadly this will not work with monorepos and may not always + # return the latest tag. + if ref == "": + tags = subprocess.check_output( + ["git", "tag", "--sort", "-v:refname"], + encoding="ascii" + ).strip().split('\n') + if len(tags) == 0: + raise RuntimeError("Failed to retrieve latest release tag.") + ref = tags[0] + + print(f"Using ref: {ref}") + subprocess.run(["git", "checkout", ref], check=True) if (test_dir / ".gitmodules").exists(): subprocess.run(["git", "submodule", "update", "--init"], check=True) diff --git a/test/externalTests/bleeps.sh b/test/externalTests/bleeps.sh index 30f0ec9240..5090e6c12e 100755 --- a/test/externalTests/bleeps.sh +++ b/test/externalTests/bleeps.sh @@ -38,7 +38,6 @@ function test_fn { HARDHAT_DEPLOY_FIXTURE=true npx --no hardhat --no-compile tes function bleeps_test { local repo="https://github.com/wighawag/bleeps" - local ref_type=branch local ref=main local config_file="hardhat.config.ts" local config_var=config @@ -58,7 +57,7 @@ function bleeps_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" pushd "common-lib/" neutralize_package_json_hooks diff --git a/test/externalTests/brink.sh b/test/externalTests/brink.sh index 1c3ad2e19a..48cc4028f3 100755 --- a/test/externalTests/brink.sh +++ b/test/externalTests/brink.sh @@ -37,8 +37,7 @@ function test_fn { SNAPSHOT_UPDATE=1 npx --no hardhat test; } function brink_test { local repo="https://github.com/brinktrade/brink-core" - local ref_type=branch - local ref=master + local ref="" local config_file="hardhat.config.js" local config_var="" local extra_settings="metadata: {bytecodeHash: 'none'}" @@ -60,25 +59,18 @@ function brink_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # TODO: Remove this when Brink merges https://github.com/brinktrade/brink-core/pull/52 sed -i "s|\(function isValidSignature(bytes \)calldata\( _data, bytes \)calldata\( _signature)\)|\1memory\2memory\3|g" src/Test/MockEIP1271Validator.sol - neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" "$CURRENT_EVM_VERSION" "$extra_settings" "$extra_optimizer_settings" yarn install yarn add hardhat-gas-reporter - # TODO: Remove when https://github.com/brinktrade/brink-core/issues/48 is fixed. - # TODO: Chai is ESM-only since version 5.x (see: https://github.com/chaijs/chai/issues/1561#issuecomment-1871134261), - # thus, we should stick to version 4.x until Brink and other dependencies also migrate to ESM. - yarn add chai@4.4.0 - replace_version_pragmas - for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" "$extra_settings" "$extra_optimizer_settings" store_benchmark_report hardhat brink "$repo" "$preset" diff --git a/test/externalTests/chainlink.sh b/test/externalTests/chainlink.sh index 4d5080730f..f11156713c 100755 --- a/test/externalTests/chainlink.sh +++ b/test/externalTests/chainlink.sh @@ -37,7 +37,6 @@ function test_fn { yarn test; } function chainlink_test { local repo="https://github.com/solidity-external-tests/chainlink" - local ref_type=branch local ref=develop_080 local config_file="hardhat.config.ts" local config_var=config @@ -58,7 +57,7 @@ function chainlink_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" cd "contracts/" diff --git a/test/externalTests/colony.sh b/test/externalTests/colony.sh index 402865107a..1dcd7deaa3 100755 --- a/test/externalTests/colony.sh +++ b/test/externalTests/colony.sh @@ -37,7 +37,6 @@ function test_fn { yarn run test:contracts; } function colony_test { local repo="https://github.com/solidity-external-tests/colonyNetwork.git" - local ref_type=branch local ref="develop_080" local config_file="truffle.js" @@ -57,7 +56,7 @@ function colony_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" neutralize_package_json_hooks diff --git a/test/externalTests/elementfi.sh b/test/externalTests/elementfi.sh index 94e622d10c..f3ecbb1417 100755 --- a/test/externalTests/elementfi.sh +++ b/test/externalTests/elementfi.sh @@ -37,8 +37,7 @@ function test_fn { npm run test; } function elementfi_test { local repo="https://github.com/element-fi/elf-contracts" - local ref_type=branch - local ref=main + local ref="" local config_file="hardhat.config.ts" local config_var=config @@ -60,7 +59,7 @@ function elementfi_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" chmod +x scripts/load-balancer-contracts.sh scripts/load-balancer-contracts.sh diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index aee291a1a4..a79d26c4ef 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -37,7 +37,6 @@ function test_fn { yarn test; } function ens_test { local repo="https://github.com/ensdomains/ens-contracts.git" - local ref_type=commit local ref="083d29a2c50cd0a8307386abf8fadc217b256256" local config_file="hardhat.config.js" @@ -57,7 +56,7 @@ function ens_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" neutralize_package_lock neutralize_package_json_hooks diff --git a/test/externalTests/euler.sh b/test/externalTests/euler.sh index 80f18e702d..9ede1a3406 100755 --- a/test/externalTests/euler.sh +++ b/test/externalTests/euler.sh @@ -40,7 +40,6 @@ function test_fn { function euler_test { local repo="https://github.com/euler-xyz/euler-contracts" - local ref_type=branch local ref="master" local config_file="hardhat.config.js" @@ -59,7 +58,7 @@ function euler_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 5f7ea48765..218a5a7504 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -37,8 +37,7 @@ function test_fn { npm test; } function gnosis_safe_test { local repo="https://github.com/safe-global/safe-contracts.git" - local ref_type=branch - local ref=main + local ref="" local config_file="hardhat.config.ts" local config_var=userConfig @@ -58,7 +57,7 @@ function gnosis_safe_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" # NOTE: The patterns below intentionally have hard-coded versions. @@ -77,7 +76,6 @@ function gnosis_safe_test sed -i "s|\(it\)\((\"can be used only via DELEGATECALL opcode\"\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts sed -i "s|it\((\"can only be called from Safe itself\"\)|it.skip\1|g" test/libraries/Migration.spec.ts - neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index bbb442226f..1e52134a43 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -37,8 +37,7 @@ function test_fn { yarn test; } function gp2_test { local repo="https://github.com/cowprotocol/contracts.git" - local ref_type=branch - local ref=main + local ref="" local config_file="hardhat.config.ts" local config_var="config" @@ -58,10 +57,9 @@ function gp2_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" [[ $BINARY_TYPE == native ]] && replace_global_solc "$BINARY_PATH" - neutralize_package_lock neutralize_package_json_hooks name_hardhat_default_export "$config_file" "$config_var" force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" @@ -69,14 +67,6 @@ function gp2_test force_hardhat_unlimited_contract_size "$config_file" "$config_var" yarn - # Workaround for error caused by the last release of hardhat-waffle@2.0.6 that bumps ethereum-waffle - # to version 4.0.10 and breaks gp2 build with the following error: - # - # Cannot find module 'ethereum-waffle/dist/cjs/src/deployContract' - # - # See: https://github.com/NomicFoundation/hardhat-waffle/commit/83ee9cb36ee59d0bedacbbd00043f030af104ad0 - yarn add '@nomiclabs/hardhat-waffle@2.0.5' - # Some dependencies come with pre-built artifacts. We want to build from scratch. rm -r node_modules/@gnosis.pm/safe-contracts/build/ @@ -104,7 +94,6 @@ function gp2_test sed -i 's|it\(("should revert when encoding invalid flags"\)|it.skip\1|g' test/GPv2Trade.test.ts replace_version_pragmas - for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" store_benchmark_report hardhat gp2 "$repo" "$preset" diff --git a/test/externalTests/perpetual-pools.sh b/test/externalTests/perpetual-pools.sh index 8d8dc34e21..31748a40ca 100755 --- a/test/externalTests/perpetual-pools.sh +++ b/test/externalTests/perpetual-pools.sh @@ -37,7 +37,6 @@ function test_fn { yarn test; } function perpetual_pools_test { local repo="https://github.com/solidity-external-tests/perpetual-pools-contracts" - local ref_type=branch local ref=pools-v2 local config_file="hardhat.config.ts" local config_var="config" @@ -57,7 +56,7 @@ function perpetual_pools_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index 3f7141d9ba..f841206ef2 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -36,9 +36,8 @@ function test_fn { yarn test; } function pool_together_test { - local repo="https://github.com/pooltogether/v4-core" - local ref_type=branch - local ref=master + local repo="https://github.com/pooltogether/v4-core.git" + local ref="" local config_file="hardhat.config.ts" local config_var="config" @@ -57,13 +56,12 @@ function pool_together_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # TODO: Remove this when https://github.com/NomicFoundation/hardhat/issues/3365 gets fixed. sed -i "s|it\(('should fail to return value if value passed does not fit in [0-9]\+ bits'\)|it.skip\1|g" test/libraries/ExtendedSafeCast.test.ts sed -i "s|it\(('should require an rng to be requested'\)|it.skip\1|g" test/DrawBeacon.test.ts - neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" diff --git a/test/externalTests/prb-math.py b/test/externalTests/prb-math.py index e57688ec2e..2d1469fc90 100755 --- a/test/externalTests/prb-math.py +++ b/test/externalTests/prb-math.py @@ -51,8 +51,7 @@ def configure(self): test_config = TestConfig( name="PRBMath", repo_url="https://github.com/PaulRBerg/prb-math.git", - ref_type="branch", - ref="main", + ref="", compile_only_presets=[ # pylint: disable=line-too-long # SettingsPreset.IR_NO_OPTIMIZE, # Error: Yul exception:Variable expr_15699_address is 2 slot(s) too deep inside the stack. Stack too deep. diff --git a/test/externalTests/trident.sh b/test/externalTests/trident.sh index d8d94eb3c1..e5fa914e9c 100755 --- a/test/externalTests/trident.sh +++ b/test/externalTests/trident.sh @@ -45,7 +45,6 @@ function test_fn { function trident_test { local repo="https://github.com/sushiswap/trident" - local ref_type=commit # FIXME: Switch back to master branch when https://github.com/sushiswap/trident/issues/303 gets fixed. local ref="0cab5ae884cc9a41223d52791be775c3a053cb26" # master as of 2021-12-16 local config_file="hardhat.config.ts" @@ -66,7 +65,7 @@ function trident_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # TODO: Currently tests work only with the exact versions from yarn.lock. # Re-enable this when https://github.com/sushiswap/trident/issues/284 is fixed. diff --git a/test/externalTests/uniswap.sh b/test/externalTests/uniswap.sh index 8d2551b619..bf5f828987 100755 --- a/test/externalTests/uniswap.sh +++ b/test/externalTests/uniswap.sh @@ -37,7 +37,6 @@ function test_fn { UPDATE_SNAPSHOT=1 npx hardhat test; } function uniswap_test { local repo="https://github.com/solidity-external-tests/uniswap-v3-core.git" - local ref_type=branch local ref=main_080 local config_file="hardhat.config.ts" local config_var=config @@ -57,7 +56,7 @@ function uniswap_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. diff --git a/test/externalTests/yield-liquidator.sh b/test/externalTests/yield-liquidator.sh index 7a4353af57..16a6287e53 100755 --- a/test/externalTests/yield-liquidator.sh +++ b/test/externalTests/yield-liquidator.sh @@ -37,7 +37,6 @@ function test_fn { npm run test; } function yield_liquidator_test { local repo="https://github.com/yieldprotocol/yield-liquidator-v2" - local ref_type=branch local ref="master" local config_file="hardhat.config.ts" local config_var="module.exports" @@ -57,7 +56,7 @@ function yield_liquidator_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" neutralize_package_lock neutralize_package_json_hooks diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 9f72aa4ec9..655e4814f7 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -42,8 +42,7 @@ function test_fn { npm test; } function zeppelin_test { local repo="https://github.com/OpenZeppelin/openzeppelin-contracts.git" - local ref_type=branch - local ref="master" + local ref="" local config_file="hardhat.config.js" local compile_only_presets=( @@ -62,7 +61,7 @@ function zeppelin_test print_presets_or_exit "$SELECTED_PRESETS" setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref_type" "$ref" "$DIR" + download_project "$repo" "$ref" "$DIR" # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables # them for other presets but that's fine - we want same code run for benchmarks to be comparable. @@ -100,25 +99,12 @@ function zeppelin_test # Here only the testToInt(248) and testToInt(256) cases fail so change the loop range to skip them sed -i "s|range(8, 256, 8)\(.forEach(bits => testToInt(bits));\)|range(8, 240, 8)\1|" test/utils/math/SafeCast.test.js - neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" npm install - # TODO: We fix the version to 2.0.3 instead of 2.0.4 since the latter does not work with ethers.js 6.10.0 - # Maybe related to the use of dynamic imports here: https://github.com/NomicFoundation/hardhat/commit/16ae15642951ac324ef7093a3342f7cf3a2a49a4 - npm install @nomicfoundation/hardhat-chai-matchers@2.0.3 - - # TODO: Remove when OpenZeppelin update to ethers 6.11.1+ - # Prior versions of ethers accepts an object instead of a string as an argument to the toUtf8Bytes function. - # However, starting from Ethers version 6.11.1, string arguments are enforced, - # which causes the introduced assertion to fail in some OpenZeppelin tests. - # See: https://github.com/ethers-io/ethers.js/issues/4583 - npm install ethers@6.11.0 - replace_version_pragmas - for preset in $SELECTED_PRESETS; do hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn store_benchmark_report hardhat zeppelin "$repo" "$preset" From a9a870d8fc87e43e89467cabfe9c6b84217c715b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 7 Feb 2024 14:53:31 +0100 Subject: [PATCH 36/47] Test coverage for existing parsing and formatting functionality of gas expectations --- test/libsolidity/util/TestFileParserTests.cpp | 70 +++++++++++++++---- .../util/TestFunctionCallTests.cpp | 28 ++++++++ 2 files changed, 86 insertions(+), 12 deletions(-) diff --git a/test/libsolidity/util/TestFileParserTests.cpp b/test/libsolidity/util/TestFileParserTests.cpp index 59934fdb25..46499c1475 100644 --- a/test/libsolidity/util/TestFileParserTests.cpp +++ b/test/libsolidity/util/TestFileParserTests.cpp @@ -49,18 +49,18 @@ std::vector parse(std::string const& _source, std::map _rawArguments = std::vector{}, - bool _isConstructor = false, - bool _isLibrary = false + FunctionCall const& _call, + FunctionCall::DisplayMode _mode, + std::string _signature = "", + bool _failure = true, + bytes _arguments = bytes{}, + bytes _expectations = bytes{}, + FunctionValue _value = { 0 }, + std::string _argumentComment = "", + std::string _expectationComment = "", + std::vector _rawArguments = std::vector{}, + bool _isConstructor = false, + bool _isLibrary = false ) { BOOST_REQUIRE_EQUAL(_call.expectations.failure, _failure); @@ -1063,6 +1063,52 @@ BOOST_AUTO_TEST_CASE(call_effects) BOOST_CHECK_THROW(parse(source, builtins), std::exception); } +BOOST_AUTO_TEST_CASE(gas) +{ + char const* source = R"( + // f() -> + // gas ir: 3245 + // gas legacy: 5000 + // gas legacyOptimized: 0 + )"; + auto const calls = parse(source); + BOOST_REQUIRE_EQUAL(calls.size(), 1); + BOOST_REQUIRE_EQUAL(calls[0].expectations.failure, false); + BOOST_TEST(calls[0].expectations.gasUsed == (std::map{ + {"ir", 3245}, + {"legacy", 5000}, + {"legacyOptimized", 0}, + })); +} + +BOOST_AUTO_TEST_CASE(gas_before_call) +{ + char const* source = R"( + // gas ir: 3245 + // f() -> + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_invalid_run_type) +{ + char const* source = R"( + // f() -> + // gas ir: 3245 + // gas experimental: 5000 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_duplicate_run_type) +{ + char const* source = R"( + // f() -> + // gas ir: 3245 + // gas ir: 3245 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/util/TestFunctionCallTests.cpp b/test/libsolidity/util/TestFunctionCallTests.cpp index fa3fe995ca..74a45c3268 100644 --- a/test/libsolidity/util/TestFunctionCallTests.cpp +++ b/test/libsolidity/util/TestFunctionCallTests.cpp @@ -250,6 +250,34 @@ BOOST_AUTO_TEST_CASE(format_failure_singleline) BOOST_REQUIRE_EQUAL(test.format(), "// f(uint8): 1 -> FAILURE"); } +BOOST_AUTO_TEST_CASE(format_gas) +{ + FunctionCall call{ + "f()", + FunctionValue{0}, + FunctionCallArgs{}, + FunctionCallExpectations{ + std::vector{}, + false, // failure + "some comment", + { + {"ir", 3245}, + {"legacy", 5000}, + {"legacy optimized", 0}, + }, + } + }; + call.omitsArrow = false; + + BOOST_REQUIRE_EQUAL( + TestFunctionCall(call).format(), + "// f() -> #some comment#\n" + "// gas ir: 3245\n" + "// gas legacy: 5000\n" + "// gas legacy optimized: 0" + ); +} + BOOST_AUTO_TEST_SUITE_END() } From e47e948ff6d1319660b98d1502eff44356c303aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 13:07:13 +0100 Subject: [PATCH 37/47] SoltesTypes: Fix outdated comment about allowed keys in gasUsed --- test/libsolidity/util/SoltestTypes.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/libsolidity/util/SoltestTypes.h b/test/libsolidity/util/SoltestTypes.h index b5b746e325..672e705534 100644 --- a/test/libsolidity/util/SoltestTypes.h +++ b/test/libsolidity/util/SoltestTypes.h @@ -216,7 +216,9 @@ struct FunctionCallExpectations return raw; } /// Gas used by function call - /// Should have values for Yul, YulOptimized, Legacy and LegacyOptimized + /// Keys represent all distinct combinations of compilation settings that affect produced + /// bytecode (and therefore the cost), except for EVM version. E.g. IR codegen without + /// optimization legacy codegen with optimization. std::map gasUsed; }; From d98c9438b2779ad554a179ca2d537d3da2dda33b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 7 Feb 2024 18:39:44 +0100 Subject: [PATCH 38/47] TestFunctionCall::formatGasExpectations(): runType can't be empty in practice --- test/libsolidity/util/TestFunctionCall.cpp | 43 +++++++++++----------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index 64dfbd9825..716dbff13b 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -339,27 +339,28 @@ std::string TestFunctionCall::formatGasExpectations( { std::stringstream os; for (auto const& [runType, gasUsed]: (_useActualCost ? m_gasCosts : m_call.expectations.gasUsed)) - if (!runType.empty()) - { - bool differentResults = - m_gasCosts.count(runType) > 0 && - m_call.expectations.gasUsed.count(runType) > 0 && - m_gasCosts.at(runType) != m_call.expectations.gasUsed.at(runType); - - s256 difference = 0; - if (differentResults) - difference = - static_cast(m_gasCosts.at(runType)) - - static_cast(m_call.expectations.gasUsed.at(runType)); - int percent = 0; - if (differentResults) - percent = static_cast( - 100.0 * (static_cast(difference) / static_cast(m_call.expectations.gasUsed.at(runType))) - ); - os << std::endl << _linePrefix << "// gas " << runType << ": " << (gasUsed.str()); - if (_showDifference && differentResults && _useActualCost) - os << " [" << std::showpos << difference << " (" << percent << "%)]"; - } + { + soltestAssert(runType != ""); + + bool differentResults = + m_gasCosts.count(runType) > 0 && + m_call.expectations.gasUsed.count(runType) > 0 && + m_gasCosts.at(runType) != m_call.expectations.gasUsed.at(runType); + + s256 difference = 0; + if (differentResults) + difference = + static_cast(m_gasCosts.at(runType)) - + static_cast(m_call.expectations.gasUsed.at(runType)); + int percent = 0; + if (differentResults) + percent = static_cast( + 100.0 * (static_cast(difference) / static_cast(m_call.expectations.gasUsed.at(runType))) + ); + os << std::endl << _linePrefix << "// gas " << runType << ": " << (gasUsed.str()); + if (_showDifference && differentResults && _useActualCost) + os << " [" << std::showpos << difference << " (" << percent << "%)]"; + } return os.str(); } From c55c8b5504fdb8789741883e5af6f890be2b5cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 7 Feb 2024 19:42:41 +0100 Subject: [PATCH 39/47] TestFunctionCall::formatGasExpectations(): Move diffing into a helper --- test/libsolidity/util/TestFunctionCall.cpp | 43 +++++++++++++--------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index 716dbff13b..1d8c721919 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -331,6 +332,23 @@ std::string TestFunctionCall::formatRawParameters( return os.str(); } +namespace +{ + +std::string formatGasDiff(std::optional const& _gasUsed, std::optional const& _reference) +{ + if (!_reference.has_value() || !_gasUsed.has_value() || _gasUsed == _reference) + return ""; + + s256 difference = static_cast(*_gasUsed) - static_cast(*_reference); + int percent = static_cast( + 100.0 * (static_cast(difference) / static_cast(*_reference)) + ); + return fmt::format("{} ({:+}%)", difference.str(), percent); +} + +} + std::string TestFunctionCall::formatGasExpectations( std::string const& _linePrefix, bool _useActualCost, @@ -342,24 +360,13 @@ std::string TestFunctionCall::formatGasExpectations( { soltestAssert(runType != ""); - bool differentResults = - m_gasCosts.count(runType) > 0 && - m_call.expectations.gasUsed.count(runType) > 0 && - m_gasCosts.at(runType) != m_call.expectations.gasUsed.at(runType); - - s256 difference = 0; - if (differentResults) - difference = - static_cast(m_gasCosts.at(runType)) - - static_cast(m_call.expectations.gasUsed.at(runType)); - int percent = 0; - if (differentResults) - percent = static_cast( - 100.0 * (static_cast(difference) / static_cast(m_call.expectations.gasUsed.at(runType))) - ); - os << std::endl << _linePrefix << "// gas " << runType << ": " << (gasUsed.str()); - if (_showDifference && differentResults && _useActualCost) - os << " [" << std::showpos << difference << " (" << percent << "%)]"; + os << std::endl << _linePrefix << "// gas " << runType << ": " << gasUsed.str(); + std::string gasDiff = formatGasDiff( + m_gasCosts.count(runType) > 0 ? std::make_optional(m_gasCosts.at(runType)) : std::nullopt, + m_call.expectations.gasUsed.count(runType) > 0 ? std::make_optional(m_call.expectations.gasUsed.at(runType)) : std::nullopt + ); + if (_showDifference && !gasDiff.empty() && _useActualCost) + os << " [" << gasDiff << "]"; } return os.str(); } From cd94139f3f666ea3087122a46ab8b461722bd4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 7 Feb 2024 19:51:57 +0100 Subject: [PATCH 40/47] TestFunctionCall::formatGasExpectations(): Handle corner cases properly --- test/libsolidity/util/TestFunctionCall.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index 1d8c721919..7a77f72879 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -340,7 +340,13 @@ std::string formatGasDiff(std::optional const& _gasUsed, std::optional(*_gasUsed) - static_cast(*_reference); + + if (*_reference == 0) + return fmt::format("{}", difference.str()); + int percent = static_cast( 100.0 * (static_cast(difference) / static_cast(*_reference)) ); From d5bae3f5973c54395e450762ce8df25ba1dd3285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 7 Feb 2024 20:00:19 +0100 Subject: [PATCH 41/47] TestFunctionCall::formatGasExpectations(): Helper for getting optional values from a map --- test/libsolidity/util/TestFunctionCall.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index 7a77f72879..54dd769d61 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -353,6 +353,16 @@ std::string formatGasDiff(std::optional const& _gasUsed, std::optional gasOrNullopt(std::map const& _map, std::string const& _key) +{ + auto it = _map.find(_key); + if (it == _map.end()) + return std::nullopt; + + return it->second; +} + } std::string TestFunctionCall::formatGasExpectations( @@ -368,8 +378,8 @@ std::string TestFunctionCall::formatGasExpectations( os << std::endl << _linePrefix << "// gas " << runType << ": " << gasUsed.str(); std::string gasDiff = formatGasDiff( - m_gasCosts.count(runType) > 0 ? std::make_optional(m_gasCosts.at(runType)) : std::nullopt, - m_call.expectations.gasUsed.count(runType) > 0 ? std::make_optional(m_call.expectations.gasUsed.at(runType)) : std::nullopt + gasOrNullopt(m_gasCosts, runType), + gasOrNullopt(m_call.expectations.gasUsed, runType) ); if (_showDifference && !gasDiff.empty() && _useActualCost) os << " [" << gasDiff << "]"; From 2ee4d6b1eeaee104007a64ce0b23faa57862800d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 9 Feb 2024 19:24:34 +0100 Subject: [PATCH 42/47] Keep track of code deposit gas when executing contract code --- test/EVMHost.cpp | 7 ++++++- test/EVMHost.h | 7 +++++++ test/ExecutionFramework.cpp | 2 ++ test/ExecutionFramework.h | 6 ++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 9af4d7099d..c43d53d6bc 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -161,6 +161,7 @@ void EVMHost::reset() recorded_calls.clear(); // Clear EIP-2929 account access indicator recorded_account_accesses.clear(); + m_totalCodeDepositGas = 0; // Mark all precompiled contracts as existing. Existing here means to have a balance (as per EIP-161). // NOTE: keep this in sync with `EVMHost::call` below. @@ -203,6 +204,7 @@ void EVMHost::newTransactionFrame() // Otherwise, the previous behavior (pre-Cancun) is maintained. accounts.erase(address); newlyCreatedAccounts.clear(); + m_totalCodeDepositGas = 0; recorded_selfdestructs.clear(); } @@ -392,15 +394,18 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2) { - result.gas_left -= static_cast(evmasm::GasCosts::createDataGas * result.output_size); + int64_t codeDepositGas = static_cast(evmasm::GasCosts::createDataGas * result.output_size); + result.gas_left -= codeDepositGas; if (result.gas_left < 0) { + m_totalCodeDepositGas += -result.gas_left; result.gas_left = 0; result.status_code = EVMC_OUT_OF_GAS; // TODO clear some fields? } else { + m_totalCodeDepositGas += codeDepositGas; result.create_address = message.recipient; destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size); destination.codehash = convertToEVMC(keccak256({result.output_data, result.output_size})); diff --git a/test/EVMHost.h b/test/EVMHost.h index 144596e05e..848314c879 100644 --- a/test/EVMHost.h +++ b/test/EVMHost.h @@ -94,6 +94,8 @@ class EVMHost: public evmc::MockedHost /// @returns contents of storage at @param _addr. StorageMap const& get_address_storage(evmc::address const& _addr); + u256 totalCodeDepositGas() const { return m_totalCodeDepositGas; } + static Address convertFromEVMC(evmc::address const& _addr); static evmc::address convertToEVMC(Address const& _addr); static util::h256 convertFromEVMC(evmc::bytes32 const& _data); @@ -137,6 +139,11 @@ class EVMHost: public evmc::MockedHost langutil::EVMVersion m_evmVersion; /// EVM version requested from EVMC (matches the above) evmc_revision m_evmRevision; + + /// The part of the total cost of the current transaction that paid for the code deposits. + /// I.e. GAS_CODE_DEPOSIT times the total size of deployed code of all newly created contracts, + /// including the current contract itself if it was a creation transaction. + u256 m_totalCodeDepositGas; }; class EVMHostPrinter diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 9fc36440b3..0081ba4a9d 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -191,6 +191,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 auto const gasRefund = std::min(u256(result.gas_refund), totalGasUsed / refundRatio); m_gasUsed = totalGasUsed - gasRefund; + m_gasUsedForCodeDeposit = m_evmcHost->totalCodeDepositGas(); m_transactionSuccessful = (result.status_code == EVMC_SUCCESS); if (m_showMessages) @@ -199,6 +200,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 std::cout << " result: " << static_cast(result.status_code) << std::endl; std::cout << " gas used: " << m_gasUsed.str() << std::endl; std::cout << " gas used (without refund): " << totalGasUsed.str() << std::endl; + std::cout << " code deposits only: " << m_gasUsedForCodeDeposit.str() << std::endl; std::cout << " gas refund (total): " << result.gas_refund << std::endl; std::cout << " gas refund (bound): " << gasRefund.str() << std::endl; } diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 27ceb4f280..5d66ea10d0 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -303,7 +303,13 @@ class ExecutionFramework util::h160 m_sender = account(0); util::h160 m_contractAddress; bytes m_output; + + /// Total gas used by the transaction, after refund. u256 m_gasUsed; + + /// The portion of @a m_gasUsed spent on code deposits of newly created contracts. + /// May exceed @a m_gasUsed in rare corner cases due to refunds. + u256 m_gasUsedForCodeDeposit; }; #define ABI_CHECK(result, expectation) do { \ From 96233864437e304b6c02c867b29ffe428a72c630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 9 Feb 2024 19:27:07 +0100 Subject: [PATCH 43/47] Separate 'code' gas settings in semantic tests --- test/libsolidity/SemanticTest.cpp | 10 +- test/libsolidity/util/SoltestTypes.h | 5 + test/libsolidity/util/TestFileParser.cpp | 42 ++++++-- test/libsolidity/util/TestFileParserTests.cpp | 102 ++++++++++++++++++ test/libsolidity/util/TestFunctionCall.cpp | 22 ++++ test/libsolidity/util/TestFunctionCall.h | 9 +- .../util/TestFunctionCallTests.cpp | 65 ++++++++--- 7 files changed, 231 insertions(+), 24 deletions(-) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 25113b689d..676c39eaf9 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -569,6 +569,11 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp (_compileViaYul ? "ir"s : "legacy"s) + (m_optimiserSettings == OptimiserSettings::full() ? "Optimized" : ""); + soltestAssert( + io_test.call().expectations.gasUsed.count(setting) == + io_test.call().expectations.gasUsedForCodeDeposit.count(setting) + ); + // We don't check gas if enforce gas cost is not active // or test is run with abi encoder v1 only // or gas used less than threshold for enforcing feature @@ -587,9 +592,12 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp solAssert(!m_runWithABIEncoderV1Only, ""); io_test.setGasCost(setting, m_gasUsed); + io_test.setCodeDepositGasCost(setting, m_gasUsedForCodeDeposit); + return io_test.call().expectations.gasUsed.count(setting) > 0 && - m_gasUsed == io_test.call().expectations.gasUsed.at(setting); + m_gasUsed == io_test.call().expectations.gasUsed.at(setting) && + m_gasUsedForCodeDeposit == io_test.call().expectations.gasUsedForCodeDeposit.at(setting); } void SemanticTest::printSource(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const diff --git a/test/libsolidity/util/SoltestTypes.h b/test/libsolidity/util/SoltestTypes.h index 672e705534..a2d593fd3c 100644 --- a/test/libsolidity/util/SoltestTypes.h +++ b/test/libsolidity/util/SoltestTypes.h @@ -220,6 +220,11 @@ struct FunctionCallExpectations /// bytecode (and therefore the cost), except for EVM version. E.g. IR codegen without /// optimization legacy codegen with optimization. std::map gasUsed; + + /// The portion of @a gasUsed spent on code deposits of newly created contracts. + /// May exceed @a gasUsed in rare corner cases due to refunds. + /// Keys must always match @a gasUsedExcludingCode. + std::map gasUsedForCodeDeposit; }; /** diff --git a/test/libsolidity/util/TestFileParser.cpp b/test/libsolidity/util/TestFileParser.cpp index 3fba998a07..e7e20f7c5c 100644 --- a/test/libsolidity/util/TestFileParser.cpp +++ b/test/libsolidity/util/TestFileParser.cpp @@ -84,18 +84,31 @@ std::vector TestFileParser::parseFunctio BOOST_THROW_EXCEPTION(TestParserError("Expected function call before gas usage filter.")); std::string runType = m_scanner.currentLiteral(); - if (std::set{"ir", "irOptimized", "legacy", "legacyOptimized"}.count(runType) > 0) - { - m_scanner.scanNextToken(); - expect(Token::Colon); - if (calls.back().expectations.gasUsed.count(runType) > 0) - throw TestParserError("Gas usage expectation set multiple times."); - calls.back().expectations.gasUsed[runType] = u256(parseDecimalNumber()); - } - else + if (std::set{"ir", "irOptimized", "legacy", "legacyOptimized"}.count(runType) == 0) BOOST_THROW_EXCEPTION(TestParserError( "Expected \"ir\", \"irOptimized\", \"legacy\", or \"legacyOptimized\"." )); + m_scanner.scanNextToken(); + + bool isCodeDepositCost = false; + if (accept(Token::Identifier)) + { + if (m_scanner.currentLiteral() != "code") + BOOST_THROW_EXCEPTION(TestParserError("Expected \"code\" or \":\".")); + isCodeDepositCost = true; + m_scanner.scanNextToken(); + } + + expect(Token::Colon); + + std::map& gasExpectationMap = (isCodeDepositCost ? + calls.back().expectations.gasUsedForCodeDeposit : + calls.back().expectations.gasUsed + ); + if (gasExpectationMap.count(runType) > 0) + throw TestParserError("Gas usage expectation set multiple times."); + + gasExpectationMap[runType] = u256(parseDecimalNumber()); } else { @@ -189,6 +202,17 @@ std::vector TestFileParser::parseFunctio } } } + + for (FunctionCall& call: calls) + { + // Ensure that each specified gas expectation has both components to simplify working with them. + for (auto const& [runType, gas]: call.expectations.gasUsedForCodeDeposit) + call.expectations.gasUsed.try_emplace({runType, 0}); + + for (auto const& [runType, gas]: call.expectations.gasUsed) + call.expectations.gasUsedForCodeDeposit.try_emplace({runType, 0}); + } + return calls; } diff --git a/test/libsolidity/util/TestFileParserTests.cpp b/test/libsolidity/util/TestFileParserTests.cpp index 46499c1475..7a794f9152 100644 --- a/test/libsolidity/util/TestFileParserTests.cpp +++ b/test/libsolidity/util/TestFileParserTests.cpp @@ -1079,6 +1079,11 @@ BOOST_AUTO_TEST_CASE(gas) {"legacy", 5000}, {"legacyOptimized", 0}, })); + BOOST_TEST(calls[0].expectations.gasUsedForCodeDeposit == (std::map{ + {"ir", 0}, + {"legacy", 0}, + {"legacyOptimized", 0}, + })); } BOOST_AUTO_TEST_CASE(gas_before_call) @@ -1109,6 +1114,103 @@ BOOST_AUTO_TEST_CASE(gas_duplicate_run_type) )"; BOOST_REQUIRE_THROW(parse(source), TestParserError); } + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost) +{ + char const* source = R"( + // f() -> + // gas legacyOptimized code: 1 + // gas ir: 13000 + // gas irOptimized: 6666 + // gas irOptimized code: 666 + // gas legacy code: 0 + // gas legacyOptimized: 2 + )"; + auto const calls = parse(source); + BOOST_REQUIRE_EQUAL(calls.size(), 1); + BOOST_REQUIRE_EQUAL(calls[0].expectations.failure, false); + BOOST_TEST(calls[0].expectations.gasUsed == (std::map{ + {"ir", 13000}, + {"irOptimized", 6666}, + {"legacy", 0}, + {"legacyOptimized", 2}, + })); + BOOST_TEST(calls[0].expectations.gasUsedForCodeDeposit == (std::map{ + {"ir", 0}, + {"irOptimized", 666}, + {"legacy", 0}, + {"legacyOptimized", 1}, + })); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_invalid_suffix) +{ + char const* source = R"( + // f() -> + // gas ir data: 3245 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_tokens_after_suffix) +{ + char const* source = R"( + // f() -> + // gas ir code code: 3245 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_double_code_gas) +{ + char const* source = R"( + // f() -> + // gas ir: 3245 + // gas ir code: 1 + // gas ir code: 1 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_non_code_cost) +{ + // NOTE: This arrangement is unlikely but may still be possible due to refunds. + char const* source = R"( + // f() -> + // gas ir: 10 + // gas ir code: 20 + )"; + auto const calls = parse(source); + BOOST_REQUIRE_EQUAL(calls.size(), 1); + BOOST_REQUIRE_EQUAL(calls[0].expectations.failure, false); + BOOST_TEST(calls[0].expectations.gasUsed == (std::map{ + {"ir", 10}, + })); + BOOST_TEST(calls[0].expectations.gasUsedForCodeDeposit == (std::map{ + {"ir", 20}, + })); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_total_cost) +{ + char const* source = R"( + // f() -> + // gas ir: -10 + // gas ir code: 20 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + +BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_code_cost) +{ + char const* source = R"( + // f() -> + // gas ir: 20 + // gas ir code: -10 + )"; + BOOST_REQUIRE_THROW(parse(source), TestParserError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index 54dd769d61..b22ac3716a 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include + #include #include #include @@ -371,11 +374,19 @@ std::string TestFunctionCall::formatGasExpectations( bool _showDifference ) const { + using ranges::views::keys; + using ranges::views::set_symmetric_difference; + + soltestAssert(set_symmetric_difference(m_codeDepositGasCosts | keys, m_gasCosts | keys).empty()); + soltestAssert(set_symmetric_difference(m_call.expectations.gasUsedForCodeDeposit | keys, m_call.expectations.gasUsed | keys).empty()); + std::stringstream os; for (auto const& [runType, gasUsed]: (_useActualCost ? m_gasCosts : m_call.expectations.gasUsed)) { soltestAssert(runType != ""); + u256 gasUsedForCodeDeposit = (_useActualCost ? m_codeDepositGasCosts : m_call.expectations.gasUsedForCodeDeposit).at(runType); + os << std::endl << _linePrefix << "// gas " << runType << ": " << gasUsed.str(); std::string gasDiff = formatGasDiff( gasOrNullopt(m_gasCosts, runType), @@ -383,6 +394,17 @@ std::string TestFunctionCall::formatGasExpectations( ); if (_showDifference && !gasDiff.empty() && _useActualCost) os << " [" << gasDiff << "]"; + + if (gasUsedForCodeDeposit != 0) + { + os << std::endl << _linePrefix << "// gas " << runType << " code: " << gasUsedForCodeDeposit.str(); + std::string codeGasDiff = formatGasDiff( + gasOrNullopt(m_codeDepositGasCosts, runType), + gasOrNullopt(m_call.expectations.gasUsedForCodeDeposit, runType) + ); + if (_showDifference && !codeGasDiff.empty() && _useActualCost) + os << " [" << codeGasDiff << "]"; + } } return os.str(); } diff --git a/test/libsolidity/util/TestFunctionCall.h b/test/libsolidity/util/TestFunctionCall.h index 8b4ed5019d..cf05b6a216 100644 --- a/test/libsolidity/util/TestFunctionCall.h +++ b/test/libsolidity/util/TestFunctionCall.h @@ -51,7 +51,11 @@ class TestFunctionCall ExpectedValuesActualGas }; - TestFunctionCall(FunctionCall _call): m_call(std::move(_call)), m_gasCosts(m_call.expectations.gasUsed) {} + TestFunctionCall(FunctionCall _call): + m_call(std::move(_call)), + m_gasCosts(m_call.expectations.gasUsed), + m_codeDepositGasCosts(m_call.expectations.gasUsedForCodeDeposit) + {} /// Formats this function call test and applies the format that was detected during parsing. /// _renderMode determines the source of values to be inserted into the updated test expectations. @@ -94,6 +98,7 @@ class TestFunctionCall void setFailure(const bool _failure) { m_failure = _failure; } void setRawBytes(const bytes _rawBytes) { m_rawBytes = _rawBytes; } void setGasCost(std::string const& _runType, u256 const& _gasCost) { m_gasCosts[_runType] = _gasCost; } + void setCodeDepositGasCost(std::string const& _runType, u256 const& _gasCost) { m_codeDepositGasCosts[_runType] = _gasCost; } void setContractABI(Json::Value _contractABI) { m_contractABI = std::move(_contractABI); } void setSideEffects(std::vector _sideEffects) { m_call.actualSideEffects = _sideEffects; } @@ -143,6 +148,8 @@ class TestFunctionCall bytes m_rawBytes = bytes{}; /// Actual gas costs std::map m_gasCosts; + /// Actual code deposit gas costs + std::map m_codeDepositGasCosts; /// Transaction status of the actual call. False in case of a REVERT or any other failure. bool m_failure = true; /// JSON object which holds the contract ABI and that is used to set the output formatting diff --git a/test/libsolidity/util/TestFunctionCallTests.cpp b/test/libsolidity/util/TestFunctionCallTests.cpp index 74a45c3268..b78b7e5f29 100644 --- a/test/libsolidity/util/TestFunctionCallTests.cpp +++ b/test/libsolidity/util/TestFunctionCallTests.cpp @@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(format_unsigned_singleline) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(format_unsigned_singleline_signed_encoding) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(format_unsigned_multiline) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter result{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{result}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{result}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{}, std::string{}}; FunctionCall call{"f(uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(format_multiple_unsigned_singleline) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param, param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param, param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param, param}, std::string{}}; FunctionCall call{"f(uint8, uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(format_signed_singleline) bytes expectedBytes = toBigEndian(u256{-1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "-1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(int8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(format_hex_singleline) bytes expectedBytes = result + bytes(32 - result.size(), 0); ABIType abiType{ABIType::Hex, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "0x31", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bytes32)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(format_hex_string_singleline) bytes expectedBytes = fromHex("4200ef"); ABIType abiType{ABIType::HexString, ABIType::AlignLeft, 3}; Parameter param{expectedBytes, "hex\"4200ef\"", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(string)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(format_bool_true_singleline) bytes expectedBytes = toBigEndian(u256{true}); ABIType abiType{ABIType::Boolean, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "true", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bool)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE(format_bool_false_singleline) bytes expectedBytes = toBigEndian(u256{false}); ABIType abiType{ABIType::Boolean, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "false", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bool)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -198,7 +198,7 @@ BOOST_AUTO_TEST_CASE(format_bool_left_singleline) bytes expectedBytes = toBigEndian(u256{false}); ABIType abiType{ABIType::Boolean, ABIType::AlignLeft, 32}; Parameter param{expectedBytes, "left(false)", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bool)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -213,7 +213,7 @@ BOOST_AUTO_TEST_CASE(format_hex_number_right_singleline) bytes expectedBytes = result + bytes(32 - result.size(), 0); ABIType abiType{ABIType::Hex, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "right(0x42)", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(bool)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(format_empty_byte_range) bytes expectedBytes; ABIType abiType{ABIType::None, ABIType::AlignNone, 0}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{param}, false, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{}, std::string{}}; FunctionCall call{"f()", {0}, arguments, expectations}; call.omitsArrow = false; @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(format_failure_singleline) bytes expectedBytes = toBigEndian(u256{1}); ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32}; Parameter param{expectedBytes, "1", abiType, FormatInfo{}}; - FunctionCallExpectations expectations{std::vector{}, true, std::string{}, {}}; + FunctionCallExpectations expectations{std::vector{}, true, std::string{}, {}, {}}; FunctionCallArgs arguments{std::vector{param}, std::string{}}; FunctionCall call{"f(uint8)", {0}, arguments, expectations}; call.omitsArrow = false; @@ -265,6 +265,11 @@ BOOST_AUTO_TEST_CASE(format_gas) {"legacy", 5000}, {"legacy optimized", 0}, }, + { + {"ir", 0}, + {"legacy", 0}, + {"legacy optimized", 0}, + }, } }; call.omitsArrow = false; @@ -278,6 +283,40 @@ BOOST_AUTO_TEST_CASE(format_gas) ); } +BOOST_AUTO_TEST_CASE(format_gas_with_code_deposit) +{ + FunctionCall call{ + "f()", + FunctionValue{0}, + FunctionCallArgs{}, + FunctionCallExpectations{ + std::vector{}, + false, // failure + "some comment", + { + {"ir", 0}, // Zero costs are shown + {"legacy", 5000}, + {"legacy optimized", 300}, + }, + { + {"ir", 0}, // Zero code deposit costs are omitted + {"legacy", 125}, + {"legacy optimized", 0}, + }, + } + }; + call.omitsArrow = false; + + BOOST_REQUIRE_EQUAL( + TestFunctionCall(call).format(), + "// f() -> #some comment#\n" + "// gas ir: 0\n" + "// gas legacy: 5000\n" + "// gas legacy code: 125\n" + "// gas legacy optimized: 300" + ); +} + BOOST_AUTO_TEST_SUITE_END() } From 96ce95aa3a21f285ee32d30d8b2eed8017a2bdd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 9 Feb 2024 21:30:46 +0100 Subject: [PATCH 44/47] Do not include code deposit gas in the total visible in test expectations --- test/libsolidity/SemanticTest.cpp | 13 +++++---- ...2_in_function_inherited_in_v1_contract.sol | 9 ++++-- ...ode_v2_in_modifier_used_in_v1_contract.sol | 3 +- .../arithmetics/check_var_init.sol | 3 +- .../array/constant_var_as_array_length.sol | 9 ++++-- ...nup_during_multi_element_per_slot_copy.sol | 9 ++++-- .../array/fixed_arrays_as_return_type.sol | 9 ++++-- .../array/fixed_arrays_in_constructors.sol | 9 ++++-- .../array/function_array_cross_calls.sol | 9 ++++-- .../semanticTests/array/reusing_memory.sol | 9 ++++-- .../byte_array_to_storage_cleanup.sol | 9 ++++-- .../constructor/arrays_in_constructors.sol | 9 ++++-- .../bytes_in_constructors_packer.sol | 9 ++++-- .../bytes_in_constructors_unpacker.sol | 9 ++++-- .../constructor_arguments_external.sol | 9 ++++-- .../constructor_function_complex.sol | 3 +- .../constructor_static_array_argument.sol | 9 ++++-- .../constructor/no_callvalue_check.sol | 9 ++++-- .../constructor_inheritance_init_order.sol | 3 +- .../constructor_inheritance_init_order_2.sol | 9 ++++-- .../semanticTests/constructor_with_params.sol | 6 ++-- ...ructor_with_params_diamond_inheritance.sol | 9 ++++-- .../constructor_with_params_inheritance.sol | 9 ++++-- .../events/event_emit_from_other_contract.sol | 9 ++++-- .../externalContracts/FixedFeeRegistrar.sol | 9 ++++-- .../externalContracts/base64.sol | 9 ++++-- .../externalContracts/deposit_contract.sol | 9 ++++-- .../externalContracts/prbmath_signed.sol | 9 ++++-- .../externalContracts/prbmath_unsigned.sol | 9 ++++-- .../externalContracts/ramanujan_pi.sol | 9 ++++-- .../externalContracts/strings.sol | 9 ++++-- .../freeFunctions/new_operator.sol | 3 +- .../creation_function_call_no_args.sol | 3 +- .../creation_function_call_with_args.sol | 9 ++++-- .../creation_function_call_with_salt.sol | 9 ++++-- .../external_call_to_nonexisting.sol | 9 ++++-- ...ernal_call_to_nonexisting_debugstrings.sol | 9 ++++-- .../functionCall/failed_create.sol | 9 ++++-- .../functionCall/gas_and_value_basic.sol | 9 ++++-- .../gas_and_value_brace_syntax.sol | 9 ++++-- .../functionCall/send_zero_ether.sol | 3 +- .../functionTypes/store_function.sol | 6 ++-- .../immutable/multi_creation.sol | 9 ++++-- .../semanticTests/immutable/use_scratch.sol | 9 ++++-- .../address_overload_resolution.sol | 6 ++-- ...d_function_calldata_calldata_interface.sol | 3 +- ...ted_function_calldata_memory_interface.sol | 6 ++-- .../inheritance/member_notation_ctor.sol | 6 ++-- .../inheritance/value_for_constructor.sol | 9 ++++-- .../balance_other_contract.sol | 9 ++++-- .../operator_making_pure_external_call.sol | 12 +++++--- .../operator_making_view_external_call.sol | 12 +++++--- .../salted_create/prediction_example.sol | 3 +- .../salted_create/salted_create.sol | 9 ++++-- .../salted_create_with_value.sol | 9 ++++-- .../semanticTests/smoke/alignment.sol | 3 +- .../semanticTests/smoke/constructor.sol | 9 ++++-- .../semanticTests/state/blockhash_basic.sol | 9 ++++-- .../userDefinedValueType/erc20.sol | 9 ++++-- .../using/using_global_invisible.sol | 3 +- .../semanticTests/various/address_code.sol | 9 ++++-- .../various/code_access_content.sol | 6 ++-- .../various/code_access_create.sol | 3 +- .../various/code_access_runtime.sol | 3 +- .../semanticTests/various/code_length.sol | 3 +- .../semanticTests/various/create_calldata.sol | 9 ++++-- .../semanticTests/various/erc20.sol | 9 ++++-- .../various/external_types_in_calls.sol | 3 +- .../various/many_subassemblies.sol | 9 ++++-- .../various/negative_stack_height.sol | 6 ++-- .../various/selfdestruct_pre_cancun.sol | 9 ++++-- ...ruct_pre_cancun_multiple_beneficiaries.sol | 21 +++++++++----- .../selfdestruct_pre_cancun_redeploy.sol | 18 ++++++++---- .../semanticTests/various/senders_balance.sol | 9 ++++-- .../various/staticcall_for_view_and_pure.sol | 21 +++++++++----- .../semanticTests/various/value_complex.sol | 9 ++++-- .../semanticTests/various/value_insane.sol | 9 ++++-- test/libsolidity/util/SoltestTypes.h | 6 ++-- test/libsolidity/util/TestFileParser.cpp | 6 ++-- test/libsolidity/util/TestFileParserTests.cpp | 29 +++++++------------ test/libsolidity/util/TestFunctionCall.cpp | 12 ++++---- test/libsolidity/util/TestFunctionCall.h | 6 ++-- .../util/TestFunctionCallTests.cpp | 4 +-- 83 files changed, 444 insertions(+), 244 deletions(-) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 676c39eaf9..381ec5bda5 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -570,7 +570,7 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp (m_optimiserSettings == OptimiserSettings::full() ? "Optimized" : ""); soltestAssert( - io_test.call().expectations.gasUsed.count(setting) == + io_test.call().expectations.gasUsedExcludingCode.count(setting) == io_test.call().expectations.gasUsedForCodeDeposit.count(setting) ); @@ -584,19 +584,22 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp !m_enforceGasCost || m_gasUsed < m_enforceGasCostMinValue || m_gasUsed >= InitialGas || - (setting == "ir" && io_test.call().expectations.gasUsed.count(setting) == 0) || + (setting == "ir" && io_test.call().expectations.gasUsedExcludingCode.count(setting) == 0) || io_test.call().kind == FunctionCall::Kind::Builtin ) return true; solAssert(!m_runWithABIEncoderV1Only, ""); - io_test.setGasCost(setting, m_gasUsed); + // NOTE: Cost excluding code is unlikely to be negative but it may still be possible due to refunds. + // We'll deal with it when we actually have a test case like that. + solUnimplementedAssert(m_gasUsed >= m_gasUsedForCodeDeposit); + io_test.setGasCostExcludingCode(setting, m_gasUsed - m_gasUsedForCodeDeposit); io_test.setCodeDepositGasCost(setting, m_gasUsedForCodeDeposit); return - io_test.call().expectations.gasUsed.count(setting) > 0 && - m_gasUsed == io_test.call().expectations.gasUsed.at(setting) && + io_test.call().expectations.gasUsedExcludingCode.count(setting) > 0 && + m_gasUsed - m_gasUsedForCodeDeposit == io_test.call().expectations.gasUsedExcludingCode.at(setting) && m_gasUsedForCodeDeposit == io_test.call().expectations.gasUsedForCodeDeposit.at(setting); } diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol index 55f7991def..c41905e2a4 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol @@ -30,6 +30,9 @@ contract C is B { } // ---- // test() -> 77 -// gas irOptimized: 110348 -// gas legacy: 151866 -// gas legacyOptimized: 110373 +// gas irOptimized: 55148 +// gas irOptimized code: 55200 +// gas legacy: 57266 +// gas legacy code: 94600 +// gas legacyOptimized: 55173 +// gas legacyOptimized code: 55200 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol index 7de2630120..7a2395549b 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol @@ -39,4 +39,5 @@ contract C is B { // ---- // test() -> 5, 10 // gas irOptimized: 87337 -// gas legacy: 102651 +// gas legacy: 66251 +// gas legacy code: 36400 diff --git a/test/libsolidity/semanticTests/arithmetics/check_var_init.sol b/test/libsolidity/semanticTests/arithmetics/check_var_init.sol index fc5418cb0e..9061cd284d 100644 --- a/test/libsolidity/semanticTests/arithmetics/check_var_init.sol +++ b/test/libsolidity/semanticTests/arithmetics/check_var_init.sol @@ -16,4 +16,5 @@ contract D { // ---- // f() -> FAILURE, hex"4e487b71", 0x11 // g(), 100 wei -> 1 -// gas legacy: 100380 +// gas legacy: 76780 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol index 45861babaa..19acb7cba1 100644 --- a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol +++ b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol @@ -8,9 +8,12 @@ contract C { } // ---- // constructor(): 1, 2, 3 -> -// gas irOptimized: 139616 -// gas legacy: 180517 -// gas legacyOptimized: 150462 +// gas irOptimized: 124816 +// gas irOptimized code: 14800 +// gas legacy: 134317 +// gas legacy code: 46200 +// gas legacyOptimized: 127062 +// gas legacyOptimized code: 23400 // a(uint256): 0 -> 1 // a(uint256): 1 -> 2 // a(uint256): 2 -> 3 diff --git a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol index 8be8328926..36b94d7c39 100644 --- a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol +++ b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol @@ -16,7 +16,10 @@ contract C { } // ---- // constructor() -// gas irOptimized: 226321 -// gas legacy: 215753 -// gas legacyOptimized: 181756 +// gas irOptimized: 89121 +// gas irOptimized code: 137200 +// gas legacy: 89553 +// gas legacy code: 126200 +// gas legacyOptimized: 83556 +// gas legacyOptimized code: 98200 // f() -> 0 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol index dd90985735..0fb513543b 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol @@ -18,6 +18,9 @@ contract B { } // ---- // f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004 -// gas irOptimized: 114404 -// gas legacy: 230001 -// gas legacyOptimized: 130637 +// gas irOptimized: 59204 +// gas irOptimized code: 55200 +// gas legacy: 68001 +// gas legacy code: 162000 +// gas legacyOptimized: 60037 +// gas legacyOptimized code: 70600 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol index c7b2dc77a3..0eb0f1e90e 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol @@ -9,8 +9,11 @@ contract Creator { } // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 126327 -// gas legacy: 174186 -// gas legacyOptimized: 128709 +// gas irOptimized: 103927 +// gas irOptimized code: 22400 +// gas legacy: 115186 +// gas legacy code: 59000 +// gas legacyOptimized: 104909 +// gas legacyOptimized code: 23800 // r() -> 4 // ch() -> 3 diff --git a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol index 773e904cc0..e35e24bbf1 100644 --- a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol +++ b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol @@ -42,6 +42,9 @@ contract C { } // ---- // test() -> 5, 6, 7 -// gas irOptimized: 255728 -// gas legacy: 440376 -// gas legacyOptimized: 278651 +// gas irOptimized: 86128 +// gas irOptimized code: 169600 +// gas legacy: 97576 +// gas legacy code: 342800 +// gas legacyOptimized: 87851 +// gas legacyOptimized code: 190800 diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index 8f6afe30ba..a7608f6e0c 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -24,6 +24,9 @@ contract Main { } // ---- // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 -// gas irOptimized: 111924 -// gas legacy: 125154 -// gas legacyOptimized: 113012 +// gas irOptimized: 99524 +// gas irOptimized code: 12400 +// gas legacy: 101554 +// gas legacy code: 23600 +// gas legacyOptimized: 99612 +// gas legacyOptimized code: 13400 diff --git a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol index 877e2a1bce..14130926e7 100644 --- a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol +++ b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol @@ -28,9 +28,12 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 443402 -// gas legacy: 711295 -// gas legacyOptimized: 482378 +// gas irOptimized: 82402 +// gas irOptimized code: 361000 +// gas legacy: 101895 +// gas legacy code: 609400 +// gas legacyOptimized: 85378 +// gas legacyOptimized code: 397000 // h() -> 0x20, 0x40, 0x00, 0 // ~ emit ev(uint256[],uint256): 0x40, 0x21, 0x02, 0x00, 0x00 // g() -> 0x20, 0x40, 0, 0x00 diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 19d79b6c4f..3e60ba451c 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -24,6 +24,9 @@ contract Creator { } // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 -// gas irOptimized: 424526 -// gas legacy: 581426 -// gas legacyOptimized: 444599 +// gas irOptimized: 328126 +// gas irOptimized code: 96400 +// gas legacy: 336626 +// gas legacy code: 244800 +// gas legacyOptimized: 329599 +// gas legacyOptimized code: 115000 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index cfa74f016f..7885d3ceec 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -24,6 +24,9 @@ contract Creator { } // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 275102 -// gas legacy: 418433 -// gas legacyOptimized: 291960 +// gas irOptimized: 169902 +// gas irOptimized code: 105200 +// gas legacy: 173433 +// gas legacy code: 245000 +// gas legacyOptimized: 170360 +// gas legacyOptimized code: 121600 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 39da45e8a5..1d6b01127c 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -8,8 +8,11 @@ contract Test { } // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> -// gas irOptimized: 269225 -// gas legacy: 310820 -// gas legacyOptimized: 258604 +// gas irOptimized: 182025 +// gas irOptimized code: 87200 +// gas legacy: 196220 +// gas legacy code: 114600 +// gas legacyOptimized: 182604 +// gas legacyOptimized code: 76000 // 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 714ae3e554..8fa725dad5 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol @@ -17,8 +17,11 @@ contract Main { } // ---- // constructor(): "abc", true -// gas irOptimized: 104374 -// gas legacy: 143300 -// gas legacyOptimized: 102933 +// gas irOptimized: 80174 +// gas irOptimized code: 24200 +// gas legacy: 85100 +// gas legacy code: 58200 +// gas legacyOptimized: 80133 +// gas legacyOptimized code: 22800 // getFlag() -> true // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol index 4117b84b64..33650aff6f 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol @@ -17,4 +17,5 @@ contract C { } // ---- // f() -> 16 -// gas legacy: 102082 +// gas legacy: 78482 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index a61192742d..e6ce445ada 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -9,9 +9,12 @@ contract C { } // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 170975 -// gas legacy: 218378 -// gas legacyOptimized: 176211 +// gas irOptimized: 147975 +// gas irOptimized code: 23000 +// gas legacy: 157978 +// gas legacy code: 60400 +// gas legacyOptimized: 150011 +// gas legacyOptimized code: 26200 // a() -> 1 // b(uint256): 0 -> 2 // b(uint256): 1 -> 3 diff --git a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol index eec01005eb..b1dc80a408 100644 --- a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol +++ b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol @@ -17,6 +17,9 @@ contract C { } // ---- // f(), 2000 ether -> true -// gas irOptimized: 119441 -// gas legacy: 122621 -// gas legacyOptimized: 122490 +// gas irOptimized: 117641 +// gas irOptimized code: 1800 +// gas legacy: 117821 +// gas legacy code: 4800 +// gas legacyOptimized: 117690 +// gas legacyOptimized code: 4800 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol index ece0cc31a6..ef53142d45 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol @@ -14,5 +14,6 @@ contract B is A { // compileViaYul: true // ---- // constructor() -> -// gas irOptimized: 119636 +// gas irOptimized: 99436 +// gas irOptimized code: 20200 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol index 654c9af56d..e19ad39cfa 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol @@ -9,7 +9,10 @@ contract B is A { } // ---- // constructor() -> -// gas irOptimized: 119636 -// gas legacy: 133574 -// gas legacyOptimized: 115337 +// gas irOptimized: 99436 +// gas irOptimized code: 20200 +// gas legacy: 100974 +// gas legacy code: 32600 +// gas legacyOptimized: 99137 +// gas legacyOptimized code: 16200 // y() -> 42 diff --git a/test/libsolidity/semanticTests/constructor_with_params.sol b/test/libsolidity/semanticTests/constructor_with_params.sol index e427f6d9ab..1c5a170202 100644 --- a/test/libsolidity/semanticTests/constructor_with_params.sol +++ b/test/libsolidity/semanticTests/constructor_with_params.sol @@ -9,7 +9,9 @@ contract C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 101370 -// gas legacy: 115614 +// gas irOptimized: 81170 +// gas irOptimized code: 20200 +// gas legacy: 83614 +// gas legacy code: 32000 // i() -> 2 // k() -> 0 diff --git a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol index 6507081447..29f401a773 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol @@ -21,9 +21,12 @@ contract D is B, C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 151950 -// gas legacy: 168623 -// gas legacyOptimized: 144521 +// gas irOptimized: 124350 +// gas irOptimized code: 27600 +// gas legacy: 128223 +// gas legacy code: 40400 +// gas legacyOptimized: 123921 +// gas legacyOptimized code: 20600 // i() -> 2 // j() -> 2 // k() -> 1 diff --git a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol index 8cc7c69f68..b0373b74f1 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol @@ -12,8 +12,11 @@ contract D is C { } // ---- // constructor(): 2, 0 -> -// gas irOptimized: 121781 -// gas legacy: 137193 -// gas legacyOptimized: 118504 +// gas irOptimized: 101581 +// gas irOptimized code: 20200 +// gas legacy: 105193 +// gas legacy code: 32000 +// gas legacyOptimized: 101504 +// gas legacyOptimized code: 17000 // i() -> 2 // k() -> 1 diff --git a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol index 0c56cbb671..6a01d00192 100644 --- a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol +++ b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol @@ -15,8 +15,11 @@ contract C { } // ---- // constructor() -> -// gas irOptimized: 165370 -// gas legacy: 244776 -// gas legacyOptimized: 171587 +// gas irOptimized: 113970 +// gas irOptimized code: 51400 +// gas legacy: 119776 +// gas legacy code: 125000 +// gas legacyOptimized: 114187 +// gas legacyOptimized code: 57400 // deposit(bytes32), 18 wei: 0x1234 -> // ~ emit Deposit(address,bytes32,uint256) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: #0xc06afe3a8444fc0004668591e8306bfb9968e79e, #0x1234, 0x00 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index 011fecbd34..d308d4597e 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -74,9 +74,12 @@ contract FixedFeeRegistrar is Registrar { } // ---- // constructor() -// gas irOptimized: 384606 -// gas legacy: 913417 -// gas legacyOptimized: 476924 +// gas irOptimized: 78006 +// gas irOptimized code: 306600 +// gas legacy: 115817 +// gas legacy code: 797600 +// gas legacyOptimized: 84924 +// gas legacyOptimized code: 392000 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 // gas irOptimized: 45967 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index ee2745d1ac..b712092ed0 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -33,9 +33,12 @@ contract test { // EVMVersion: >=constantinople // ---- // constructor() -// gas irOptimized: 405828 -// gas legacy: 735050 -// gas legacyOptimized: 522718 +// gas irOptimized: 79428 +// gas irOptimized code: 326400 +// gas legacy: 102450 +// gas legacy code: 632600 +// gas legacyOptimized: 88318 +// gas legacyOptimized code: 434400 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index caa7fc39c8..0ef87edd4f 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -176,9 +176,12 @@ contract DepositContract is IDepositContract, ERC165 { } // ---- // constructor() -// gas irOptimized: 1386886 -// gas legacy: 2368733 -// gas legacyOptimized: 1740004 +// gas irOptimized: 815686 +// gas irOptimized code: 571200 +// gas legacy: 925933 +// gas legacy code: 1442800 +// gas legacyOptimized: 854404 +// gas legacyOptimized code: 885600 // 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 ba7a208fd7..ddd6397183 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -48,9 +48,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 1841736 -// gas legacy: 2414087 -// gas legacyOptimized: 1847612 +// gas irOptimized: 177336 +// gas irOptimized code: 1664400 +// gas legacy: 209687 +// gas legacy code: 2204400 +// gas legacyOptimized: 178012 +// gas legacyOptimized code: 1669600 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22137 // gas legacy: 22767 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 90b283db46..deacfd0564 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -48,9 +48,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 1716323 -// gas legacy: 2193546 -// gas legacyOptimized: 1725057 +// gas irOptimized: 168523 +// gas irOptimized code: 1547800 +// gas legacy: 195146 +// gas legacy code: 1998400 +// gas legacyOptimized: 168857 +// gas legacyOptimized code: 1556200 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22004 // gas legacy: 22497 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 4442b6d479..cdaec8797e 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -33,9 +33,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 407503 -// gas legacy: 615086 -// gas legacyOptimized: 451867 +// gas irOptimized: 79503 +// gas irOptimized code: 328000 +// gas legacy: 92086 +// gas legacy code: 523000 +// gas legacyOptimized: 82667 +// gas legacyOptimized code: 369200 // prb_pi() -> 3141592656369545286 // gas irOptimized: 57478 // gas legacy: 100947 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 3f88fc39c6..a4b0f9fd35 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -49,9 +49,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 630220 -// gas legacy: 1061953 -// gas legacyOptimized: 718933 +// gas irOptimized: 96420 +// gas irOptimized code: 533800 +// gas legacy: 126553 +// gas legacy code: 935400 +// gas legacyOptimized: 102933 +// gas legacyOptimized code: 616000 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22660 // gas legacy: 23190 diff --git a/test/libsolidity/semanticTests/freeFunctions/new_operator.sol b/test/libsolidity/semanticTests/freeFunctions/new_operator.sol index dd44a1b595..d621629c3b 100644 --- a/test/libsolidity/semanticTests/freeFunctions/new_operator.sol +++ b/test/libsolidity/semanticTests/freeFunctions/new_operator.sol @@ -13,4 +13,5 @@ contract D { } // ---- // f() -> 2 -// gas legacy: 100211 +// gas legacy: 76611 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_no_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_no_args.sol index b6a33fb7e8..6044065958 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_no_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_no_args.sol @@ -11,4 +11,5 @@ contract D { } // ---- // f() -> 2 -// gas legacy: 100185 +// gas legacy: 76585 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol index 34aac74efa..1133dc2be3 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -15,7 +15,10 @@ contract D { } // ---- // constructor(): 2 -> -// gas irOptimized: 192663 -// gas legacy: 241170 -// gas legacyOptimized: 192897 +// gas irOptimized: 138863 +// gas irOptimized code: 53800 +// gas legacy: 145570 +// gas legacy code: 95600 +// gas legacyOptimized: 138297 +// gas legacyOptimized code: 54600 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol index cb26a6e26a..ba90a8ecd5 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -17,7 +17,10 @@ contract D { // EVMVersion: >=constantinople // ---- // constructor(): 2 -> -// gas irOptimized: 192826 -// gas legacy: 241536 -// gas legacyOptimized: 193129 +// gas irOptimized: 139026 +// gas irOptimized code: 53800 +// gas legacy: 145936 +// gas legacy code: 95600 +// gas legacyOptimized: 138529 +// gas legacyOptimized code: 54600 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index a1c74cf898..9d521f7777 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -22,9 +22,12 @@ contract C { } // ---- // constructor(), 1 ether -> -// gas irOptimized: 262355 -// gas legacy: 441442 -// gas legacyOptimized: 292862 +// gas irOptimized: 89555 +// gas irOptimized code: 172800 +// gas legacy: 103042 +// gas legacy code: 338400 +// gas legacyOptimized: 91862 +// gas legacyOptimized code: 201000 // 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 96f097ce7f..9baacd8127 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -25,9 +25,12 @@ contract C { // revertStrings: debug // ---- // constructor(), 1 ether -> -// gas irOptimized: 390464 -// gas legacy: 809985 -// gas legacyOptimized: 498331 +// gas irOptimized: 99264 +// gas irOptimized code: 291200 +// gas legacy: 123585 +// gas legacy code: 686400 +// gas legacyOptimized: 107331 +// gas legacyOptimized code: 391000 // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 1 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 2 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/functionCall/failed_create.sol b/test/libsolidity/semanticTests/functionCall/failed_create.sol index 091e5a77a6..b6c077753a 100644 --- a/test/libsolidity/semanticTests/functionCall/failed_create.sol +++ b/test/libsolidity/semanticTests/functionCall/failed_create.sol @@ -17,9 +17,12 @@ contract C { // EVMVersion: >=byzantium // ---- // constructor(), 20 wei -// gas irOptimized: 166148 -// gas legacy: 285547 -// gas legacyOptimized: 168515 +// gas irOptimized: 61548 +// gas irOptimized code: 104600 +// gas legacy: 70147 +// gas legacy code: 215400 +// gas legacyOptimized: 61715 +// gas legacyOptimized code: 106800 // f(uint256): 20 -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a // x() -> 1 // f(uint256): 20 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index 8396cb12db..806c8eb41b 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -38,9 +38,12 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 252626 -// gas legacy: 391568 -// gas legacyOptimized: 268069 +// gas irOptimized: 120226 +// gas irOptimized code: 132400 +// gas legacy: 130568 +// gas legacy code: 261000 +// gas legacyOptimized: 121069 +// gas legacyOptimized code: 147000 // sendAmount(uint256): 5 -> 5 // outOfGas() -> FAILURE # call to helper should not succeed but amount should be transferred anyway # // checkState() -> false, 15 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol index 9d9c3f603f..c186fc40b2 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -37,9 +37,12 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 252626 -// gas legacy: 391568 -// gas legacyOptimized: 268069 +// gas irOptimized: 120226 +// gas irOptimized code: 132400 +// gas legacy: 130568 +// gas legacy code: 261000 +// gas legacyOptimized: 121069 +// gas legacyOptimized code: 147000 // sendAmount(uint256): 5 -> 5 // outOfGas() -> FAILURE # call to helper should not succeed but amount should be transferred anyway # // checkState() -> false, 15 diff --git a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol index a737de5cd4..94a7213232 100644 --- a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol +++ b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol @@ -16,6 +16,7 @@ contract Main { // ---- // constructor(), 20 wei -> // gas irOptimized: 100264 -// gas legacy: 110555 +// gas legacy: 57555 +// gas legacy code: 53000 // gas legacyOptimized: 100361 // s() -> true diff --git a/test/libsolidity/semanticTests/functionTypes/store_function.sol b/test/libsolidity/semanticTests/functionTypes/store_function.sol index 132a6c9565..5397d0b701 100644 --- a/test/libsolidity/semanticTests/functionTypes/store_function.sol +++ b/test/libsolidity/semanticTests/functionTypes/store_function.sol @@ -26,5 +26,7 @@ contract C { // ---- // t() -> 9 // gas irOptimized: 99064 -// gas legacy: 149095 -// gas legacyOptimized: 106188 +// gas legacy: 79495 +// gas legacy code: 69600 +// gas legacyOptimized: 77588 +// gas legacyOptimized code: 28600 diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index 145c32add6..c8806c50d0 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -27,8 +27,11 @@ contract C { } // ---- // f() -> 3, 7, 5 -// gas irOptimized: 124021 -// gas legacy: 148528 -// gas legacyOptimized: 123971 +// gas irOptimized: 86821 +// gas irOptimized code: 37200 +// gas legacy: 87728 +// gas legacy code: 60800 +// gas legacyOptimized: 86771 +// gas legacyOptimized code: 37200 // x() -> 7 // y() -> 5 diff --git a/test/libsolidity/semanticTests/immutable/use_scratch.sol b/test/libsolidity/semanticTests/immutable/use_scratch.sol index a7c8ea6a50..dc07086c29 100644 --- a/test/libsolidity/semanticTests/immutable/use_scratch.sol +++ b/test/libsolidity/semanticTests/immutable/use_scratch.sol @@ -15,8 +15,11 @@ contract C { } // ---- // constructor(): 3 -> -// gas irOptimized: 123526 -// gas legacy: 197645 -// gas legacyOptimized: 137658 +// gas irOptimized: 81126 +// gas irOptimized code: 42400 +// gas legacy: 88245 +// gas legacy code: 109400 +// gas legacyOptimized: 81858 +// gas legacyOptimized code: 55800 // f() -> 84, 23 // m(uint256): 3 -> 7 diff --git a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol index c65d1abec5..0865ed2876 100644 --- a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol +++ b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol @@ -21,7 +21,9 @@ contract D { // ---- // f() -> 1 // gas irOptimized: 77051 -// gas legacy: 112280 +// gas legacy: 54480 +// gas legacy code: 57800 // g() -> 5 // gas irOptimized: 77106 -// gas legacy: 112816 +// gas legacy: 55016 +// gas legacy code: 57800 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol index 3114c80f19..0567c2ab14 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol @@ -23,4 +23,5 @@ contract B { // ---- // g() -> 42 // gas irOptimized: 80813 -// gas legacy: 122471 +// gas legacy: 55871 +// gas legacy code: 66600 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol index 74bf42ec7e..d5ff54b68a 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol @@ -23,5 +23,7 @@ contract B { // ---- // g() -> 42 // gas irOptimized: 100282 -// gas legacy: 180440 -// gas legacyOptimized: 112596 +// gas legacy: 56840 +// gas legacy code: 123600 +// gas legacyOptimized: 54996 +// gas legacyOptimized code: 57600 diff --git a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol index 263588abab..e704a297bb 100644 --- a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol +++ b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol @@ -19,6 +19,8 @@ contract A { } // ---- // g(int256): -1 -> -1 -// gas legacy: 102078 +// gas legacy: 77878 +// gas legacy code: 24200 // g(int256): 10 -> 10 -// gas legacy: 101706 +// gas legacy: 77506 +// gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index 9627ad025d..fdd0bafaad 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -39,9 +39,12 @@ contract Main { } // ---- // constructor(), 22 wei -> -// gas irOptimized: 261864 -// gas legacy: 392786 -// gas legacyOptimized: 261593 +// gas irOptimized: 143864 +// gas irOptimized code: 118000 +// gas legacy: 156586 +// gas legacy code: 236200 +// gas legacyOptimized: 143593 +// gas legacyOptimized code: 118000 // getFlag() -> true // getName() -> "abc" // getBalances() -> 12, 10 diff --git a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol index 1a5c9b19b4..0ad55b5ddf 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -16,9 +16,12 @@ contract ClientReceipt { } // ---- // constructor(), 2000 wei -> -// gas irOptimized: 169907 -// gas legacy: 230018 -// gas legacyOptimized: 173867 +// gas irOptimized: 114107 +// gas irOptimized code: 55800 +// gas legacy: 118618 +// gas legacy code: 111400 +// gas legacyOptimized: 114067 +// gas legacyOptimized code: 59800 // balance -> 1500 // gas irOptimized: 191881 // gas legacy: 235167 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol index ce6a0f48db..a621b4c12a 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol @@ -53,9 +53,13 @@ contract C { // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 183981 -// gas legacyOptimized: 123563 +// gas legacy: 56981 +// gas legacy code: 127000 +// gas legacyOptimized: 55163 +// gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 183239 -// gas legacyOptimized: 123251 +// gas legacy: 56239 +// gas legacy code: 127000 +// gas legacyOptimized: 54851 +// gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol index f3f8ebdc63..84f6bf08e7 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol @@ -59,9 +59,13 @@ contract C { // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 183981 -// gas legacyOptimized: 123563 +// gas legacy: 56981 +// gas legacy code: 127000 +// gas legacyOptimized: 55163 +// gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 183239 -// gas legacyOptimized: 123251 +// gas legacy: 56239 +// gas legacy code: 127000 +// gas legacyOptimized: 54851 +// gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/salted_create/prediction_example.sol b/test/libsolidity/semanticTests/salted_create/prediction_example.sol index e7171536d6..6fa865440b 100644 --- a/test/libsolidity/semanticTests/salted_create/prediction_example.sol +++ b/test/libsolidity/semanticTests/salted_create/prediction_example.sol @@ -26,4 +26,5 @@ contract C { // compileViaYul: also // ---- // createDSalted(bytes32,uint256): 42, 64 -> -// gas legacy: 102841 +// gas legacy: 79241 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create.sol b/test/libsolidity/semanticTests/salted_create/salted_create.sol index 743ff5fd2a..535a2813c1 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create.sol @@ -21,6 +21,9 @@ contract A { // ---- // different_salt() -> true // same_salt() -> true -// gas irOptimized: 98438895 -// gas legacy: 98439109 -// gas legacyOptimized: 98438967 +// gas irOptimized: 98438295 +// gas irOptimized code: 600 +// gas legacy: 98437509 +// gas legacy code: 1600 +// gas legacyOptimized: 98437367 +// gas legacyOptimized code: 1600 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index 58b3f07603..735731c8ab 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -21,6 +21,9 @@ contract A { // EVMVersion: >=constantinople // ---- // f(), 10 ether -> 3007, 3008, 3009 -// gas irOptimized: 253005 -// gas legacy: 381063 -// gas legacyOptimized: 279658 +// gas irOptimized: 187005 +// gas irOptimized code: 66000 +// gas legacy: 190863 +// gas legacy code: 190200 +// gas legacyOptimized: 187258 +// gas legacyOptimized code: 92400 diff --git a/test/libsolidity/semanticTests/smoke/alignment.sol b/test/libsolidity/semanticTests/smoke/alignment.sol index 3e8016f988..296ae01617 100644 --- a/test/libsolidity/semanticTests/smoke/alignment.sol +++ b/test/libsolidity/semanticTests/smoke/alignment.sol @@ -25,5 +25,6 @@ contract D { // stateDecimal() -> right(42) // stateBytes() -> left(0x4200ef) // internalStateDecimal() -> 0x20 -// gas legacy: 100265 +// gas legacy: 76665 +// gas legacy code: 23600 // update(bool,uint256,bytes32): false, -23, left(0x2300ef) -> false, -23, left(0x2300ef) diff --git a/test/libsolidity/semanticTests/smoke/constructor.sol b/test/libsolidity/semanticTests/smoke/constructor.sol index 55789b2f4b..2783fe4a8c 100644 --- a/test/libsolidity/semanticTests/smoke/constructor.sol +++ b/test/libsolidity/semanticTests/smoke/constructor.sol @@ -12,9 +12,12 @@ contract C { } // ---- // constructor(), 2 wei: 3 -> -// gas irOptimized: 104396 -// gas legacy: 148256 -// gas legacyOptimized: 106699 +// gas irOptimized: 78996 +// gas irOptimized code: 25400 +// gas legacy: 83056 +// gas legacy code: 65200 +// gas legacyOptimized: 78899 +// gas legacyOptimized code: 27800 // state() -> 3 // balance() -> 2 // balance -> 2 diff --git a/test/libsolidity/semanticTests/state/blockhash_basic.sol b/test/libsolidity/semanticTests/state/blockhash_basic.sol index 03d6f9fe76..64b8d55a26 100644 --- a/test/libsolidity/semanticTests/state/blockhash_basic.sol +++ b/test/libsolidity/semanticTests/state/blockhash_basic.sol @@ -12,9 +12,12 @@ contract C { } // ---- // constructor() -// gas irOptimized: 108138 -// gas legacy: 152171 -// gas legacyOptimized: 106738 +// gas irOptimized: 80338 +// gas irOptimized code: 27800 +// gas legacy: 83571 +// gas legacy code: 68600 +// gas legacyOptimized: 80338 +// gas legacyOptimized code: 26400 // genesisHash() -> 0x3737373737373737373737373737373737373737373737373737373737373737 // currentHash() -> 0 // f(uint256): 0 -> 0x3737373737373737373737373737373737373737373737373737373737373737 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index ac8609d713..8976cf3c52 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -113,9 +113,12 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 352682 -// gas legacy: 834752 -// gas legacyOptimized: 412648 +// gas irOptimized: 121082 +// gas irOptimized code: 231600 +// gas legacy: 163352 +// gas legacy code: 671400 +// gas legacyOptimized: 127448 +// gas legacyOptimized code: 285200 // totalSupply() -> 20 // gas irOptimized: 23415 // gas legacy: 23653 diff --git a/test/libsolidity/semanticTests/using/using_global_invisible.sol b/test/libsolidity/semanticTests/using/using_global_invisible.sol index 3e767a185d..818707f6fe 100644 --- a/test/libsolidity/semanticTests/using/using_global_invisible.sol +++ b/test/libsolidity/semanticTests/using/using_global_invisible.sol @@ -40,4 +40,5 @@ contract D { // ---- // library: "A":L // test() -> 3 -// gas legacy: 120881 +// gas legacy: 59681 +// gas legacy code: 61200 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 7e48b00ca8..6a97c0bf7e 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -14,9 +14,12 @@ contract C { } // ---- // constructor() -> -// gas irOptimized: 173273 -// gas legacy: 241796 -// gas legacyOptimized: 153670 +// gas irOptimized: 70873 +// gas irOptimized code: 102400 +// gas legacy: 82796 +// gas legacy code: 159000 +// gas legacyOptimized: 69870 +// gas legacyOptimized code: 83800 // initCode() -> 0x20, 0 // f() -> true // g() -> 0 diff --git a/test/libsolidity/semanticTests/various/code_access_content.sol b/test/libsolidity/semanticTests/various/code_access_content.sol index 92d31d6214..dc4e49b2da 100644 --- a/test/libsolidity/semanticTests/various/code_access_content.sol +++ b/test/libsolidity/semanticTests/various/code_access_content.sol @@ -38,6 +38,8 @@ contract C { } // ---- // testRuntime() -> true -// gas legacy: 100177 +// gas legacy: 76577 +// gas legacy code: 23600 // testCreation() -> true -// gas legacy: 100600 +// gas legacy: 77000 +// gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/various/code_access_create.sol b/test/libsolidity/semanticTests/various/code_access_create.sol index 075682129c..d2b7f92f4e 100644 --- a/test/libsolidity/semanticTests/various/code_access_create.sol +++ b/test/libsolidity/semanticTests/various/code_access_create.sol @@ -23,4 +23,5 @@ contract C { } // ---- // test() -> 7 -// gas legacy: 100849 +// gas legacy: 76649 +// gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/various/code_access_runtime.sol b/test/libsolidity/semanticTests/various/code_access_runtime.sol index 9a9e7a80bf..b62eb0b853 100644 --- a/test/libsolidity/semanticTests/various/code_access_runtime.sol +++ b/test/libsolidity/semanticTests/various/code_access_runtime.sol @@ -23,4 +23,5 @@ contract C { // EVMVersion: >=constantinople // ---- // test() -> 42 -// gas legacy: 100235 +// gas legacy: 76035 +// gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/various/code_length.sol b/test/libsolidity/semanticTests/various/code_length.sol index a8aac5306f..c30ac838fe 100644 --- a/test/libsolidity/semanticTests/various/code_length.sol +++ b/test/libsolidity/semanticTests/various/code_length.sol @@ -59,5 +59,6 @@ contract C { } // ---- // constructor() -// gas legacy: 124136 +// gas legacy: 66936 +// gas legacy code: 57200 // f(): true, true -> true, true diff --git a/test/libsolidity/semanticTests/various/create_calldata.sol b/test/libsolidity/semanticTests/various/create_calldata.sol index c3d038136f..2db42adebb 100644 --- a/test/libsolidity/semanticTests/various/create_calldata.sol +++ b/test/libsolidity/semanticTests/various/create_calldata.sol @@ -8,7 +8,10 @@ contract C { } // ---- // constructor(): 42 -> -// gas irOptimized: 145578 -// gas legacy: 173845 -// gas legacyOptimized: 137877 +// gas irOptimized: 68378 +// gas irOptimized code: 77200 +// gas legacy: 78445 +// gas legacy code: 95400 +// gas legacyOptimized: 68677 +// gas legacyOptimized code: 69200 // s() -> 0x20, 0 diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index 00c12fb18a..f7956c4c50 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -96,9 +96,12 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 353248 -// gas legacy: 807559 -// gas legacyOptimized: 408718 +// gas irOptimized: 121248 +// gas irOptimized code: 232000 +// gas legacy: 159959 +// gas legacy code: 647600 +// gas legacyOptimized: 126918 +// gas legacyOptimized code: 281800 // totalSupply() -> 20 // gas irOptimized: 23415 // gas legacy: 23524 diff --git a/test/libsolidity/semanticTests/various/external_types_in_calls.sol b/test/libsolidity/semanticTests/various/external_types_in_calls.sol index e8742c2346..aff302d26e 100644 --- a/test/libsolidity/semanticTests/various/external_types_in_calls.sol +++ b/test/libsolidity/semanticTests/various/external_types_in_calls.sol @@ -24,5 +24,6 @@ contract C { } // ---- // test() -> 9, 7 -// gas legacy: 127514 +// gas legacy: 80314 +// gas legacy code: 47200 // t2() -> 9 diff --git a/test/libsolidity/semanticTests/various/many_subassemblies.sol b/test/libsolidity/semanticTests/various/many_subassemblies.sol index 26c3a1bbff..67a576da78 100644 --- a/test/libsolidity/semanticTests/various/many_subassemblies.sol +++ b/test/libsolidity/semanticTests/various/many_subassemblies.sol @@ -30,6 +30,9 @@ contract D { } // ---- // run() -> -// gas irOptimized: 381615 -// gas legacy: 392719 -// gas legacyOptimized: 392719 +// gas irOptimized: 375015 +// gas irOptimized code: 6600 +// gas legacy: 375119 +// gas legacy code: 17600 +// gas legacyOptimized: 375119 +// gas legacyOptimized code: 17600 diff --git a/test/libsolidity/semanticTests/various/negative_stack_height.sol b/test/libsolidity/semanticTests/various/negative_stack_height.sol index 7289d2bbd9..44fd0089cf 100644 --- a/test/libsolidity/semanticTests/various/negative_stack_height.sol +++ b/test/libsolidity/semanticTests/various/negative_stack_height.sol @@ -65,5 +65,7 @@ contract C { // compileViaYul: false // ---- // constructor() -> -// gas legacy: 575268 -// gas legacyOptimized: 345022 +// gas legacy: 92268 +// gas legacy code: 483000 +// gas legacyOptimized: 75022 +// gas legacyOptimized code: 270000 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun.sol index 4142eb25cf..a39b6c4235 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun.sol @@ -62,9 +62,12 @@ contract D { // EVMVersion: =shanghai // ---- // constructor(), 1 ether -> -// gas irOptimized: 242428 -// gas legacy: 373563 -// gas legacyOptimized: 234516 +// gas irOptimized: 67028 +// gas irOptimized code: 175400 +// gas legacy: 76163 +// gas legacy code: 297400 +// gas legacyOptimized: 66516 +// gas legacyOptimized code: 168000 // exists() -> false // test_create_and_terminate() -> // exists() -> false diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol index 87e81a2902..a09a7cac68 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol @@ -35,23 +35,30 @@ contract D { // EVMVersion: <=shanghai // ---- // constructor(), 2 ether -> -// gas irOptimized: 223918 -// gas legacy: 374024 -// gas legacyOptimized: 239815 +// gas irOptimized: 107718 +// gas irOptimized code: 116200 +// gas legacy: 120424 +// gas legacy code: 253600 +// gas legacyOptimized: 109015 +// gas legacyOptimized code: 130800 // balance: 0x1111111111111111111111111111111111111111 -> 0 // balance: 0x2222222222222222222222222222222222222222 -> 0 // balance -> 2000000000000000000 // exists() -> false // test_deploy_and_terminate_twice() -> -// gas irOptimized: 135350 -// gas legacy: 165584 -// gas legacyOptimized: 144396 +// gas irOptimized: 121350 +// gas irOptimized code: 14000 +// gas legacy: 122384 +// gas legacy code: 43200 +// gas legacyOptimized: 121596 +// gas legacyOptimized code: 22800 // exists() -> false // balance: 0x1111111111111111111111111111111111111111 -> 1000000000000000000 // balance: 0x2222222222222222222222222222222222222222 -> 0 // balance -> 1000000000000000000 // deploy() -> -// gas legacy: 101691 +// gas legacy: 58491 +// gas legacy code: 43200 // exists() -> true // balance: 0x1111111111111111111111111111111111111111 -> 1000000000000000000 // balance: 0x2222222222222222222222222222222222222222 -> 0 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol index e0885782c2..fc650ebba7 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol @@ -79,15 +79,21 @@ contract D { // EVMVersion: =shanghai // ---- // constructor(), 1 ether -> -// gas irOptimized: 430253 -// gas legacy: 690244 -// gas legacyOptimized: 412799 +// gas irOptimized: 133253 +// gas irOptimized code: 297000 +// gas legacy: 151644 +// gas legacy code: 538600 +// gas legacyOptimized: 131799 +// gas legacyOptimized code: 281000 // exists() -> false // test_deploy_and_terminate() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 117489 -// gas legacy: 118895 -// gas legacyOptimized: 117137 +// gas irOptimized: 96689 +// gas irOptimized code: 20800 +// gas legacy: 98095 +// gas legacy code: 20800 +// gas legacyOptimized: 96337 +// gas legacyOptimized code: 20800 // exists() -> false // deploy_create2() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/various/senders_balance.sol b/test/libsolidity/semanticTests/various/senders_balance.sol index a1c7d4147f..5b4371149f 100644 --- a/test/libsolidity/semanticTests/various/senders_balance.sol +++ b/test/libsolidity/semanticTests/various/senders_balance.sol @@ -16,7 +16,10 @@ contract D { } // ---- // constructor(), 27 wei -> -// gas irOptimized: 167857 -// gas legacy: 218435 -// gas legacyOptimized: 167276 +// gas irOptimized: 114057 +// gas irOptimized code: 53800 +// gas legacy: 117835 +// gas legacy code: 100600 +// gas legacyOptimized: 113676 +// gas legacyOptimized code: 53600 // f() -> 27 diff --git a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol index 1306529d41..77a330f3cd 100644 --- a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol +++ b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol @@ -35,12 +35,19 @@ contract D { // EVMVersion: >=byzantium // ---- // f() -> 0x1 # This should work, next should throw # -// gas legacy: 102095 +// gas legacy: 76495 +// gas legacy code: 25600 // fview() -> FAILURE -// gas irOptimized: 98438588 -// gas legacy: 98438774 -// gas legacyOptimized: 98438580 +// gas irOptimized: 98425388 +// gas irOptimized code: 13200 +// gas legacy: 98413174 +// gas legacy code: 25600 +// gas legacyOptimized: 98425380 +// gas legacyOptimized code: 13200 // fpure() -> FAILURE -// gas irOptimized: 98438589 -// gas legacy: 98438774 -// gas legacyOptimized: 98438580 +// gas irOptimized: 98425389 +// gas irOptimized code: 13200 +// gas legacy: 98413174 +// gas legacy code: 25600 +// gas legacyOptimized: 98425380 +// gas legacyOptimized code: 13200 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol index 2adac6bf4c..427a006dc1 100644 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ b/test/libsolidity/semanticTests/various/value_complex.sol @@ -19,7 +19,10 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 172399 -// gas legacy: 252276 -// gas legacyOptimized: 180336 +// gas irOptimized: 114399 +// gas irOptimized code: 58000 +// gas legacy: 120076 +// gas legacy code: 132200 +// gas legacyOptimized: 114536 +// gas legacyOptimized code: 65800 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/various/value_insane.sol b/test/libsolidity/semanticTests/various/value_insane.sol index 87fa01485d..97fbbab1e6 100644 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ b/test/libsolidity/semanticTests/various/value_insane.sol @@ -18,7 +18,10 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 173263 -// gas legacy: 253800 -// gas legacyOptimized: 180768 +// gas irOptimized: 114463 +// gas irOptimized code: 58800 +// gas legacy: 120200 +// gas legacy code: 133600 +// gas legacyOptimized: 114568 +// gas legacyOptimized code: 66200 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/util/SoltestTypes.h b/test/libsolidity/util/SoltestTypes.h index a2d593fd3c..791cea0116 100644 --- a/test/libsolidity/util/SoltestTypes.h +++ b/test/libsolidity/util/SoltestTypes.h @@ -215,11 +215,11 @@ struct FunctionCallExpectations raw += param.rawBytes; return raw; } - /// Gas used by function call - /// Keys represent all distinct combinations of compilation settings that affect produced + /// Gas used by function call minus the portion spent on code deposits (which is tracked + /// separately, in @a gasUsedForCodeDeposit). /// bytecode (and therefore the cost), except for EVM version. E.g. IR codegen without /// optimization legacy codegen with optimization. - std::map gasUsed; + std::map gasUsedExcludingCode; /// The portion of @a gasUsed spent on code deposits of newly created contracts. /// May exceed @a gasUsed in rare corner cases due to refunds. diff --git a/test/libsolidity/util/TestFileParser.cpp b/test/libsolidity/util/TestFileParser.cpp index e7e20f7c5c..5a32a1591a 100644 --- a/test/libsolidity/util/TestFileParser.cpp +++ b/test/libsolidity/util/TestFileParser.cpp @@ -103,7 +103,7 @@ std::vector TestFileParser::parseFunctio std::map& gasExpectationMap = (isCodeDepositCost ? calls.back().expectations.gasUsedForCodeDeposit : - calls.back().expectations.gasUsed + calls.back().expectations.gasUsedExcludingCode ); if (gasExpectationMap.count(runType) > 0) throw TestParserError("Gas usage expectation set multiple times."); @@ -207,9 +207,9 @@ std::vector TestFileParser::parseFunctio { // Ensure that each specified gas expectation has both components to simplify working with them. for (auto const& [runType, gas]: call.expectations.gasUsedForCodeDeposit) - call.expectations.gasUsed.try_emplace({runType, 0}); + call.expectations.gasUsedExcludingCode.try_emplace({runType, 0}); - for (auto const& [runType, gas]: call.expectations.gasUsed) + for (auto const& [runType, gas]: call.expectations.gasUsedExcludingCode) call.expectations.gasUsedForCodeDeposit.try_emplace({runType, 0}); } diff --git a/test/libsolidity/util/TestFileParserTests.cpp b/test/libsolidity/util/TestFileParserTests.cpp index 7a794f9152..4bb4aed3ac 100644 --- a/test/libsolidity/util/TestFileParserTests.cpp +++ b/test/libsolidity/util/TestFileParserTests.cpp @@ -1074,7 +1074,7 @@ BOOST_AUTO_TEST_CASE(gas) auto const calls = parse(source); BOOST_REQUIRE_EQUAL(calls.size(), 1); BOOST_REQUIRE_EQUAL(calls[0].expectations.failure, false); - BOOST_TEST(calls[0].expectations.gasUsed == (std::map{ + BOOST_TEST(calls[0].expectations.gasUsedExcludingCode == (std::map{ {"ir", 3245}, {"legacy", 5000}, {"legacyOptimized", 0}, @@ -1121,19 +1121,19 @@ BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost) // f() -> // gas legacyOptimized code: 1 // gas ir: 13000 - // gas irOptimized: 6666 + // gas irOptimized: 6000 // gas irOptimized code: 666 // gas legacy code: 0 - // gas legacyOptimized: 2 + // gas legacyOptimized: 1 )"; auto const calls = parse(source); BOOST_REQUIRE_EQUAL(calls.size(), 1); BOOST_REQUIRE_EQUAL(calls[0].expectations.failure, false); - BOOST_TEST(calls[0].expectations.gasUsed == (std::map{ + BOOST_TEST(calls[0].expectations.gasUsedExcludingCode == (std::map{ {"ir", 13000}, - {"irOptimized", 6666}, + {"irOptimized", 6000}, {"legacy", 0}, - {"legacyOptimized", 2}, + {"legacyOptimized", 1}, })); BOOST_TEST(calls[0].expectations.gasUsedForCodeDeposit == (std::map{ {"ir", 0}, @@ -1175,27 +1175,20 @@ BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_double_code_gas) BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_non_code_cost) { // NOTE: This arrangement is unlikely but may still be possible due to refunds. + // We'll deal with it when we actually have a test case like that. char const* source = R"( // f() -> - // gas ir: 10 + // gas ir: -10 // gas ir code: 20 )"; - auto const calls = parse(source); - BOOST_REQUIRE_EQUAL(calls.size(), 1); - BOOST_REQUIRE_EQUAL(calls[0].expectations.failure, false); - BOOST_TEST(calls[0].expectations.gasUsed == (std::map{ - {"ir", 10}, - })); - BOOST_TEST(calls[0].expectations.gasUsedForCodeDeposit == (std::map{ - {"ir", 20}, - })); + BOOST_REQUIRE_THROW(parse(source), TestParserError); } BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_total_cost) { char const* source = R"( // f() -> - // gas ir: -10 + // gas ir: -30 // gas ir code: 20 )"; BOOST_REQUIRE_THROW(parse(source), TestParserError); @@ -1205,7 +1198,7 @@ BOOST_AUTO_TEST_CASE(gas_with_code_deposit_cost_negative_code_cost) { char const* source = R"( // f() -> - // gas ir: 20 + // gas ir: 10 // gas ir code: -10 )"; BOOST_REQUIRE_THROW(parse(source), TestParserError); diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index b22ac3716a..dd74d4035c 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -377,20 +377,20 @@ std::string TestFunctionCall::formatGasExpectations( using ranges::views::keys; using ranges::views::set_symmetric_difference; - soltestAssert(set_symmetric_difference(m_codeDepositGasCosts | keys, m_gasCosts | keys).empty()); - soltestAssert(set_symmetric_difference(m_call.expectations.gasUsedForCodeDeposit | keys, m_call.expectations.gasUsed | keys).empty()); + soltestAssert(set_symmetric_difference(m_codeDepositGasCosts | keys, m_gasCostsExcludingCode | keys).empty()); + soltestAssert(set_symmetric_difference(m_call.expectations.gasUsedForCodeDeposit | keys, m_call.expectations.gasUsedExcludingCode | keys).empty()); std::stringstream os; - for (auto const& [runType, gasUsed]: (_useActualCost ? m_gasCosts : m_call.expectations.gasUsed)) + for (auto const& [runType, gasUsedExcludingCode]: (_useActualCost ? m_gasCostsExcludingCode : m_call.expectations.gasUsedExcludingCode)) { soltestAssert(runType != ""); u256 gasUsedForCodeDeposit = (_useActualCost ? m_codeDepositGasCosts : m_call.expectations.gasUsedForCodeDeposit).at(runType); - os << std::endl << _linePrefix << "// gas " << runType << ": " << gasUsed.str(); + os << std::endl << _linePrefix << "// gas " << runType << ": " << gasUsedExcludingCode.str(); std::string gasDiff = formatGasDiff( - gasOrNullopt(m_gasCosts, runType), - gasOrNullopt(m_call.expectations.gasUsed, runType) + gasOrNullopt(m_gasCostsExcludingCode, runType), + gasOrNullopt(m_call.expectations.gasUsedExcludingCode, runType) ); if (_showDifference && !gasDiff.empty() && _useActualCost) os << " [" << gasDiff << "]"; diff --git a/test/libsolidity/util/TestFunctionCall.h b/test/libsolidity/util/TestFunctionCall.h index cf05b6a216..724cb8286c 100644 --- a/test/libsolidity/util/TestFunctionCall.h +++ b/test/libsolidity/util/TestFunctionCall.h @@ -53,7 +53,7 @@ class TestFunctionCall TestFunctionCall(FunctionCall _call): m_call(std::move(_call)), - m_gasCosts(m_call.expectations.gasUsed), + m_gasCostsExcludingCode(m_call.expectations.gasUsedExcludingCode), m_codeDepositGasCosts(m_call.expectations.gasUsedForCodeDeposit) {} @@ -97,7 +97,7 @@ class TestFunctionCall void calledNonExistingFunction() { m_calledNonExistingFunction = true; } void setFailure(const bool _failure) { m_failure = _failure; } void setRawBytes(const bytes _rawBytes) { m_rawBytes = _rawBytes; } - void setGasCost(std::string const& _runType, u256 const& _gasCost) { m_gasCosts[_runType] = _gasCost; } + void setGasCostExcludingCode(std::string const& _runType, u256 const& _gasCost) { m_gasCostsExcludingCode[_runType] = _gasCost; } void setCodeDepositGasCost(std::string const& _runType, u256 const& _gasCost) { m_codeDepositGasCosts[_runType] = _gasCost; } void setContractABI(Json::Value _contractABI) { m_contractABI = std::move(_contractABI); } void setSideEffects(std::vector _sideEffects) { m_call.actualSideEffects = _sideEffects; } @@ -147,7 +147,7 @@ class TestFunctionCall /// Result of the actual call been made. bytes m_rawBytes = bytes{}; /// Actual gas costs - std::map m_gasCosts; + std::map m_gasCostsExcludingCode; /// Actual code deposit gas costs std::map m_codeDepositGasCosts; /// Transaction status of the actual call. False in case of a REVERT or any other failure. diff --git a/test/libsolidity/util/TestFunctionCallTests.cpp b/test/libsolidity/util/TestFunctionCallTests.cpp index b78b7e5f29..5741ccd0de 100644 --- a/test/libsolidity/util/TestFunctionCallTests.cpp +++ b/test/libsolidity/util/TestFunctionCallTests.cpp @@ -295,7 +295,7 @@ BOOST_AUTO_TEST_CASE(format_gas_with_code_deposit) "some comment", { {"ir", 0}, // Zero costs are shown - {"legacy", 5000}, + {"legacy", 4875}, {"legacy optimized", 300}, }, { @@ -311,7 +311,7 @@ BOOST_AUTO_TEST_CASE(format_gas_with_code_deposit) TestFunctionCall(call).format(), "// f() -> #some comment#\n" "// gas ir: 0\n" - "// gas legacy: 5000\n" + "// gas legacy: 4875\n" "// gas legacy code: 125\n" "// gas legacy optimized: 300" ); From 381b149b8dd3fe87ae9d1af49514788adaa3e997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 11 Feb 2024 16:03:50 +0100 Subject: [PATCH 45/47] gas_diff_stats.py: Include code deposit costs in total cost --- scripts/gas_diff_stats.py | 5 ++++- test/scripts/test_gas_diff_stats.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 7403b39172..13d8a59e8d 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -23,7 +23,7 @@ import sys from pathlib import Path from enum import Enum -from parsec import generate, ParseError, regex, string +from parsec import generate, ParseError, regex, string, optional from tabulate import tabulate class Kind(Enum): @@ -49,6 +49,7 @@ class Diff(Enum): gas_ir_optimized = string("gas irOptimized").result(Kind.IrOptimized) gas_legacy_optimized = string("gas legacyOptimized").result(Kind.LegacyOptimized) gas_legacy = string("gas legacy").result(Kind.Legacy) +code_suffix = string("code") def number() -> int: """Parse number.""" @@ -67,6 +68,8 @@ def diff_string() -> (Kind, Diff, int): yield comment yield space codegen_kind = yield gas_ir_optimized ^ gas_ir ^ gas_legacy_optimized ^ gas_legacy + yield optional(space) + yield optional(code_suffix) yield colon yield space val = yield number() diff --git a/test/scripts/test_gas_diff_stats.py b/test/scripts/test_gas_diff_stats.py index 4980293aea..e67bd0be89 100644 --- a/test/scripts/test_gas_diff_stats.py +++ b/test/scripts/test_gas_diff_stats.py @@ -85,3 +85,25 @@ def test_collect_statistics_should_ignore_unchanged_costs(self): 0, # +legacyOptimized 3, # +legacy )) + + def test_collect_statistics_should_include_code_deposit_in_total_cost(self): + diff_output = dedent(""" + -// gas irOptimized: 1 + -// gas legacy: 20 + -// gas legacyOptimized: 300 + +// gas irOptimized: 4000 + +// gas irOptimized code: 50000 + +// gas legacy: 600000 + +// gas legacyOptimized: 7000000 + +// gas legacyOptimized code: 80000000 + -// gas legacy code: 900000000 + """).splitlines() + + self.assertEqual(collect_statistics(diff_output), ( + 1, # -irOptimized + 300, # -legacyOptimized + 900000020, # -legacy + 54000, # +irOptimized + 87000000, # +legacyOptimized + 600000, # +legacy + )) From e7312a501086e1b0751bc3abbc7e7f08de8b8acd Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 21 Feb 2024 21:09:09 +0100 Subject: [PATCH 46/47] Use CircleCI rust+node convenience image for t_ems_ext_hardhat job --- .circleci/config.yml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 663c64520e..30c0229642 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1385,7 +1385,7 @@ jobs: t_ems_ext_hardhat: <<: *base_node_small docker: - - image: cimg/node:18.16 + - image: cimg/rust:1.74.0-node environment: <<: *base_node_small_env HARDHAT_TESTS_SOLC_PATH: /tmp/workspace/soljson.js @@ -1395,18 +1395,15 @@ jobs: at: /tmp/workspace - run: name: Ensure pnpm is installed if npm is present - command: | - if command -v npm &> /dev/null; then - sudo npm install -g pnpm - fi + command: sudo npm install -g pnpm - run: name: Retrieve Hardhat latest release tag command: | # Make authenticated requests when the Github token is available if [[ -n "$GITHUB_ACCESS_TOKEN" ]]; then - EXTRA_HEADERS=(--header 'Authorization: Bearer '"${GITHUB_ACCESS_TOKEN}") + EXTRA_HEADERS=(--header "Authorization: Bearer ${GITHUB_ACCESS_TOKEN}") fi - HARDHAT_RELEASE_TAG=$( + HARDHAT_LATEST_RELEASE_TAG=$( curl \ --silent \ --location \ @@ -1416,8 +1413,8 @@ jobs: https://api.github.com/repos/nomiclabs/hardhat/releases/latest \ | jq --raw-output .tag_name \ ) - echo "export HARDHAT_RELEASE_TAG='${HARDHAT_RELEASE_TAG}'" >> "$BASH_ENV" - - run: git clone --depth 1 https://github.com/nomiclabs/hardhat.git --branch $HARDHAT_RELEASE_TAG + echo "export HARDHAT_LATEST_RELEASE_TAG='${HARDHAT_LATEST_RELEASE_TAG}'" >> "$BASH_ENV" + - run: git clone --depth 1 https://github.com/nomiclabs/hardhat.git --branch "$HARDHAT_LATEST_RELEASE_TAG" - run: name: Install dependencies command: | From c8358f5677a786847fb4783866f995d0e140389c Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 21 Feb 2024 21:01:28 +0100 Subject: [PATCH 47/47] Fix detect_hardhat_artifact_dir in externalTests scripts --- scripts/externalTests/common.sh | 41 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 3bca968a5a..082a25c4c5 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -570,17 +570,15 @@ 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 detect_hardhat_artifact_dirs +{ + # NOTE: The artifacts path is a configured parameter in Hardhat, so the below may fail for new external tests + # See: https://hardhat.org/hardhat-runner/docs/config#path-configuration + local artifact_dir=() + [[ -e build/artifacts ]] && artifact_dir+=("build/artifacts") + [[ -e artifacts/ ]] && artifact_dir+=("artifacts") + (( ${#artifact_dir[@]} != 0 )) || assertFail + echo -n "${artifact_dir[@]}" } function bytecode_size_json_from_truffle_artifacts @@ -605,16 +603,17 @@ function bytecode_size_json_from_truffle_artifacts function bytecode_size_json_from_hardhat_artifacts { # NOTE: The output of this function is a series of concatenated JSON dicts rather than a list. - - for artifact in "$(detect_hardhat_artifact_dir)"/build-info/*.json; do - # Each artifact contains Standard JSON output under the `output` key. - # Process it into a dict of the form `{"": {"": }}`, - # Note that one Hardhat artifact often represents multiple input files. - jq '.output.contracts | to_entries[] | { - "\(.key)": .value | to_entries[] | { - "\(.key)": (.value.evm.bytecode.object | length / 2) - } - }' "$artifact" + for artifact_dir in $(detect_hardhat_artifact_dirs); do + for artifact in "$artifact_dir"/build-info/*.json; do + # Each artifact contains Standard JSON output under the `output` key. + # Process it into a dict of the form `{"": {"": }}`, + # Note that one Hardhat artifact often represents multiple input files. + jq '.output.contracts | to_entries[] | { + "\(.key)": .value | to_entries[] | { + "\(.key)": (.value.evm.bytecode.object | length / 2) + } + }' "$artifact" + done done }