diff --git a/Changelog.md b/Changelog.md index b295b7bf445c..44c6d2b31a05 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,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/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index 319aa4d8b1da..5bd50105fc80 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -1,4 +1,5 @@ .. index:: storage, state variable, mapping, transient storage +.. _storage-layout: ********************************************************** Layout of State Variables in Storage and Transient Storage diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 7a97fa54e7b4..04fdcfca570d 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -202,12 +202,381 @@ The compiler API expects a JSON formatted input and outputs the compilation resu The standard error output is not used and the process will always terminate in a "success" state, even if there were errors. Errors are always reported as part of the JSON output. -The following subsections describe the format through an example. -Comments are of course not permitted and used here only for explanatory purposes. +The following subsections describe the layout and explain each field and object of the format. Input Description ----------------- +The root JSON object contains three top level keys that define the compilation process. + ++--------------+--------+----------+---------------------------------------------------------------------+ +| Field | Type | Required | Description | ++==============+========+==========+=====================================================================+ +| ``language`` | string | Yes | Source code language. Supported values: ``"Solidity"``, ``"Yul"``, | +| | | | ``"SolidityAST"`` (experimental), ``"EVMAssembly"`` (experimental). | ++--------------+--------+----------+---------------------------------------------------------------------+ +| ``sources`` | object | Yes | Map of source file names to their content or URL references. | ++--------------+--------+----------+---------------------------------------------------------------------+ +| ``settings`` | object | No | Compiler configuration including optimizer, EVM version, output | +| | | | selection, among others. | ++--------------+--------+----------+---------------------------------------------------------------------+ + +Sources +------- + +The ``sources`` object is a map where each key is the global name of a source file. +Imports can use other files via remappings (see below). +Each value is a source descriptor object with the following fields. + +keccak256 +^^^^^^^^^ + +Optional. +Keccak-256 hash of the source file content. +It is used to verify the retrieved content if imported via URLs. + + +urls +^^^^ + +URL(s) to the source file. +Required unless ``content`` is used +URL(s) should be imported in this order and the result checked against the keccak256 hash (if available). +If the hash doesn't match or none of the URL(s) result in success, an error should be raised. +Using the commandline interface only filesystem paths are supported. +With the JavaScript interface the URL will be passed to the user-supplied read callback, +so any URL supported by the callback can be used. +If files are used, their directories should be added to the command-line via `--allow-paths `. + +ast +^^^ + +Required if language is set to "SolidityAST". +If language is set to "SolidityAST", an AST needs to be supplied under the "ast" key and there can be only one source file present. +The format is the same as used by the ``ast`` output. +Note that importing ASTs is experimental and in particular that: +- importing invalid ASTs can produce undefined results and +- no proper error reporting is available on invalid ASTs. + +Furthermore, note that the AST import only consumes the fields of the AST as produced by the compiler in +"stopAfter": "parsing" mode and then re-performs analysis, so any analysis-based annotations of the AST are ignored upon import. + +assemblyJson +^^^^^^^^^^^^ + +Required if language is set to "EVMAssembly". +If language is set to "EVMAssembly", an EVM Assembly JSON object needs to be supplied under +the "assemblyJson" key and there can be only one source file present. +The format is the same as used by the ``evm.legacyAssembly`` output or ``--asm-json`` output on the command line. +Note that importing EVM assembly is experimental. + +TODO: +".data": { ... }, // optional +"sourceList": [ ... ] // optional (if no ``source`` node was defined in any ``.code`` object) + +.. note:: + + For Solidity and Yul languages, each source must provide either ``urls`` or ``content``. + For SolidityAST, the ``ast`` field replaces both. + For EVMAssembly, the ``assemblyJson`` field is used instead. + +Settings +-------- + +The ``settings`` object defines general configuration of the compilation pipeline, +such as the EVM version and enabling the IR pipeline, and also specific configuration for +the optimizer, debug, metadata, libraries and output selection. +Every field within ``settings`` is optional and in case they are omitted, the compiler uses default values. + +General Settings +^^^^^^^^^^^^^^^^ + ++------------------+----------+-------------------------------------------------------------------------+ +| Field | Type | Description | ++==================+==========+=========================================================================+ +| ``stopAfter`` | string | Stop compilation after the given stage. Currently only ``"parsing"`` | +| | | is valid. | ++------------------+----------+-------------------------------------------------------------------------+ +| ``remappings`` | string[] | List of remappings. | ++------------------+----------+-------------------------------------------------------------------------+ +| ``experimental`` | boolean | Experimental mode toggle, false by default. Makes it possible to use | +| | | experimental features (but does not enable any such feature by itself). | +| | | The use of this mode is recorded in contract metadata. | ++------------------+----------+-------------------------------------------------------------------------+ +| ``evmVersion`` | string | Version of the EVM to compile for. Affects type checking and code | +| | | generation. Can be ``homestead``, ``tangerineWhistle``, | +| | | ``spuriousDragon``, ``byzantium``, ``constantinople``, | +| | | ``petersburg``, ``istanbul``, ``berlin``, ``london``, ``paris``, | +| | | ``shanghai``, ``cancun``, ``prague`` or ``osaka`` (default). | ++------------------+----------+-------------------------------------------------------------------------+ +| ``eofVersion`` | integer | Experimental. EVM Object Format version to compile for. Currently the | +| | | only valid value is ``1``. If not specified, legacy non-EOF bytecode | +| | | will be generated. Requires ``evmVersion`` >= ``osaka``. | ++------------------+----------+-------------------------------------------------------------------------+ +| ``viaIR`` | boolean | Change compilation pipeline to go through the Yul intermediate | +| | | representation. False by default. | ++------------------+----------+-------------------------------------------------------------------------+ +| ``viaSSACFG`` | boolean | Experimental. Turn on SSA CFG-based code generation via the IR | +| | | (implies ``viaIR: true``). False by default. | ++------------------+----------+-------------------------------------------------------------------------+ + +Optimizer Settings +^^^^^^^^^^^^^^^^^^ + +The ``optimizer`` object controls how aggressively the compiler optimizes the generated bytecode. +As mentioned before, all settings are optional and have default values. +The optimizer can be turned on by a top level toggle field, ``optimizer.enabled``, which is false by default. + +.. note:: + The state of the optimizer is fully determined by the 'details' dict and this setting + only affects its defaults - when enabled, all components default to being enabled. + The opposite is not true - there are several components that always default to being + enabled an can only be explicitly disabled via 'details'. + +.. warning:: + Before version 0.8.6 omitting this setting was not equivalent to setting + it to false and would result in all components being disabled instead. + +.. warning:: + Enabling optimizations for EVMAssembly input is allowed but not necessary under normal circumstances. + It forces the opcode-based optimizer to run again and can produce bytecode that is not reproducible from metadata. + +The integer field ``optimizer.runs`` indicates how many times the code is intended to run. +This field is optional and defaults to a value of 200. +Lower values will optimize more for initial deployment cost, higher values will optimize more for high-frequency usage. + +The ``optimizer.details`` object provides fine-grained control over individual optimizer components. +The default values are determined by whether the optimizer is enabled or not. + +.. note:: + The ``optimizer.enabled`` setting only affects the defaults of ``optimizer.details`` + and has no effect when all values are provided explicitly. + +Each component can be enabled using the following boolean fields: + ++--------------------------------------------+---------+---------------------------------------------------------------+ +| Field | Default | Description | ++============================================+=========+===============================================================+ +| ``peephole`` | True | Peephole optimizer (opcode-based). Always run, even with | +| | | optimization disabled, except for EVMAssembly input or when | +| | | explicitly turned off. | ++--------------------------------------------+---------+---------------------------------------------------------------+ +| ``inliner`` | True | Inliner (opcode-based). | ++--------------------------------------------+---------+---------------------------------------------------------------+ +| ``jumpdestRemover`` | True | Unused ``JUMPDEST`` remover (opcode-based). Always runs, even | +| | | with optimization disabled, except for EVMAssembly input or | +| | | when explicitly turned off. | ++--------------------------------------------+---------+---------------------------------------------------------------+ +| ``orderLiterals`` | True | Literal reordering (codegen-based). Moves literals to the | +| | | right of commutative binary operators during code generation, | +| | | helping exploit associativity. | ++--------------------------------------------+---------+---------------------------------------------------------------+ +| ``deduplicate`` | True | Block deduplicator (opcode-based). Unifies assembly code | +| | | blocks that share content. | ++--------------------------------------------+---------+---------------------------------------------------------------+ +| ``cse`` | True | Common subexpression elimination (opcode-based). This is the | +| | | most complicated step but can also provide the largest gain. | ++--------------------------------------------+---------+---------------------------------------------------------------+ +| ``constantOptimizer`` | True | Constant optimizer (opcode-based). Tries to find better | +| | | representations of literal numbers and strings, that satisfy | +| | | the size/cost trade-off determined by the ``runs`` setting. | ++--------------------------------------------+---------+---------------------------------------------------------------+ +| ``simpleCounterForLoopUncheckedIncrement`` | True | Unchecked loop increment (codegen-based). Use unchecked | +| | | arithmetic when incrementing the counter of ``for`` loops | +| | | under certain circumstances. Always runs, even with | +| | | optimization disabled, unless explicitly turned off. | ++--------------------------------------------+---------+---------------------------------------------------------------+ +| ``yul`` | True | Yul optimizer. Used to optimize the IR produced by the Yul | +| | | IR-based pipeline as well as inline assembly and utility Yul | +| | | code generated by the compiler. Before Solidity 0.6.0 the | +| | | default was ``false``. | ++--------------------------------------------+---------+---------------------------------------------------------------+ + +There is also the ``optimizer.yulDetails`` subobject which contains fine tuning options for the Yul optimizer. +The ``optimizer.yulDetails.stackAllocation`` setting aims to improve allocation of stack slots for variables and can free up stack slots early. +The ``optimizer.yulDetails.optimizerSteps`` is the most important setting of the Yul optimizer, defining its optimization step sequence. +The general form of the value is "
:". +The setting is optional and when omitted, default values are used for both sequences. +If the value does not contain the ``:`` delimiter, it is interpreted as the main sequence and the default is used for the cleanup sequence. +To make one of the sequences empty, the delimiter must be present at the first or last position. +In particular if the whole value consists only of the delimiter, both sequences are empty. +Note that there are several hard-coded steps that always run, even when both sequences are empty. +For more information see :ref:`Selecting Optimizations `. + +Debug Settings +^^^^^^^^^^^^^^ + +The ``debug`` object controls how revert and require reason strings and debug annotations are handled in the output. + +The ``debug.revertStrings`` field defines how to treat revert and require reason strings. +Settings are: + +- "default": does not inject compiler-generated revert strings and keeps user-supplied ones. +- "strip": removes all revert strings keeping side-effects +- "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). + +The ``debug.debugInfo`` field defines how much extra debug information to include +in comments in the producedEVM assembly and Yul code. +Available components are: + +- ``location``: Annotations of the form ``@src ::`` indicating the location of + the corresponding element in the original Solidity file, where: + + - ```` is the file index matching the ``@use-src`` annotation, + - ```` is the index of the first byte at that location, + - ```` is the index of the first byte after that location. + +- ``snippet``: A single-line code snippet from the location indicated by ``@src``. The snippet is + quoted and follows the corresponding ``@src`` annotation. +- ``ast-id``: Annotations of the form ``@ast-id `` over elements that can be mapped back to + a definition in the original Solidity file. ```` is a node ID in the Solidity AST ('ast' output). +- ``ethdebug``: Ethdebug annotations (experimental). +- ``*``: Wildcard value that can be used to request all non-experimental components. + +Metadata Settings +^^^^^^^^^^^^^^^^^ +The ``metadata`` object configures how contract metadata is embedded in the compiled bytecode. + ++--------------------------------+---------+---------+------------------------------------------------------+ +| Field | Type | Default | Description | ++================================+=========+=========+======================================================+ +| ``appendCBOR`` | boolean | True | The CBOR metadata is appended at the end of the | +| | | | bytecode by default. Setting this to false omits the | +| | | | metadata from the runtime and deploy time code. | ++--------------------------------+---------+---------+------------------------------------------------------+ +| ``metadata.useLiteralContent`` | boolean | False | Use only literal content and not URLs | ++--------------------------------+---------+---------+------------------------------------------------------+ +| ``metadata.bytecodeHash`` | string | "ipfs" | Use the given hash method for the metadata hash that | +| | | | is appended to the bytecode. The metadata hash can | +| | | | be removed from the bytecode via option "none". The | +| | | | other options are "ipfs" and "bzzr1". | ++--------------------------------+---------+---------+------------------------------------------------------+ + +Libraries +^^^^^^^^^ + +The ``libraries`` object provides addresses for linked library contracts. +If not all libraries are given here, it can result in unlinked objects whose output data is different. + +The top level key is the name of the source file where the library is used. +If remappings are used, this source file should match the global path after remappings were applied. +If this key is an empty string, that refers to a global level. +Each value is an object mapping library names to their deployed addresses. +Example: + +.. code-block:: javascript + + "myFile.sol": { + "MyLib": "0x123..." + } + + +Output Selection +^^^^^^^^^^^^^^^^ + +The ``outputSelection`` object can be used to select desired outputs based on file and contract names. +If this is omitted, then the compiler loads and does type checking, but will not generate any outputs apart from errors. +The first level key is the file name and the second level key is the contract name. +An empty contract name is used for outputs that are not tied to a contract but to the whole source file like the AST. +A star as contract name refers to all contracts in the file. +Similarly, a star as a file name matches all files. +To select all outputs the compiler can possibly generate, with the exclusion of Yul intermediate +representation outputs, use "outputSelection: { "*": { "*": [ "*" ], "": [ "*" ] } }" +but note that this might slow down the compilation process needlessly. +The available output types are as follows: + +- File level (needs empty string as contract name): + + - ast - AST of all source files + +- Contract level (needs the contract name or "*"): + + - abi - ABI + - devdoc - Developer documentation (natspec) + - userdoc - User documentation (natspec) + - metadata - Metadata + - ir - Yul intermediate representation of the code before optimization + - irAst - AST of Yul intermediate representation of the code before optimization (experimental) + - irOptimized - Intermediate representation after optimization + - irOptimizedAst - AST of intermediate representation after optimization (experimental) + - storageLayout - Slots, offsets and types of the contract's state variables in storage + - transientStorageLayout - Slots, offsets and types of the contract's state variables in transient storage + - evm.assembly - New assembly format + - evm.legacyAssembly - Old-style assembly format in JSON + - evm.bytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema). Can only be requested when compiling via IR. (experimental) + - evm.deployedBytecode.ethdebug - Like evm.bytecode.ethdebug, but for the runtime part of the contract (experimental) + - evm.bytecode.functionDebugData - Debugging information at function level + - evm.bytecode.object - Bytecode object + - evm.bytecode.opcodes - Opcodes list + - evm.bytecode.sourceMap - Source mapping (useful for debugging) + - evm.bytecode.linkReferences - Link references (if unlinked object) + - evm.bytecode.generatedSources - Sources generated by the compiler + - evm.deployedBytecode* - Deployed bytecode (has all the options that evm.bytecode has) + - evm.deployedBytecode.immutableReferences - Map from AST ids to bytecode ranges that reference immutables + - evm.methodIdentifiers - The list of function hashes + - evm.gasEstimates - Function gas estimates + - yulCFGJson - Control Flow Graph (CFG) of the Single Static Assignment (SSA) form of the contract (experimental) + +Note that Using ``evm``, ``evm.bytecode``, etc. will select every target part of that output. +Additionally, ``*`` can be used as a wildcard to request everything. + +Model Checker Settings +^^^^^^^^^^^^^^^^^^^^^^ + +The `modelChecker` object configures the built-in SMTChecker for formal verification of contracts. +The model checker settings are experimental and subject to change. + ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| Field | Type | Description | ++==================================+===========+=========================================================================+ +| ``contracts`` | object | Map of source files to arrays of contract names that should be | +| | | analyzed as deployed contracts. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``divModNoSlacks`` | boolean | Choose how division and modulo operations should be encoded. | +| | | When using ``false`` they are replaced by multiplication with slack | +| | | variables. This is the default. Using ``true`` here is recommended if | +| | | you are using the CHC engine and not using Spacer as the Horn solver | +| | | (using Eldarica, for example). See the `Formal Verification section | +| | | ` for a more detailed explanation. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``engine`` | string | Choose which model checker engine to use: all (default), bmc, chc, | +| | | none. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``modelChecker.extCalls`` | string | Choose whether external calls should be considered trusted in case the | +| | | code of the called function is available at compile-time. For details | +| | | see the `SMTChecker section `. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``modelChecker.invariants`` | string[] | Choose which types of invariants should be reported to the user: | +| | | contract, reentrancy. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``modelChecker.showProvedSafe`` | boolean | Choose whether to output all proved targets. The default is ``false``. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``modelChecker.showUnproved`` | boolean | Choose whether to output all unproved targets. The default is | +| | | ``false``. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``modelChecker.showUnsupported`` | boolean | Choose whether to output all unsupported language features. The default | +| | | is ``false``. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``modelChecker.solvers`` | string[] | Choose which solvers should be used, if available. Options: | +| | | ``"cvc5"``, ``"smtlib2"``, ``"z3"``. See the `Formal Verification | +| | | section ` for the solvers description. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``modelChecker.targets`` | string[] | Choose which targets should be checked. Options: constantCondition, | +| | | underflow, overflow, divByZero, balance, assert, popEmptyArray, | +| | | outOfBounds. If the option is not given all targets are checked by | +| | | default, except underflow/overflow for Solidity >=0.8.7. See the | +| | | `Formal Verification section ` for the targets | +| | | description. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ +| ``modelChecker.timeout`` | integer | Timeout for each SMT query in milliseconds. If this option is not | +| | | given, the SMTChecker will use a deterministic resource limit by | +| | | default. A given timeout of 0 means no resource/time restrictions for | +| | | any query. | ++----------------------------------+-----------+-------------------------------------------------------------------------+ + +Example: TODO: cleanup. complete settings? Minimal and realistic? + .. code-block:: javascript { @@ -378,7 +747,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 used to remove 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", @@ -537,6 +908,213 @@ Input Description Output Description ------------------ +The Solidity Standard JSON Output is the structured result returned by the +Solidity compiler after processing a Standard JSON Input file. +The output object is shaped by the `outputSelection` field in the input JSON file, +only the artifacts explicitly requested are included in the response. +Errors and warnings are always returned regardless of output selection settings. + +The root JSON output object contains up to four top-level keys. + ++---------------+--------+----------+-------------------------------------------------------------+ +| Field | Type | Required | Description | ++===============+========+==========+=============================================================+ +| ``errors`` | array | No | Not present if no errors, warnings, infos were encountered. | ++---------------+--------+----------+-------------------------------------------------------------+ +| ``sources`` | object | Yes | This contains the file-level outputs. | +| | | | It can be limited/filtered by the outputSelection settings. | ++---------------+--------+----------+-------------------------------------------------------------+ +| ``contracts`` | object | Yes | This contains the contract-level outputs. | +| | | | It can be limited/filtered by the outputSelection settings. | ++---------------+--------+----------+-------------------------------------------------------------+ +| ``ethdebug`` | object | No | Global Ethdebug output (experimental). | ++---------------+--------+----------+-------------------------------------------------------------+ + +Errors +------ + +The ``errors`` array contains diagnostic messages produced during compilation. +Each element is an object describing an error, warning, or info message. + ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ +| Field | Type | Required | Description | ++==============================+========+==========+=============================================================================+ +| ``type`` | string | Yes | Error type, such as "TypeError", "InternalCompilerError", "Exception", etc. | +| | | | See below for complete list of types. | ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ +| ``component`` | string | Yes | Component where the error originated, such as "general" etc. | ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ +| ``severity`` | string | Yes | Possible values are "error", "warning" or "info", | +| | | | but please note that this may be extended in the future. | ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ +| ``errorCode`` | string | No | Unique code for the cause of the error. | ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ +| ``message`` | string | Yes | The error message. | ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ +| ``formattedMessage`` | string | No | The message formatted with source location. | ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ +| ``sourceLocation`` | object | No | Location within the source file. | +| | | | Contains three fields, "file", "start", "end". | ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ +| ``secondarySourceLocations`` | array | No | Further locations (e.g. places of conflicting declarations). | +| | | | Contains the same fields of "sourceLocation" and also "message". | ++------------------------------+--------+----------+-----------------------------------------------------------------------------+ + +Error Types +^^^^^^^^^^^ + +1. ``JSONError``: JSON input doesn't conform to the required format, e.g. input is not a JSON object, the language is not supported, etc. +2. ``IOError``: IO and import processing errors, such as unresolvable URL or hash mismatch in supplied sources. +3. ``ParserError``: Source code doesn't conform to the language rules. +4. ``DocstringParsingError``: The NatSpec tags in the comment block cannot be parsed. +5. ``SyntaxError``: Syntactical error, such as ``continue`` is used outside of a ``for`` loop. +6. ``DeclarationError``: Invalid, unresolvable or clashing identifier names. e.g. ``Identifier not found`` +7. ``TypeError``: Error within the type system, such as invalid type conversions, invalid assignments, etc. +8. ``UnimplementedFeatureError``: Feature is not supported by the compiler, but is expected to be supported in future versions. +9. ``InternalCompilerError``: Internal bug triggered in the compiler - this should be reported as an issue. +10. ``Exception``: Unknown failure during compilation - this should be reported as an issue. +11. ``CompilerError``: Invalid use of the compiler stack - this should be reported as an issue. +12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue. +13. ``YulException``: Error during Yul code generation - this should be reported as an issue. +14. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible. +15. ``Info``: Information that the compiler thinks the user might find useful, but is not dangerous and does not necessarily need to be addressed. + + +Sources +------- + +The ``sources`` object in the output contains file-level compilation artifacts. +Each entry corresponds to a source file provided in the input. + +- ``id``: Identifier of the source (used in source maps). +- ``ast``: The AST object. + +Contracts +--------- + +The ``contracts`` object is organized as a two-level map: the first level key is the source file name, +and the second level key is the contract name. +If the language has no concept of contract names (e.g., Yul), the contract name is an empty string. + ++----------------------------+--------+----------------------------------------------------------------------------------+ +| Field | Type | Description | ++============================+========+==================================================================================+ +| ``abi`` | array | The Ethereum Contract ABI. If empty, it is represented as an empty array. | +| | | See :ref:`ABI section `. | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``metadata`` | string | See the :ref:`Metadata Output documentation` (serialised JSON string). | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``userdoc`` | object | User documentation (see :ref:`Natspec Format`). | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``devdoc`` | object | Developer documentation (see :ref:`Natspec Format`). | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``ir`` | string | Intermediate representation before optimization. | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``irAst`` | object | AST of intermediate representation before optimization. | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``irOptimized`` | string | Intermediate representation after optimization. | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``irOptimizedAst`` | object | AST of intermediate representation after optimization. | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``storageLayout`` | object | Describes the :ref:`storage layout `. | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``transientStorageLayout`` | object | Describes the :ref:`transient storage layout `. | ++----------------------------+--------+----------------------------------------------------------------------------------+ +| ``evm`` | object | EVM-related outputs. Described below. | ++----------------------------+--------+----------------------------------------------------------------------------------+ + +evm +^^^ + +The `evm` object is the largest output section, containing all bytecode, assembly, debugging data, +method identifiers, and gas estimates for a contract. + ++-----------------------+--------+---------------------------------------------------------------------------------------------+ +| Field | Type | Description | ++=======================+========+=============================================================================================+ +| ``assembly`` | string | New format EVM assembly representation of the compiled contract as a human-readable string. | ++-----------------------+--------+---------------------------------------------------------------------------------------------+ +| ``legacyAssembly`` | object | Old style assembly output as a structured JSON object. Contains code arrays, data sections, | +| | | and source references. Corresponds to the ``--asm-json`` CLI flag. | ++-----------------------+--------+---------------------------------------------------------------------------------------------+ +| ``bytecode`` | object | Contains immutable references and ethdebug (experimental). | ++-----------------------+--------+---------------------------------------------------------------------------------------------+ +| ``deployedBytecode`` | object | Contains immutable references and ethdebug (experimental). | ++-----------------------+--------+---------------------------------------------------------------------------------------------+ +| ``methodIdentifiers`` | object | The list of function hashes. Maps thje name of the method to its hash. | ++-----------------------+--------+---------------------------------------------------------------------------------------------+ +| ``gasEstimates`` | object | Function gas estimates. | ++-----------------------+--------+---------------------------------------------------------------------------------------------+ +| ``yulCFGJson`` | object | Yul CFG representation of the SSA form (experimental). | ++-----------------------+--------+---------------------------------------------------------------------------------------------+ + +evm.bytecode +^^^^^^^^^^^^ + +The ``evm.bytecode`` object contains the deployment (creation) bytecode and all associated debugging and linking metadata. +The deployment bytecode is the code that runs during contract creation and returns the runtime bytecode. + ++-----------------------+--------+----------------------------------------------------------------------------------------+ +| Field | Type | Description | ++=======================+========+========================================================================================+ +| ``object`` | string | The compiled bytecode as a hex string. | ++-----------------------+--------+----------------------------------------------------------------------------------------+ +| ``opcodes`` | string | Opcode list. | ++-----------------------+--------+----------------------------------------------------------------------------------------+ +| ``sourceMap`` | string | The source mapping as a string. See the source mapping definition. | ++-----------------------+--------+----------------------------------------------------------------------------------------+ +| ``generatedSources`` | array | Array of sources generated by the compiler. Currently only contains a single Yul file. | ++-----------------------+--------+----------------------------------------------------------------------------------------+ +| ``linkReferences`` | object | If given, this is an unlinked object. References for unlinked library calls. | ++-----------------------+--------+----------------------------------------------------------------------------------------+ +| ``functionDebugData`` | object | Debugging data at the level of functions. | ++-----------------------+--------+----------------------------------------------------------------------------------------+ +| ``ethdebug`` | object | Debug information in the ethdebug format (experimental). | ++-----------------------+--------+----------------------------------------------------------------------------------------+ + +The ``evm.deployedBytecode`` object has the same structure as ``evm.bytecode``. +Additionally, it includes the ``immutableReferences`` suboject which maps AST IDs of immutables to their bytecode offset and size. +For example, two references to the immutable with AST ID 3, both 32 bytes, the first one at bytecode offset 42, +and the other at bytecode offset 80, is specified as: + +.. code-block:: javascript + + "immutableReferences": { + "3": [{ "start": 42, "length": 32 }, { "start": 80, "length": 32 }] + } + + + +Gas Estimates +^^^^^^^^^^^^^ + +The ``evm.gasEstimates`` object provides estimated gas costs for contract creation and function execution. + +- ``creation``: Gas estimates for contract deployment. Contains three string fields. + + - ``codeDepositCost``: Gas to store the runtime bytecode on-chain. + - ``executionCost``: Gas to execute the constructor + - ``totalCost``: Sum of both previous costs. + +- ``external``: Map of external/public function signatures to their estimated execution gas cost as a string. +- ``internal``: Map of internal function names to their estimated execution gas cost as a string. + +.. note:: + Values may be "infinite" if the compiler cannot determine a bound. + +Yul CFG +^^^^^^^ + +Experimental. +Yul CFG representation of the SSA form. + +Ethdebug +-------- + +Experimental. + +Example: TODO: cleanup. + .. code-block:: javascript { @@ -699,26 +1277,6 @@ Output Description "ethdebug": {/* ... */ } } - -Error Types -~~~~~~~~~~~ - -1. ``JSONError``: JSON input doesn't conform to the required format, e.g. input is not a JSON object, the language is not supported, etc. -2. ``IOError``: IO and import processing errors, such as unresolvable URL or hash mismatch in supplied sources. -3. ``ParserError``: Source code doesn't conform to the language rules. -4. ``DocstringParsingError``: The NatSpec tags in the comment block cannot be parsed. -5. ``SyntaxError``: Syntactical error, such as ``continue`` is used outside of a ``for`` loop. -6. ``DeclarationError``: Invalid, unresolvable or clashing identifier names. e.g. ``Identifier not found`` -7. ``TypeError``: Error within the type system, such as invalid type conversions, invalid assignments, etc. -8. ``UnimplementedFeatureError``: Feature is not supported by the compiler, but is expected to be supported in future versions. -9. ``InternalCompilerError``: Internal bug triggered in the compiler - this should be reported as an issue. -10. ``Exception``: Unknown failure during compilation - this should be reported as an issue. -11. ``CompilerError``: Invalid use of the compiler stack - this should be reported as an issue. -12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue. -13. ``YulException``: Error during Yul code generation - this should be reported as an issue. -14. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible. -15. ``Info``: Information that the compiler thinks the user might find useful, but is not dangerous and does not necessarily need to be addressed. - .. index:: ! Experimental mode, ! --experimental .. _experimental-mode: diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index d5cb27b6e1df..b2dc232b71cb 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() > 1 ? 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"