diff --git a/Changelog.md b/Changelog.md index adf89b3ac8f2..86378bc47b12 100644 --- a/Changelog.md +++ b/Changelog.md @@ -17,6 +17,7 @@ Compiler Features: Bugfixes: * Yul: Fix incorrect serialization of Yul object names containing double quotes and escape sequences, producing output that could not be parsed as valid Yul. * Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue. +* Yul IR Code Generation: Preserve custom error argument of `require` when option `revert-strings=strip` is selected. ### 0.8.34 (2026-02-18) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 7a97fa54e7b4..92601142a062 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -378,7 +378,9 @@ Input Description // How to treat revert (and require) reason strings. Settings are // "default", "strip", "debug" and "verboseDebug". // "default" does not inject compiler-generated revert strings and keeps user-supplied ones. - // "strip" removes all revert strings (if possible, i.e. if literals are used) keeping side-effects + // "strip" removes all revert strings (if possible, i.e. if literals are used) keeping side-effects. + // NOTE: "strip" does not remove custom errors. + // WARNING: Before Solidity 0.8.35, "strip" in the IR pipeline also removed custom errors. // "debug" injects strings for compiler-generated internal reverts, implemented for ABI encoders V1 and V2 for now. // "verboseDebug" even appends further information to user-supplied revert strings (not yet implemented) "revertStrings": "default", diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index d5cb27b6e1df..398cc6af616c 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1158,10 +1158,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) solAssert(arguments.size() > 0, "Expected at least one parameter for require/assert"); solAssert(arguments.size() <= 2, "Expected no more than two parameters for require/assert"); - Type const* messageArgumentType = - arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip ? - arguments[1]->annotation().type : - nullptr; + Type const* messageArgumentType = arguments.size() == 2 ? arguments[1]->annotation().type : nullptr; auto const* magicType = dynamic_cast(messageArgumentType); if (magicType && magicType->kind() == MagicType::Kind::Error) @@ -1175,6 +1172,9 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) } else { + // This option only removes strings, not custom errors + if (m_context.revertStrings() == RevertStrings::Strip) + messageArgumentType = nullptr; ASTPointer stringArgumentExpression = messageArgumentType ? arguments[1] : nullptr; std::string requireOrAssertFunction = m_utils.requireOrAssertFunction( functionType->kind() == FunctionType::Kind::Assert, diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/args b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/args new file mode 100644 index 000000000000..46e3d60a56fc --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/args @@ -0,0 +1 @@ +--revert-strings strip --debug-info none --asm --optimize diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/input.sol b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/input.sol new file mode 100644 index 000000000000..870b8d25597d --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/input.sol @@ -0,0 +1,11 @@ +pragma solidity >=0.0; +// SPDX-License-Identifier: GPL-3.0 +contract C { + error MyError(uint errorCode, string errorMsg, bool flag); + function flag() pure public returns (bool) { return false; } + function f() pure external { + uint code = 8; + string memory eMsg = "error"; + require(false, MyError(code, eMsg, flag())); + } +} diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/output b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/output new file mode 100644 index 000000000000..b478056ce468 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/output @@ -0,0 +1,173 @@ + +======= input.sol:C ======= +EVM assembly: + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + dup1 + 0x890eba68 + eq + tag_4 + jumpi + tag_2: + revert(0x00, 0x00) + tag_3: + tag_5 + tag_6 + jump // in + tag_5: + stop + tag_4: + 0x40 + dup1 + mload + 0x00 + dup2 + mstore + swap1 + mload + swap1 + dup2 + swap1 + sub + 0x20 + add + swap1 + return + tag_6: + 0x40 + dup1 + mload + dup1 + dup3 + add + swap1 + swap2 + mstore + 0x05 + dup2 + mstore + shl(0xd9, 0x32b93937b9) + 0x20 + dup3 + add + mstore + 0x08 + swap1 + dup2 + dup2 + 0x00 + mload(0x40) + shl(0xe5, 0x01676c8b) + dup2 + mstore + 0x04 + add + tag_14 + swap4 + swap3 + swap2 + swap1 + tag_15 + jump // in + tag_14: + mload(0x40) + dup1 + swap2 + sub + swap1 + revert + tag_15: + dup4 + dup2 + mstore + 0x60 + 0x20 + dup3 + add + mstore + 0x00 + dup4 + mload + dup1 + 0x60 + dup5 + add + mstore + dup1 + 0x20 + dup7 + add + 0x80 + dup6 + add + mcopy + 0x00 + 0x80 + dup3 + dup6 + add + add + mstore + 0x80 + 0x1f + not + 0x1f + dup4 + add + and + dup5 + add + add + swap2 + pop + pop + dup3 + iszero + iszero + 0x40 + dup4 + add + mstore + swap5 + swap4 + pop + pop + pop + pop + jump // out + + auxdata: +} diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/args b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/args new file mode 100644 index 000000000000..46e3d60a56fc --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/args @@ -0,0 +1 @@ +--revert-strings strip --debug-info none --asm --optimize diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/input.sol b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/input.sol new file mode 100644 index 000000000000..9b4d88bba792 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/input.sol @@ -0,0 +1,12 @@ +pragma solidity >=0.0; +// SPDX-License-Identifier: GPL-3.0 +contract C { + error MyError(uint errorCode, string errorMsg); + uint public counter = 0; + function count() public returns (uint) { return ++counter; } + function f() external { + string memory eMsg = "error"; + require(false, MyError(count(), eMsg)); + counter += 2; + } +} diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/output b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/output new file mode 100644 index 000000000000..b11a94d25a3d --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/output @@ -0,0 +1,271 @@ + +======= input.sol:C ======= +EVM assembly: + mstore(0x40, 0x80) + 0x00 + 0x00 + sstore + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x06661abd + eq + tag_3 + jumpi + dup1 + 0x26121ff0 + eq + tag_4 + jumpi + dup1 + 0x61bc221a + eq + tag_5 + jumpi + tag_2: + revert(0x00, 0x00) + tag_3: + tag_6 + tag_7 + jump // in + tag_6: + mload(0x40) + swap1 + dup2 + mstore + 0x20 + add + mload(0x40) + dup1 + swap2 + sub + swap1 + return + tag_4: + tag_10 + tag_11 + jump // in + tag_10: + stop + tag_5: + tag_6 + sload(0x00) + dup2 + jump + tag_7: + 0x00 + 0x00 + 0x00 + dup2 + sload + tag_16 + swap1 + tag_17 + jump // in + tag_16: + swap2 + dup3 + swap1 + sstore + pop + swap2 + swap1 + pop + jump // out + tag_11: + 0x40 + dup1 + mload + dup1 + dup3 + add + swap1 + swap2 + mstore + 0x05 + dup2 + mstore + shl(0xd9, 0x32b93937b9) + 0x20 + dup3 + add + mstore + 0x00 + tag_19 + tag_7 + jump // in + tag_19: + dup3 + swap1 + swap2 + tag_20 + jumpi + mload(0x40) + shl(0xe1, 0x05c9a271) + dup2 + mstore + 0x04 + add + tag_21 + swap3 + swap2 + swap1 + tag_22 + jump // in + tag_21: + mload(0x40) + dup1 + swap2 + sub + swap1 + revert + tag_20: + pop + pop + 0x02 + 0x00 + 0x00 + dup3 + dup3 + sload + tag_23 + swap2 + swap1 + tag_24 + jump // in + tag_23: + swap1 + swap2 + sstore + pop + pop + pop + jump // out + tag_25: + 0x4e487b71 + 0xe0 + shl + 0x00 + mstore + 0x11 + 0x04 + mstore + 0x24 + 0x00 + revert + tag_17: + 0x00 + 0x01 + dup3 + add + tag_31 + jumpi + tag_31 + tag_25 + jump // in + tag_31: + pop + 0x01 + add + swap1 + jump // out + tag_22: + dup3 + dup2 + mstore + 0x40 + 0x20 + dup3 + add + mstore + 0x00 + dup3 + mload + dup1 + 0x40 + dup5 + add + mstore + dup1 + 0x20 + dup6 + add + 0x60 + dup6 + add + mcopy + 0x00 + 0x60 + dup3 + dup6 + add + add + mstore + 0x60 + 0x1f + not + 0x1f + dup4 + add + and + dup5 + add + add + swap2 + pop + pop + swap4 + swap3 + pop + pop + pop + jump // out + tag_24: + dup1 + dup3 + add + dup1 + dup3 + gt + iszero + tag_35 + jumpi + tag_35 + tag_25 + jump // in + tag_35: + swap3 + swap2 + pop + pop + jump // out + + auxdata: +} diff --git a/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/in.sol b/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/in.sol new file mode 100644 index 000000000000..870b8d25597d --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/in.sol @@ -0,0 +1,11 @@ +pragma solidity >=0.0; +// SPDX-License-Identifier: GPL-3.0 +contract C { + error MyError(uint errorCode, string errorMsg, bool flag); + function flag() pure public returns (bool) { return false; } + function f() pure external { + uint code = 8; + string memory eMsg = "error"; + require(false, MyError(code, eMsg, flag())); + } +} diff --git a/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/input.json b/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/input.json new file mode 100644 index 000000000000..7a8951c2aeaa --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/input.json @@ -0,0 +1,16 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["in.sol"]} + }, + "settings": { + "viaIR": false, + "debug": { + "revertStrings": "strip", + "debugInfo": [] + }, + "outputSelection": { + "*": {"*": ["evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/output.json b/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/output.json new file mode 100644 index 000000000000..0d5635107dba --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_standard_json_io_legacy_require_custom_error/output.json @@ -0,0 +1,354 @@ +{ + "contracts": { + "C": { + "C": { + "evm": { + "assembly": " mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + dup1 + 0x890eba68 + eq + tag_4 + jumpi + tag_2: + revert(0x00, 0x00) + tag_3: + tag_5 + tag_6 + jump\t// in + tag_5: + stop + tag_4: + tag_7 + tag_8 + jump\t// in + tag_7: + mload(0x40) + tag_9 + swap2 + swap1 + tag_10 + jump\t// in + tag_9: + mload(0x40) + dup1 + swap2 + sub + swap1 + return + tag_6: + 0x00 + 0x08 + swap1 + pop + 0x00 + mload(0x40) + dup1 + 0x40 + add + 0x40 + mstore + dup1 + 0x05 + dup2 + mstore + 0x20 + add + 0x6572726f72000000000000000000000000000000000000000000000000000000 + dup2 + mstore + pop + swap1 + pop + 0x00 + dup3 + dup3 + tag_12 + tag_8 + jump\t// in + tag_12: + swap1 + swap2 + swap3 + tag_13 + jumpi + mload(0x40) + 0x2ced916000000000000000000000000000000000000000000000000000000000 + dup2 + mstore + 0x04 + add + tag_14 + swap4 + swap3 + swap2 + swap1 + tag_15 + jump\t// in + tag_14: + mload(0x40) + dup1 + swap2 + sub + swap1 + revert + tag_13: + pop + pop + pop + pop + pop + jump\t// out + tag_8: + 0x00 + 0x00 + swap1 + pop + swap1 + jump\t// out + tag_17: + 0x00 + dup2 + iszero + iszero + swap1 + pop + swap2 + swap1 + pop + jump\t// out + tag_18: + tag_29 + dup2 + tag_17 + jump\t// in + tag_29: + dup3 + mstore + pop + pop + jump\t// out + tag_10: + 0x00 + 0x20 + dup3 + add + swap1 + pop + tag_31 + 0x00 + dup4 + add + dup5 + tag_18 + jump\t// in + tag_31: + swap3 + swap2 + pop + pop + jump\t// out + tag_19: + 0x00 + dup2 + swap1 + pop + swap2 + swap1 + pop + jump\t// out + tag_20: + tag_34 + dup2 + tag_19 + jump\t// in + tag_34: + dup3 + mstore + pop + pop + jump\t// out + tag_21: + 0x00 + dup2 + mload + swap1 + pop + swap2 + swap1 + pop + jump\t// out + tag_22: + 0x00 + dup3 + dup3 + mstore + 0x20 + dup3 + add + swap1 + pop + swap3 + swap2 + pop + pop + jump\t// out + tag_23: + dup3 + dup2 + dup4 + mcopy + 0x00 + dup4 + dup4 + add + mstore + pop + pop + pop + jump\t// out + tag_24: + 0x00 + 0x1f + not + 0x1f + dup4 + add + and + swap1 + pop + swap2 + swap1 + pop + jump\t// out + tag_25: + 0x00 + tag_40 + dup3 + tag_21 + jump\t// in + tag_40: + tag_41 + dup2 + dup6 + tag_22 + jump\t// in + tag_41: + swap4 + pop + tag_42 + dup2 + dup6 + 0x20 + dup7 + add + tag_23 + jump\t// in + tag_42: + tag_43 + dup2 + tag_24 + jump\t// in + tag_43: + dup5 + add + swap2 + pop + pop + swap3 + swap2 + pop + pop + jump\t// out + tag_15: + 0x00 + 0x60 + dup3 + add + swap1 + pop + tag_45 + 0x00 + dup4 + add + dup7 + tag_20 + jump\t// in + tag_45: + dup2 + dup2 + sub + 0x20 + dup4 + add + mstore + tag_46 + dup2 + dup6 + tag_25 + jump\t// in + tag_46: + swap1 + pop + tag_47 + 0x40 + dup4 + add + dup5 + tag_18 + jump\t// in + tag_47: + swap5 + swap4 + pop + pop + pop + pop + jump\t// out + + auxdata: +} +" + } + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/in.sol b/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/in.sol new file mode 100644 index 000000000000..870b8d25597d --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/in.sol @@ -0,0 +1,11 @@ +pragma solidity >=0.0; +// SPDX-License-Identifier: GPL-3.0 +contract C { + error MyError(uint errorCode, string errorMsg, bool flag); + function flag() pure public returns (bool) { return false; } + function f() pure external { + uint code = 8; + string memory eMsg = "error"; + require(false, MyError(code, eMsg, flag())); + } +} diff --git a/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/input.json b/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/input.json new file mode 100644 index 000000000000..bda08da7605d --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/input.json @@ -0,0 +1,16 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["in.sol"]} + }, + "settings": { + "viaIR": true, + "debug": { + "revertStrings": "strip", + "debugInfo": [] + }, + "outputSelection": { + "*": {"*": ["evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/output.json b/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/output.json new file mode 100644 index 000000000000..1a98905a1479 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_standard_json_io_via_ir_require_custom_error/output.json @@ -0,0 +1,504 @@ +{ + "contracts": { + "C": { + "C": { + "evm": { + "assembly": " mstore(0x40, 0x80) + jumpi(tag_3, callvalue) + tag_5 + tag_1 + jump\t// in +tag_5: + dataSize(sub_0) + dataOffset(sub_0) + dup3 + codecopy + dataSize(sub_0) + swap1 + return +tag_3: + tag_2 + jump\t// in +tag_1: + mload(0x40) + swap1 + jump\t// out +tag_2: + 0x00 + dup1 + revert +stop + +sub_0: assembly { + mstore(0x40, 0x80) + jumpi(tag_36, iszero(lt(calldatasize, 0x04))) + tag_37: + tag_12 + jump\t// in + tag_36: + tag_38 + calldataload(0x00) + tag_1 + jump\t// in + tag_38: + dup1 + 0x26121ff0 + eq + tag_39 + jumpi + 0x890eba68 + sub + tag_37 + jumpi + tag_11 + jump\t// in + tag_39: + tag_7 + jump\t// in + tag_1: + 0xe0 + shr + swap1 + jump\t// out + tag_2: + mload(0x40) + swap1 + jump\t// out + tag_3: + 0x00 + dup1 + revert + tag_4: + 0x00 + dup1 + revert + tag_5: + 0x00 + swap2 + sub + slt + tag_43 + jumpi + jump\t// out + tag_43: + tag_4 + jump\t// in + tag_6: + 0x00 + add + swap1 + jump\t// out + tag_7: + jumpi(tag_45, callvalue) + tag_47 + calldatasize + 0x04 + tag_5 + jump\t// in + tag_47: + tag_48 + tag_33 + jump\t// in + tag_48: + tag_49 + tag_2 + jump\t// in + tag_49: + dup1 + tag_50 + dup2 + tag_6 + jump\t// in + tag_50: + sub + swap1 + return + tag_45: + tag_3 + jump\t// in + tag_8: + iszero + iszero + swap1 + jump\t// out + tag_9: + tag_51 + swap1 + tag_8 + jump\t// in + tag_51: + swap1 + mstore + jump\t// out + tag_10: + swap2 + swap1 + tag_52 + swap1 + 0x00 + 0x20 + dup6 + add + swap5 + add + swap1 + tag_9 + jump\t// in + tag_52: + jump\t// out + tag_11: + jumpi(tag_53, callvalue) + tag_55 + calldatasize + 0x04 + tag_5 + jump\t// in + tag_55: + tag_56 + tag_57 + tag_35 + jump\t// in + tag_57: + tag_58 + tag_2 + jump\t// in + tag_58: + swap2 + dup3 + swap2 + dup3 + tag_10 + jump\t// in + tag_56: + sub + swap1 + return + tag_53: + tag_3 + jump\t// in + tag_12: + 0x00 + dup1 + revert + tag_13: + swap1 + jump\t// out + tag_14: + swap1 + jump\t// out + tag_15: + swap1 + jump\t// out + tag_16: + tag_59 + tag_60 + tag_61 + swap3 + tag_13 + jump\t// in + tag_60: + tag_15 + jump\t// in + tag_59: + tag_14 + jump\t// in + tag_61: + swap1 + jump\t// out + tag_17: + 0x1f + dup1 + not + swap2 + add + and + swap1 + jump\t// out + tag_18: + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x41) + revert(0x00, 0x24) + tag_19: + swap1 + tag_62 + swap1 + tag_17 + jump\t// in + tag_62: + dup2 + add + swap1 + dup2 + lt + 0xffffffffffffffff + dup3 + gt + or + tag_63 + jumpi + 0x40 + mstore + jump\t// out + tag_63: + tag_18 + jump\t// in + tag_20: + swap1 + tag_65 + tag_66 + tag_2 + jump\t// in + tag_66: + swap3 + dup4 + tag_19 + jump\t// in + tag_65: + jump\t// out + tag_21: + 0xffffffffffffffff + dup2 + gt + tag_67 + jumpi + tag_69 + 0x20 + swap2 + tag_17 + jump\t// in + tag_69: + add + swap1 + jump\t// out + tag_67: + tag_18 + jump\t// in + tag_22: + swap1 + tag_70 + tag_71 + dup4 + tag_21 + jump\t// in + tag_71: + tag_20 + jump\t// in + tag_70: + swap2 + dup3 + mstore + jump\t// out + tag_23: + 0x00 + 0x6572726f72000000000000000000000000000000000000000000000000000000 + swap2 + add + mstore + jump\t// out + tag_24: + tag_72 + 0x05 + tag_22 + jump\t// in + tag_72: + swap1 + tag_73 + 0x20 + dup4 + add + tag_23 + jump\t// in + tag_73: + jump\t// out + tag_25: + tag_74 + tag_24 + jump\t// in + tag_74: + swap1 + jump\t// out + tag_26: + tag_75 + swap1 + tag_14 + jump\t// in + tag_75: + swap1 + mstore + jump\t// out + tag_27: + mload + swap1 + jump\t// out + tag_28: + 0x20 + swap2 + dup2 + mstore + add + swap1 + jump\t// out + tag_29: + swap1 + dup3 + 0x00 + swap4 + swap3 + dup3 + mcopy + add + mstore + jump\t// out + tag_30: + tag_76 + tag_77 + 0x20 + swap4 + tag_78 + swap4 + tag_79 + dup2 + tag_27 + jump\t// in + tag_79: + swap4 + dup5 + dup1 + swap4 + tag_28 + jump\t// in + tag_76: + swap6 + dup7 + swap2 + add + tag_29 + jump\t// in + tag_77: + tag_17 + jump\t// in + tag_78: + add + swap1 + jump\t// out + tag_31: + swap4 + swap3 + swap1 + tag_80 + 0x40 + swap2 + tag_81 + swap5 + tag_82 + 0x60 + dup10 + add + swap3 + 0x00 + dup11 + add + swap1 + tag_26 + jump\t// in + tag_82: + dup8 + dup3 + sub + 0x20 + dup10 + add + mstore + tag_30 + jump\t// in + tag_80: + swap5 + add + swap1 + tag_9 + jump\t// in + tag_81: + jump\t// out + tag_32: + swap3 + swap1 + swap2 + swap3 + iszero + tag_83 + jumpi + pop + pop + pop + jump\t// out + tag_83: + tag_85 + swap1 + tag_86 + tag_2 + jump\t// in + tag_86: + swap4 + dup5 + swap4 + shl(0xe5, 0x01676c8b) + dup6 + mstore + 0x04 + dup6 + add + tag_31 + jump\t// in + tag_85: + sub + swap1 + revert + tag_33: + tag_87 + tag_88 + 0x08 + tag_16 + jump\t// in + tag_88: + tag_89 + tag_25 + jump\t// in + tag_89: + 0x00 + swap2 + tag_90 + tag_35 + jump\t// in + tag_90: + swap3 + tag_32 + jump\t// in + tag_87: + jump\t// out + tag_34: + 0x00 + swap1 + jump\t// out + tag_35: + tag_91 + tag_34 + jump\t// in + tag_91: + pop + 0x00 + swap1 + jump\t// out + + auxdata: +} +" + } + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/args b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/args new file mode 100644 index 000000000000..2b930b856476 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/args @@ -0,0 +1 @@ +--revert-strings strip --debug-info none --asm --optimize --via-ir diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/input.sol b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/input.sol new file mode 100644 index 000000000000..870b8d25597d --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/input.sol @@ -0,0 +1,11 @@ +pragma solidity >=0.0; +// SPDX-License-Identifier: GPL-3.0 +contract C { + error MyError(uint errorCode, string errorMsg, bool flag); + function flag() pure public returns (bool) { return false; } + function f() pure external { + uint code = 8; + string memory eMsg = "error"; + require(false, MyError(code, eMsg, flag())); + } +} diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/output b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/output new file mode 100644 index 000000000000..7cdf2289b06c --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/output @@ -0,0 +1,146 @@ + +======= input.sol:C ======= +EVM assembly: + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, callvalue) + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return +tag_1: + 0x00 + dup1 + revert +stop + +sub_0: assembly { + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, iszero(lt(calldatasize, 0x04))) + 0x00 + dup1 + revert + tag_1: + shr(0xe0, calldataload(0x00)) + swap1 + dup2 + 0x26121ff0 + eq + tag_3 + jumpi + pop + 0x890eba68 + eq + tag_5 + jumpi + 0x00 + dup1 + revert + tag_5: + jumpi(tag_9, callvalue) + jumpi(tag_9, slt(add(not(0x03), calldatasize), 0x00)) + 0x20 + mload(0x40) + 0x00 + dup2 + mstore + return + tag_9: + 0x00 + dup1 + revert + tag_3: + jumpi(tag_9, callvalue) + jumpi(tag_9, slt(add(not(0x03), calldatasize), 0x00)) + 0x40 + dup2 + add + dup2 + dup2 + lt + 0xffffffffffffffff + dup3 + gt + or + tag_15 + jumpi + 0x40 + mstore + 0x05 + dup2 + mstore + 0x84 + 0x20 + dup3 + add + swap2 + shl(0xd9, 0x32b93937b9) + dup4 + mstore + mload(0x40) + swap3 + dup4 + swap2 + shl(0xe5, 0x01676c8b) + dup4 + mstore + 0x08 + 0x04 + dup5 + add + mstore + 0x60 + 0x24 + dup5 + add + mstore + mload + dup1 + swap2 + dup2 + 0x64 + dup6 + add + mstore + dup5 + dup5 + add + mcopy + 0x00 + dup3 + dup3 + add + dup5 + add + dup2 + swap1 + mstore + 0x44 + dup4 + add + mstore + 0x1f + add + not(0x1f) + and + dup2 + add + sub + add + swap1 + revert + tag_15: + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x41) + revert(0x00, 0x24) + + auxdata: +} diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/args b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/args new file mode 100644 index 000000000000..2b930b856476 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/args @@ -0,0 +1 @@ +--revert-strings strip --debug-info none --asm --optimize --via-ir diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/input.sol b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/input.sol new file mode 100644 index 000000000000..719765c576f4 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/input.sol @@ -0,0 +1,12 @@ +pragma solidity >=0.0; +// SPDX-License-Identifier: GPL-3.0 +contract C { + error MyError(uint errorCode, string errorMsg); + uint public counter = 0; + function genCode() public returns (uint) { return ++counter; } + function f() external { + string memory eMsg = "error"; + require(false, MyError(genCode(), eMsg)); + counter += 2; + } +} diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/output b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/output new file mode 100644 index 000000000000..d1749e308e75 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/output @@ -0,0 +1,183 @@ + +======= input.sol:C ======= +EVM assembly: + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, callvalue) + 0x00 + dup1 + sstore + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return +tag_1: + 0x00 + dup1 + revert +stop + +sub_0: assembly { + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_2, iszero(lt(calldatasize, 0x04))) + 0x00 + dup1 + revert + tag_2: + shr(0xe0, calldataload(0x00)) + swap1 + dup2 + 0x26121ff0 + eq + tag_4 + jumpi + pop + dup1 + 0x61bc221a + eq + tag_6 + jumpi + 0xaefa573d + eq + tag_8 + jumpi + 0x00 + dup1 + revert + tag_8: + jumpi(tag_12, callvalue) + jumpi(tag_12, slt(add(not(0x03), calldatasize), 0x00)) + 0x20 + tag_14 + tag_1 + jump // in + tag_14: + mload(0x40) + swap1 + dup2 + mstore + return + tag_12: + 0x00 + dup1 + revert + tag_6: + jumpi(tag_12, callvalue) + jumpi(tag_12, slt(add(not(0x03), calldatasize), 0x00)) + 0x20 + sload(0x00) + mload(0x40) + swap1 + dup2 + mstore + return + tag_4: + jumpi(tag_12, callvalue) + jumpi(tag_12, slt(add(not(0x03), calldatasize), 0x00)) + 0x40 + dup2 + add + dup2 + dup2 + lt + 0xffffffffffffffff + dup3 + gt + or + tag_23 + jumpi + 0x40 + mstore + 0x05 + dup2 + mstore + 0x64 + 0x20 + dup3 + add + shl(0xd9, 0x32b93937b9) + dup2 + mstore + tag_25 + tag_1 + jump // in + tag_25: + swap1 + mload(0x40) + swap4 + dup5 + swap3 + shl(0xe1, 0x05c9a271) + dup5 + mstore + 0x04 + dup5 + add + mstore + 0x40 + 0x24 + dup5 + add + mstore + mload + dup1 + swap2 + dup2 + 0x44 + dup6 + add + mstore + dup5 + dup5 + add + mcopy + 0x00 + dup3 + dup3 + add + dup5 + add + mstore + 0x1f + add + not(0x1f) + and + dup2 + add + sub + add + swap1 + revert + tag_23: + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x41) + revert(0x00, 0x24) + tag_1: + sload(0x00) + not(0x00) + dup2 + eq + tag_26 + jumpi + 0x01 + add + dup1 + 0x00 + sstore + swap1 + jump // out + tag_26: + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x11) + revert(0x00, 0x24) + + auxdata: +} diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_and_string_literal_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_custom_error_and_string_literal_revert_strings_strip.sol new file mode 100644 index 000000000000..29405fc17540 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_and_string_literal_revert_strings_strip.sol @@ -0,0 +1,14 @@ +contract C { + error MyError(string message); + function customError() pure external { + require(false, MyError("Error")); + } + function stringLiteral() pure external { + require(false, "Error"); + } +} +// ==== +// revertStrings: strip +// ---- +// customError() -> FAILURE, hex"8b3d2d43", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"0000000000000000000000000000000000000000000000000000000000000005", hex"4572726f72000000000000000000000000000000000000000000000000000000" +// stringLiteral() -> FAILURE diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect.sol b/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect.sol new file mode 100644 index 000000000000..c5e733176fb8 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect.sol @@ -0,0 +1,15 @@ +// The purpose of this test is to check that the side-effect of +// the error parameter occurs, i.e, MyError is constructed with errorCode = 1 +// and also confirm the state is properly reverted +contract C { + error MyError(uint errorCode); + uint public counter = 0; + function count() public returns (uint) { return ++counter; } + function f() external { + require(false, MyError(count())); + counter = 42; + } +} +// ---- +// f() -> FAILURE, hex"30b1b565", hex"0000000000000000000000000000000000000000000000000000000000000001" +// counter() -> 0 diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect_revert_strings_strip.sol new file mode 100644 index 000000000000..4838ed4e2d77 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect_revert_strings_strip.sol @@ -0,0 +1,17 @@ +// The purpose of this test is to check that the side-effect of +// the error parameter occurs, i.e, MyError is constructed with errorCode = 1 +// and also confirm the state is properly reverted +contract C { + error MyError(uint errorCode); + uint public counter = 0; + function count() public returns (uint) { return ++counter; } + function f() external { + require(false, MyError(count())); + counter = 42; + } +} +// ==== +// revertStrings: strip +// ---- +// f() -> FAILURE, hex"30b1b565", hex"0000000000000000000000000000000000000000000000000000000000000001" +// counter() -> 0 diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_no_args_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_custom_error_no_args_revert_strings_strip.sol new file mode 100644 index 000000000000..e92b62393689 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_no_args_revert_strings_strip.sol @@ -0,0 +1,13 @@ +contract C { + error MyError(); + function flag() pure public returns (bool) { return false; } + function f(int param) pure external returns (int) { + require(param % 2 == 0, MyError()); + return param / 2; + } +} +// ==== +// revertStrings: strip +// ---- +// f(int256): 3 -> FAILURE, hex"dd6c951c" +// f(int256): 4 -> 2 diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_custom_error_revert_strings_strip.sol new file mode 100644 index 000000000000..a239d74697ab --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_revert_strings_strip.sol @@ -0,0 +1,14 @@ +contract C { + error MyError(uint errorCode, string errorMsg, bool flag); + function flag() pure public returns (bool) { return false; } + function f(int param) pure external { + uint code = 8; + string memory eMsg = "error"; + require(param % 2 == 0, MyError(code, eMsg, flag())); + } +} +// ==== +// revertStrings: strip +// ---- +// f(int256): 3 -> FAILURE, hex"2ced9160", hex"0000000000000000000000000000000000000000000000000000000000000008", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000000", hex"0000000000000000000000000000000000000000000000000000000000000005", hex"6572726f72000000000000000000000000000000000000000000000000000000" +// f(int256): 4 -> diff --git a/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once_revert_strings_strip.sol new file mode 100644 index 000000000000..383dfdd87685 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once_revert_strings_strip.sol @@ -0,0 +1,25 @@ +contract C { + uint256 counter = 0; + + error CustomError(uint256); + + function getCounter() public view returns (uint256) { + return counter; + } + + function g(bool condition) internal returns (bool) { + counter++; + return condition; + } + + function f(bool condition) external { + require(g(condition), CustomError(counter)); + } +} +// ==== +// revertStrings: strip +// ---- +// f(bool): false -> FAILURE, hex"110b3655", 1 +// getCounter() -> 0 +// f(bool): true -> +// getCounter() -> 1 diff --git a/test/libsolidity/semanticTests/errors/require_error_evaluation_order_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_revert_strings_strip.sol new file mode 100644 index 000000000000..af9c709763ba --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_revert_strings_strip.sol @@ -0,0 +1,17 @@ +contract C { + uint y; + function g(bool x) internal returns (bool) { + y = 42; + return x; + } + error E(uint256); + function h() internal returns (uint256) { return y; } + function f(bool c) public { + require(g(c), E(h())); + } +} +// ==== +// revertStrings: strip +// ---- +// f(bool): false -> FAILURE, hex"002ff067", 42 +// f(bool): true -> diff --git a/test/libsolidity/semanticTests/errors/require_error_stack_check_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_error_stack_check_revert_strings_strip.sol new file mode 100644 index 000000000000..7dcdb1cc6acc --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_stack_check_revert_strings_strip.sol @@ -0,0 +1,21 @@ +// The purpose of this test is to make sure that error constructor call +// stack items are popped from the stack in the success branch, i.e. when +// require condition is true. +contract C { + error E(uint, uint, uint, function(uint256) external pure returns (uint256)); + uint public x; + + function e(uint256 y) external pure returns (uint256) { + return y; + } + + function f(bool condition, uint a, uint b, uint c) public { + require(condition, E(a, b, c, this.e)); + x = b; + } +} +// ==== +// revertStrings: strip +// ---- +// f(bool,uint256,uint256,uint256): true, 42, 4242, 424242 -> +// x() -> 4242 diff --git a/test/libsolidity/semanticTests/errors/require_inherited_error_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_inherited_error_revert_strings_strip.sol new file mode 100644 index 000000000000..eea8a1e18fd1 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_inherited_error_revert_strings_strip.sol @@ -0,0 +1,16 @@ +contract Base +{ + error CustomError(uint256, string, uint256); +} + +contract C is Base +{ + function f() external pure + { + require(false, CustomError(1, "two", 3)); + } +} +// ==== +// revertStrings: strip +// ---- +// f() -> FAILURE, hex"11a1077e", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"74776f0000000000000000000000000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/revert_statement_error_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/revert_statement_error_revert_strings_strip.sol new file mode 100644 index 000000000000..3be2c3ac2e4d --- /dev/null +++ b/test/libsolidity/semanticTests/errors/revert_statement_error_revert_strings_strip.sol @@ -0,0 +1,10 @@ +contract C { + error MyError(string message); + function revertStatement() pure external { + revert MyError("Error"); + } +} +// ==== +// revertStrings: strip +// ---- +// revertStatement() -> FAILURE, hex"8b3d2d43", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"0000000000000000000000000000000000000000000000000000000000000005", hex"4572726f72000000000000000000000000000000000000000000000000000000"