# Technical Documentation: argotorg/solidity

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/argotorg/solidity)

### Overview (`README.md`)

# The Solidity Contract-Oriented Programming Language

[](https://matrix.to/#/#ethereum_solidity:gitter.im)
[](https://gitter.im/ethereum/solidity)
[](https://forum.soliditylang.org/)
[](https://X.com/solidity_lang)
[](https://fosstodon.org/@solidity)

You can talk to us on Gitter and Matrix, tweet at us on X (previously Twitter) or create a new topic in the Solidity forum. Questions, feedback, and suggestions are welcome!

Solidity is a statically-typed, contract-oriented, high-level language for implementing smart contracts on the Ethereum platform.

For a good overview and starting point, please check out the official [Solidity Language Portal](https://soliditylang.org).

## Table of Contents

- [Background](#background)
- [Build and Install](#build-and-install)
- [Example](#example)
- [Documentation](#documentation)
- [Development](#development)
- [Maintainers](#maintainers)
- [License](#license)
- [Security](#security)

## Background

Solidity is a statically-typed curly-braces programming language designed for developing smart contracts
that run on the Ethereum Virtual Machine. Smart contracts are programs that are executed inside a peer-to-peer
network where nobody has special authority over the execution, and thus they allow anyone to implement tokens of value,
ownership, voting, and other kinds of logic.

When deploying contracts, you should use the latest released version of
Solidity. This is because breaking changes, as well as new features and bug fixes, are
introduced regularly. We currently use a 0.x version
number [to indicate this fast pace of change](https://semver.org/#spec-item-4).

## Build and Install

Instructions about how to build and install the Solidity compiler can be
found in the [Solidity documentation](https://docs.soliditylang.org/en/latest/installing-solidity.html#building-from-source).


## Example

A "Hello World" program in Solidity is of even less use than in other languages, but still:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;

contract HelloWorld {
    function helloWorld() external pure returns (string memory) {
        return "Hello, World!";
    }
}
```

To get started with Solidity, you can use [Remix](https://remix.ethereum.org/), which is a
browser-based IDE. Here are some example contracts:

1. [Voting](https://docs.soliditylang.org/en/latest/solidity-by-example.html#voting)
2. [Blind Auction](https://docs.soliditylang.org/en/latest/solidity-by-example.html#blind-auction)
3. [Safe remote purchase](https://docs.soliditylang.org/en/latest/solidity-by-example.html#safe-remote-purchase)
4. [Micropayment Channel](https://docs.soliditylang.org/en/latest/solidity-by-example.html#micropayment-channel)

## Documentation

The Solidity documentation is hosted using [Read the Docs](https://docs.soliditylang.org).

## Development

Solidity is still under development. Contributions are always welcome!
Please follow the
[Developer's Guide](https://docs.soliditylang.org/en/latest/contributing.html)
if you want to help.

You can find our current feature and bug priorities for forthcoming
releases in the [projects section](https://github.com/argotorg/solidity/projects).

## Maintainers
The Solidity programming language and compiler are open-source community projects governed by a core team.
The core team is part of the [Argot Collective](https://argot.org/), a non-profit that develops and maintains Solidity.
The project was originally started at and sponsored by the [Ethereum Foundation](https://ethereum.foundation/).

## License
Solidity is licensed under [GNU General Public License v3.0](LICENSE.txt).

Some third-party code has its [own licensing terms](cmake/templates/license.h.in).

## Security

The security policy may be [found here](SECURITY.md).

---

### Overview (`.circleci/README.md`)

## CircleCI integration

### Docker images

The docker images are built locally on the developer machine:

```sh
cd .circleci/docker/

docker build -t ethereum/solidity-buildpack-deps:ubuntu2404-<revision> -f Dockerfile.ubuntu2404 .
docker push ethereum/solidity-buildpack-deps:ubuntu2404-<revision>
```

The current revisions per docker image are stored in [circle ci pipeline parameters](https://github.com/CircleCI-Public/api-preview-docs/blob/master/docs/pipeline-parameters.md#pipeline-parameters) called `<image-desc>-docker-image-rev` (e.g., `ubuntu-2404-docker-image-rev`). Please update the value assigned to the parameter(s) corresponding to the docker image(s) being updated at the time of the update. Please verify that the value assigned to the parameter matches the revision part of the docker image tag (`<revision>` in the docker build/push snippet shown above). Otherwise, the docker image used by circle ci and the one actually pushed to docker hub will differ.

Once the docker image has been built and pushed to Docker Hub, you can find it at:

    https://hub.docker.com/r/ethereum/solidity-buildpack-deps:ubuntu2404-<revision>

where the image tag reflects the target OS and revision to build Solidity and run its tests on.

### Testing docker images locally

```sh
cd solidity
# Mounts your local solidity directory in docker container for testing
docker run -v `pwd`:/src/solidity -ti ethereum/solidity-buildpack-deps:ubuntu2404-<revision> /bin/bash
cd /src/solidity
<commands_to_test_build_with_new_docker_image>
```

---

### Overview (`docs/README.md`)

# Solidity Language Docs

## Local environment setup

1. Install python https://www.python.org/downloads/
1. Install sphinx (the tool used to generate the docs) https://www.sphinx-doc.org/en/master/usage/installation.html

Go to `/docs` and run `./docs.sh` to install dependencies and build the project:

```sh
cd docs
./docs.sh
```

That will output the generated htmls under _build/

## Serve environment

```py
python3 -m http.server -d _build/html --cgi 8080
```

Visit dev server at http://localhost:8080

---

### Overview (`libyul/optimiser/README.md`)

# Yul-Based Optimizer

The documentation of the Yul-based optimizer module has been moved to the official Solidity documentation.

Please refer to the [optimizer documentation](/docs/internals/optimizer.rst) for a description of all optimization stages and how to use the optimizer and to the [Yul documentation](/docs/yul.rst#optimization-step-sequence) for more information on the optimization step sequence and a list of abbreviations for each step.

---

### Overview (`test/compilationTests/README.md`)

This directory contains various Solidity contract source code files
that are compiled as part of the regular tests.

These contracts are externally contributed and their presence in this
repository does not make any statement about their quality or usefulness.

---

### Overview (`test/ethdebugSchemaTests/README.md`)

# ETHDebug schema tests

These tests validate Solidity's ETHDebug output against a pinned checkout of the upstream `ethdebug/format` JSON Schemas.

The schema checkout is a git submodule at `test/ethdebugSchemaTests/ethdebug-format`. Initialize it with:

```bash
git submodule update --init test/ethdebugSchemaTests/ethdebug-format
```

Run the tests with:

```bash
pytest test/ethdebugSchemaTests --solc-binary-path=build/solc/solc -v
```

The JSON inputs use `contentFile` entries to keep Solidity examples in regular
`.sol` fixture files under `sources/`. The pytest harness expands those entries
to Standard JSON `content` before invoking `solc`.

To update the schema version, bump the submodule commit and rerun this suite.

---

### Overview (`test/evmc/README.md`)

# EVMC

This is an import of [EVMC](https://github.com/ipsilon/evmc) version [12.0.0](https://github.com/ipsilon/evmc/releases/tag/v12.0.0).

Steps when upgrading:
- Copy all from [include/evmc](https://github.com/ipsilon/evmc/tree/master/include/evmc) to [test/evmc](https://github.com/argotorg/solidity/tree/develop/test/evmc)
    - Note that you should delete (or not copy in the first place) `tooling.hpp` and `instructions.h`.
- Copy [`loader.c`](https://github.com/ipsilon/evmc/blob/master/lib/loader/loader.c) to [test/evmc](https://github.com/argotorg/solidity/tree/develop/test/evmc)
- `MockedAccount.storage` in `mocked_host.hpp` should be changed to a `map` from `unordered_map` as ordering is important for fuzzing. You'll also need to include `<map>`.
    See [PR #11094](https://github.com/argotorg/solidity/pull/11094) for more details.

---

### Overview (`test/externalTests/README.md`)

## Solidity external tests
This directory contains scripts for compiling some of the popular open-source projects using the
current version of the compiler and running their test suites.

Since projects often do not use the latest compiler, we keep a fork of each of these projects
at https://github.com/solidity-external-tests/. If changes are needed to make a project work with the
latest version of the compiler, they are maintained as a branch on top of the upstream master branch.
This is especially important for testing our `breaking` branch because we can not realistically expect
external projects to be instantly compatible with a compiler version that has not been released yet.
Applying necessary changes ourselves gives us confidence that breaking changes are sane and that
these projects *can* be upgraded at all.

### Recommended workflow

#### Adding a new external project
1. If the upstream code cannot be compiled without modifications, create a fork of the repository
   in https://github.com/solidity-external-tests/.
2. In our fork, remove all the branches except for the main one (`master`, `develop`, `main`, etc).
    This branch is going to be always kept up to date with the upstream repository and should not
    contain any extra commits.
    - If the project is not up to date with the latest compiler version but has a branch that is,
        try to use that branch instead.
3. In our fork, create a new branch named after the main branch and the compiler version from our
 `develop` branch.
     E.g. if the latest Solidity version is 0.7.5 and the main branch of the external project
     is called `master`, create `master_070`. This is where we will be adding our own commits.
4. Create a script for compiling/testing the project and put it in `test/externalTests/` in the
    Solidity repository.
    - The script should apply workarounds necessary to make the project actually use the compiler
        binary it receives as a parameter and possibly add generic workarounds that should
        work across different versions of the upstream project.
    - Very specific workarounds that may easily break with every upstream change are better done as
        commits in the newly added branch in the fork instead.
5. List the script in `test/externalTests.sh`.
6. Add the script to CircleCI configuration. Make sure to add both a compilation-only run and one that
    also executes the test suite. If the latter takes a significant amount of time (say, more than
    15 minutes) make it run nightly rather than on every PR.
7. Make sure that tests pass both on `develop` and on `breaking`. If the compiler from `breaking`
    branch will not work without additional changes, add another branch, called after it in turn,
    and add necessary workarounds there. Continuing the example above, the new branch would be
    called `master_080` and should be rebased on top of `master_070`.
    - The fewer commits in these branches, the better. Ideally, any changes needed to make the compiler
        work should be submitted upstream and our scripts should be using the upstream repository
        directly.

#### Updating external projects for a PR that introduces breaking changes in the compiler
If a PR to our `breaking` branch introduces changes that will make an external project no longer
compile or pass its tests, the fork needs to be modified (or created if it does not yet exist):
- If a branch specific to the compiler version from `breaking` does not exist yet:
    1. Create the branch. It should be based on the version-specific branch used on `develop`.
    2. Make your PR modify the project script in `test/externalScripts/` to use the new branch.
    3. You are free to add any changes you need in the new branch since it will not interfere with
        tests on `breaking`.
    4. Work on your PR until it is approved and merged into `breaking`.
- If the branch already exists and our CI depends on it:
    1. If the external project after your changes can still work with `breaking` even without your PR or
        if you know that the PR is straightforward and will be merged immediately without interfering
        with tests on `breaking` for a significant amount of time, you can just push your modifications
        to the branch directly and skip straight to steps 4. and 6.
    2. Create a PR in the fork, targeting the existing version-specific branch.
    3. In your PR to `breaking`, modify the corresponding script in `test/externalScripts/` to
        use the branch from your PR in the fork.
    4. Work on your PR until it is approved and ready to merge.
    5. Merge the PR in the fork.
    6. Discard your changes to the script and merge your PR into `breaking`.

#### Pulling upstream changes into a fork
1. Pull changes directly into the main branch in the fork. This should be straightforward thanks to
    it not containing any of our customizations.
2. If the project has been updated to a newer Solidity version, abandon the current version-specific
    branch used on `develop` (but do not delete it) and create a new one corresponding to the newer
    version. Then update project script in `test/externalTests/` to use the new branch. E.g. if `develop` uses
    `master_050` and the project has been updated to use Solidity 0.7.3, create `master_070`.
3. Otherwise, rebase the current version-specific branch on the main branch of the fork. This may require
    tweaking some of the commits to apply our fixes in new places.
4. If we have a separate branch for `breaking`, rebase it on top of the one used on `develop`.

The above is the workflow to use when the update is straightforward and looks safe. In that case it is
fine to just modify the branches directly. If this is not the case, it is recommended to first perform the
operation on copies of these version-specific branches and test them by creating PRs on `develop` and
`breaking` to see if tests pass. The PRs should just modify project scripts in `test/externalScripts/`
to use the updated copies of the branches and can be discarded afterwards without being merged.

#### Changes needed after a breaking release of the compiler
When a non-backwards-compatible version becomes the most recent release, `breaking` branch
gets merged into `develop` which automatically results in a switch to the newer version-specific
branches if they exist. If no changes on our part were necessary, it is completely fine to keep using
e.g. the `master_060` of an external project in Solidity 0.8.x.

Since each project is handled separately, this approach may result in a mix of version-specific branches
between different external projects. For example, in one project we could have `master_050` on
both `develop` and `breaking` and in another `breaking` could use `master_080` while `develop` still
uses `master_060`.

---

### Overview (`test/formal/README.md`)

The Solidity compiler implements several [optimization rules](https://github.com/argotorg/solidity/blob/develop/libevmasm/RuleList.h).

This directory contains an effort to formally prove the correctness of those rules in:

- HOL with [EthIsabelle](https://github.com/ekpyron/eth-isabelle)
- FOL with SMT solvers using [Integers and BitVectors](http://smtlib.cs.uiowa.edu/theories.shtml)

---

### Overview (`test/fuzztest/README.md`)

# Property-based / fuzz tests

This directory holds **property-based / fuzz tests** built
on [Google FuzzTest](https://github.com/google/fuzztest) (vendored at `deps/fuzztest`).
Instead of asserting a fixed output for a fixed input, a property test states a property that must hold for all inputs
from a domain, and FuzzTest searches that domain for counterexamples.

## Options

Two CMake options control this (defined in `cmake/EthOptions.cmake`):

- `PROPERTY_BASED_TESTS` (default `OFF`) — master on/off switch. While it is `OFF`, `deps/fuzztest` is never added 
  to the build, so none of its transitive `FetchContent` dependencies are configured.
- `PROPERTY_BASED_TESTS_MODE` (default `unittest`, values `unittest` / `fuzzing`). Selects the run mode. Only
  meaningful when `PROPERTY_BASED_TESTS` is `ON`.
  - `unittest`: each `FUZZ_TEST` runs as an ordinary test case with a 1sec burst of random inputs.
  - `fuzzing`: coverage-guided fuzzing. Requires Clang.

## Configure

```sh
# unit-test mode (works with the default g++ build)
cmake -S . -B build-prop -G Ninja -DPROPERTY_BASED_TESTS=ON

# fuzzing mode (Clang required)
CC=clang CXX=clang++ cmake -S . -B build-fuzz -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/fuzztest.cmake
```

---

### Overview (`tools/yulPhaser/README.md`)

## yul-phaser
`yul-phaser` is an internal tool for finding good sequences of [optimisation steps](/libyul/optimiser/README.md) for Yul optimiser.

### How it works
The space of possible solutions to this problem (usually referred to as _phase-ordering problem_) is extremely large and there may even be no single sequence that produces optimal results for all possible programs.

The tool uses genetic algorithms to find sequences that result in better programs than others and to iteratively refine them.
The input is a set of one or more [Yul](/docs/yul.rst) programs and each sequence is applied to all of these programs.
Optimised programs are given numeric scores according to the selected metric.

Optimisation step sequences are presented in an abbreviated form - as strings of letters where each character represents one step.
There's a [table listing available abbreviations in the optimiser docs](/docs/yul.rst#optimization-step-sequence).

### How to use it
The application has sensible defaults for most parameters.
An invocation can be as simple as:

``` bash
tools/yul-phaser ../test/libyul/yulOptimizerTests/fullSuite/*.yul \
    --random-population 100
```

This assumes that you have a working copy of the Solidity repository and you're in the build directory within that working copy.

Run `yul-phaser --help` for a full list of available options.

#### Restarting from a previous state
`yul-phaser` can save the list of sequences found after each round:

``` bash
tools/yul-phaser *.yul        \
    --random-population   100 \
    --population-autosave /tmp/population.txt
```

If you stop the application, you can later use the file to continue the search from the point you left off:

``` bash
tools/yul-phaser *.yul                         \
    --population-from-file /tmp/population.txt \
    --population-autosave  /tmp/population.txt
```

#### Analysing a sequence
Apart from running the genetic algorithm, `yul-phaser` can also provide useful information about a particular sequence.

For example, to see the value of a particular metric for a given sequence and program run:
``` bash
tools/yul-phaser *.yul            \
    --show-initial-population     \
    --rounds            0         \
    --metric            code-size \
    --metric-aggregator sum       \
    --population        <your sequence>
```

You can also easily see program code after being optimised using that sequence:
``` bash
tools/yul-phaser *.yul                    \
    --rounds     0                        \
    --mode       print-optimised-programs \
    --population <your sequence>
```

#### Using output from Solidity compiler
`yul-phaser` can process the intermediate representation produced by `solc`:

``` bash
solc/solc <sol file> --ir --output-dir <output directory>
```

After running this command you'll find one or more .yul files in the output directory.
These files contain whole Yul objects rather than just raw Yul programs but `yul-phaser` is prepared to handle them too.

#### Using optimisation step sequences with the compiler
You can tell Yul optimiser to use a specific sequence for your code by passing `--yul-optimizations` option to `solc`:

``` bash
solc/solc <sol file> --optimize --ir-optimized --yul-optimizations <sequence>
```

### How to choose good parameters
Choosing good parameters for a genetic algorithm is not a trivial task but phaser's defaults are generally enough to find a sequence that gives results comparable or better than one hand-crafted by an experienced developer for a given set of programs.
The difficult part is providing a fairly representative set of input files.
If the files you give do not need certain optimisations the tool will find sequences that do not use these optimisations and perform badly for programs that could benefit from them.
If all the provided files greatly benefit from a specific optimisation, the sequence may not work well for programs that do not.

We have conducted [a set of rough experiments](https://github.com/argotorg/solidity/issues/7806#issuecomment-598644491) to evaluate some combinations of parameter values.
The conclusions were used to adjust the defaults but you might still benefit from some general observations:

1. The algorithm that performed the best was `GEWEP`.
2. Using longer sequences in the initial population yields better results. The algorithm is good at removing superfluous steps.
3. Preserving the top sequences from previous rounds improves results. Elite should contain at least a few individuals, especially when using the `classic` algorithm.
4. Do not set mutation/deletion/addition chance too high. It makes results worse because it destroys the good patterns preserved by crossover. Values around 1-5% seem to work best.
5. Keep the algorithm running for 1000 rounds or more. It usually finds good sequences faster than that but it can shorten them significantly if you let it run longer. This is especially important when starting with long sequences.

---

### Overview (`libsolidity/codegen/ir/README.md`)

# The Solidity to Yul Code Generator

This directory contains the new experimental code generator that
compiles Solidity to an intermediate representation in Yul
with EVM dialect.

The main semantic differences to the legacy code generator are the following:

- Arithmetic operations cause a failing assertion if the result is not in range.
- Resizing a storage array to a length larger than 2**64 causes a failing assertion.

---

### Overview (`scripts/docker/buildpack-deps/README.md`)

# buildpack-deps docker images

The `buildpack-deps` docker images are used to compile and test solidity within our CI.

## GitHub Workflow

The creation of the images is triggered by a single workflow, defined in `.github/workflows/buildpack-deps.yml`.
For each resulting `buildpack-deps` docker image a strategy is defined in the workflow file - the image variant.
The workflow gets triggered, if any Dockerfile defined in `scripts/docker/buildpack-deps/Dockerfile.*` was changed
within the PR.

### Versioning

The version of the docker images can be defined within the Dockerfile with `LABEL version`. A new docker image
will only be created and pushed, if the new version is incremented by `1` compared with the version of the Dockerfile
located in `develop`.

### Build, Test & Push

Note that the whole workflow - including all defined strategies (image variants) - will be triggered,
even if only a single Dockerfile was changed. The full workflow will only get executed, if the corresponding
Dockerfile was changed. The execution of workflows of unchanged Dockerfiles will not continue and just return success.
See `scripts/ci/docker_upgrade.sh`.

If the version check was successful, the docker image will be built using the Dockerfile located in
`scripts/docker/buildpack-deps/Dockerfile.*`.

The resulting docker image will be tested by executing the corresponding `scripts/ci/buildpack-deps_test_*` scripts.
Some of these scripts are symlinked to `scripts/ci/build.sh`, except the following two:
 * `buildpack-deps-ubuntu.clang.ossfuzz` => `scripts/ci/build_ossfuzz.sh`
 * `buildpack-deps_test_emscripten.sh` => `scripts/ci/build_emscripten.sh`

These scripts `scripts/ci/build.sh` and `scripts/ci/build_ossfuzz.sh` are also used by CircleCI, see `.circleci/config.yml`.

If the tests passed successfully, the docker image will get tagged by the version defined within the corresponding `Dockerfile`.
Finally, a comment will be added to the PR that contains the full repository, version and repository digest
of the freshly created docker image.

The files `.circleci/config.yml` and `scripts/build_emscripten.sh` need to be updated with the new hash posted in the comment.

---

### Overview (`test/compilationTests/MultiSigWallet/README.md`)

MultiSigWallet contracts, originally from

https://github.com/ConsenSys/MultiSigWallet

---

### Overview (`test/compilationTests/corion/README.md`)

CORION contracts, originally from

https://github.com/CORIONplatform/solidity

---

### Overview (`test/compilationTests/gnosis/README.md`)

Gnosis contracts, originally from

https://github.com/gnosis/gnosis-contracts

---

### Overview (`test/compilationTests/milestonetracker/README.md`)

Giveth milestone tracker, originally from

https://github.com/Giveth/milestonetracker/

---

### Overview (`test/tools/ossfuzz/README.md`)

## Intro

[oss-fuzz][1] is Google's fuzzing infrastructure that performs continuous fuzzing. What this means is that, each and every upstream commit is automatically fetched by the infrastructure and fuzzed on a daily basis.

## How to build fuzzers?

We have multiple fuzzers, some based on string input and others on protobuf input. To build them, please do the following:

- Create a local docker image from `Dockerfile.ubuntu.clang.ossfuzz` in the `.circleci/docker` sub-directory. Please note that this step is likely to take at least an hour to complete. Therefore, it is recommended to do it when you are away from the computer (and the computer is plugged to power since we do not want a battery drain).

```
$ cd .circleci/docker
$ docker build -t solidity-ossfuzz-local -f Dockerfile.ubuntu.clang.ossfuzz .
```

- Login to the docker container sourced from the image built in the previous step from the solidity parent directory

```
## Host
$ cd solidity
$ docker run -v `pwd`:/src/solidity -ti solidity-ossfuzz-local /bin/bash
## Docker shell
$ cd /src/solidity
```

- Run cmake and build fuzzer harnesses

```
## Docker shell
$ cd /src/solidity
$ rm -rf fuzzer-build && mkdir fuzzer-build && cd fuzzer-build
## Compile protobuf C++ bindings
$ protoc --proto_path=../test/tools/ossfuzz yulProto.proto --cpp_out=../test/tools/ossfuzz
$ protoc --proto_path=../test/tools/ossfuzz abiV2Proto.proto --cpp_out=../test/tools/ossfuzz
$ protoc --proto_path=../test/tools/ossfuzz solProto.proto --cpp_out=../test/tools/ossfuzz
## Run cmake
$ export CC=clang CXX=clang++
$ cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/libfuzzer.cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release} ..
$ make ossfuzz ossfuzz_proto ossfuzz_abiv2 -j
```

## Why the elaborate docker image to build fuzzers?

For the following reasons:

- Fuzzing binaries **must** link against libc++ and not libstdc++
  - This is [because][2] (1) MemorySanitizer (which flags uses of uninitialized memory) depends on libc++; and (2) because libc++ is instrumented (to check for memory and type errors) and libstdc++ not, the former may find more bugs.

- Linking against libc++ requires us to compile everything solidity depends on from source (and link these against libc++ as well)

- To reproduce the compiler versions used by upstream oss-fuzz bots, we need to reuse their docker image containing the said compiler versions

- Some fuzzers depend on libprotobuf, libprotobuf-mutator, libevmone etc. which may not be available locally; even if they were they might not be the right versions

## What is LIB\_FUZZING\_ENGINE?

oss-fuzz contains multiple fuzzer back-ends i.e., fuzzers. Each back-end may require different linker flags. oss-fuzz builder bot defines the correct linker flags via a bash environment variable called `LIB_FUZZING_ENGINE`.

For the solidity ossfuzz CI build, we use the libFuzzer back-end. This back-end requires us to manually set the `LIB_FUZZING_ENGINE` to `-fsanitize=fuzzer`.

## What does the ossfuzz directory contain?

To help oss-fuzz do this, we (as project maintainers) need to provide the following:

- test harnesses: C/C++ tests that define the `LLVMFuzzerTestOneInput` API. This determines what is to be fuzz tested.
- build infrastructure: (c)make targets per fuzzing binary. Fuzzing requires coverage and memory instrumentation of the code to be fuzzed.
- configuration files: These are files with the `.options` extension that are parsed by oss-fuzz. The only option that we use currently is the `dictionary` option that asks the fuzzing engines behind oss-fuzz to use the specified dictionary. The specified dictionary happens to be `solidity.dict.`

`solidity.dict` contains Solidity-specific syntactical tokens that are more likely to guide the fuzzer towards generating parseable and varied Solidity input.

To be consistent and aid better evaluation of the utility of the fuzzing dictionary, we stick to the following rules-of-thumb:
  - Full tokens such as `block.number` are preceded and followed by a whitespace
  - Incomplete tokens including function calls such as `msg.sender.send()` are abbreviated `.send(` to provide some leeway to the fuzzer to synthesize variants such as `address(this).send()`
  - Language keywords are suffixed by a whitespace with the exception of those that end a line of code such as `break;` and `continue;`

[1]: https://github.com/google/oss-fuzz
[2]: https://github.com/google/oss-fuzz/issues/1114#issuecomment-360660201

---

### Overview (`test/libsolidity/semanticTests/externalContracts/_prbmath/README.md`)

Imported from https://github.com/hifi-finance/prb-math/commit/62021c1abc3413f20d0bdc8f941cf9f21d5a7d2d

---

### Overview (`test/libsolidity/semanticTests/externalContracts/_stringutils/README.md`)

String utilities, originally from

https://github.com/Arachnid/solidity-stringutils

---

### 050 Breaking Changes (`docs/050-breaking-changes.rst`)

********************************
Solidity v0.5.0 Breaking Changes
********************************

This section highlights the main breaking changes introduced in Solidity
version 0.5.0, along with the reasoning behind the changes and how to update
affected code.
For the full list check
`the release changelog <https://github.com/argotorg/solidity/releases/tag/v0.5.0>`_.

.. note::
   Contracts compiled with Solidity v0.5.0 can still interface with contracts
   and even libraries compiled with older versions without recompiling or
   redeploying them.  Changing the interfaces to include data locations and
   visibility and mutability specifiers suffices. See the
   :ref:`Interoperability With Older Contracts <interoperability>` section below.

Semantic Only Changes
=====================

This section lists the changes that are semantic-only, thus potentially
hiding new and different behavior in existing code.

* Signed right shift now uses proper arithmetic shift, i.e. rounding towards
  negative infinity, instead of rounding towards zero.  Signed and unsigned
  shift will have dedicated opcodes in Constantinople, and are emulated by
  Solidity for the moment.

* The ``continue`` statement in a ``do...while`` loop now jumps to the
  condition, which is the common behavior in such cases. It used to jump to the
  loop body. Thus, if the condition is false, the loop terminates.

* The functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` do not
  pad anymore when given a single ``bytes`` parameter.

* Pure and view functions are now called using the opcode ``STATICCALL``
  instead of ``CALL`` if the EVM version is Byzantium or later. This
  disallows state changes on the EVM level.

* The ABI encoder now properly pads byte arrays and strings from calldata
  (``msg.data`` and external function parameters) when used in external
  function calls and in ``abi.encode``. For unpadded encoding, use
  ``abi.encodePacked``.

* The ABI decoder reverts in the beginning of functions and in
  ``abi.decode()`` if passed calldata is too short or points out of bounds.
  Note that dirty higher order bits are still simply ignored.

* Forward all available gas with external function calls starting from
  Tangerine Whistle.

Semantic and Syntactic Changes
==============================

This section highlights changes that affect syntax and semantics.

* The functions ``.call()``, ``.delegatecall()``, ``staticcall()``,
  ``keccak256()``, ``sha256()`` and ``ripemd160()`` now accept only a single
  ``bytes`` argument. Moreover, the argument is not padded. This was changed to
  make more explicit and clear how the arguments are concatenated. Change every
  ``.call()`` (and family) to a ``.call("")`` and every ``.call(signature, a,
  b, c)`` to use ``.call(abi.encodeWithSignature(signature, a, b, c))`` (the
  last one only works for value types).  Change every ``keccak256(a, b, c)`` to
  ``keccak256(abi.encodePacked(a, b, c))``. Even though it is not a breaking
  change, it is suggested that developers change
  ``x.call(bytes4(keccak256("f(uint256)")), a, b)`` to
  ``x.call(abi.encodeWithSignature("f(uint256)", a, b))``.

* Functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` now return
  ``(bool, bytes memory)`` to provide access to the return data.  Change
  ``bool success = otherContract.call("f")`` to ``(bool success, bytes memory
  data) = otherContract.call("f")``.

* Solidity now implements C99-style scoping rules for function local
  variables, that is, variables can only be used after they have been
  declared and only in the same or nested scopes. Variables declared in the
  initialization block of a ``for`` loop are valid at any point inside the
  loop.

Explicitness Requirements
=========================

This section lists changes where the code now needs to be more explicit.
For most of the topics the compiler will provide suggestions.

* Explicit function visibility is now mandatory.  Add ``public`` to every
  function and constructor, and ``external`` to every fallback or interface
  function that does not specify its visibility already.

* Explicit data location for all variables of struct, array or mapping types is
  now mandatory. This is also applied to function parameters and return
  variables.  For example, change ``uint[] x = z`` to ``uint[] storage x =
  z``, and ``function f(uint[][] x)`` to ``function f(uint[][] memory x)``
  where ``memory`` is the data location and might be replaced by ``storage`` or
  ``calldata`` accordingly.  Note that ``external`` functions require
  parameters with a data location of ``calldata``.

* Contract types do not include ``address`` members anymore in
  order to separate the namespaces.  Therefore, it is now necessary to
  explicitly convert values of contract type to addresses before using an
  ``address`` member.  Example: if ``c`` is a contract, change
  ``c.transfer(...)`` to ``address(c).transfer(...)``,
  and ``c.balance`` to ``address(c).balance``.

* Explicit conversions between unrelated contract types are now disallowed. You can only
  convert from a contract type to one of its base or ancestor types. If you are sure that
  a contract is compatible with the contract type you want to convert to, although it does not
  inherit from it, you can work around this by converting to ``address`` first.
  Example: if ``A`` and ``B`` are contract types, ``B`` does not inherit from ``A`` and
  ``b`` is a contract of type ``B``, you can still convert ``b`` to type ``A`` using ``A(address(b))``.
  Note that you still need to watch out for matching payable fallback functions, as explained below.

* The ``address`` type  was split into ``address`` and ``address payable``,
  where only ``address payable`` provides the ``transfer`` function.  An
  ``address payable`` can be directly converted to an ``address``, but the
  other way around is not allowed. Converting ``address`` to ``address
  payable`` is possible via conversion through ``uint160``. If ``c`` is a
  contract, ``address(c)`` results in ``address payable`` only if ``c`` has a
  payable fallback function. If you use the :ref:`withdraw pattern<withdrawal_pattern>`,
  you most likely do not have to change your code because ``transfer``
  is only used on ``msg.sender`` instead of stored addresses and ``msg.sender``
  is an ``address payable``.

* Conversions between ``bytesX`` and ``uintY`` of different size are now
  disallowed due to ``bytesX`` padding on the right and ``uintY`` padding on
  the left which may cause unexpected conversion results.  The size must now be
  adjusted within the type before the conversion.  For example, you can convert
  a ``bytes4`` (4 bytes) to a ``uint64`` (8 bytes) by first converting the
  ``bytes4`` variable to ``bytes8`` and then to ``uint64``. You get the
  opposite padding when converting through ``uint32``. Before v0.5.0 any
  conversion between ``bytesX`` and ``uintY`` would go through ``uint8X``. For
  example ``uint8(bytes3(0x291807))`` would be converted to ``uint8(uint24(bytes3(0x291807)))``
  (the result is ``0x07``).

* Using ``msg.value`` in non-payable functions (or introducing it via a
  modifier) is disallowed as a security feature. Turn the function into
  ``payable`` or create a new internal function for the program logic that
  uses ``msg.value``.

* For clarity reasons, the command-line interface now requires ``-`` if the
  standard input is used as source.

Deprecated Elements
===================

This section lists changes that deprecate prior features or syntax.  Note that
many of these changes were already enabled in the experimental mode
``v0.5.0``.

Command-line and JSON Interfaces
--------------------------------

* The command-line option ``--formal`` (used to generate Why3 output for
  further formal verification) was deprecated and is now removed.  A new
  formal verification module, the SMTChecker, is enabled via ``pragma
  experimental SMTChecker;``.

* The command-line option ``--julia`` was renamed to ``--yul`` due to the
  renaming of the intermediate language ``Julia`` to ``Yul``.

* The ``--clone-bin`` and ``--combined-json clone-bin`` command-line options
  were removed.

* Remappings with empty prefix are disallowed.

* The JSON AST fields ``constant`` and ``payable`` were removed. The
  information is now present in the ``stateMutability`` field.

* The JSON AST field ``isConstructor`` of the ``FunctionDefinition``
  node was replaced by a field called ``kind`` which can have the
  value ``"constructor"``, ``"fallback"`` or ``"function"``.

* In unlinked binary hex files, library address placeholders are now
  the first 36 hex characters of the keccak256 hash of the fully qualified
  library name, surrounded by ``$...$``. Previously,
  just the fully qualified library name was used.
  This reduces the chances of collisions, especially when long paths are used.
  Binary files now also contain a list of mappings from these placeholders
  to the fully qualified names.

Constructors
------------

* Constructors must now be defined using the ``constructor`` keyword.

* Calling base constructors without parentheses is now disallowed.

* Specifying base constructor arguments multiple times in the same inheritance
  hierarchy is now disallowed.

* Calling a constructor with arguments but with wrong argument count is now
  disallowed.  If you only want to specify an inheritance relation without
  giving arguments, do not provide parentheses at all.

Functions
---------

* Function ``callcode`` is now disallowed (in favor of ``delegatecall``). It
  is still possible to use it via inline assembly.

* ``suicide`` is now disallowed (in favor of ``selfdestruct``).

* ``sha3`` is now disallowed (in favor of ``keccak256``).

* ``throw`` is now disallowed (in favor of ``revert``, ``require`` and
  ``assert``).

Conversions
-----------

* Explicit and implicit conversions from decimal literals to ``bytesXX`` types
  is now disallowed.

* Explicit and implicit conversions from hex literals to ``bytesXX`` types
  of different size is now disallowed.

Literals and Suffixes
---------------------

* The unit denomination ``years`` is now disallowed due to complications and
  confusions about leap years.

* Trailing dots that are not followed by a number are now disallowed.

* Combining hex numbers with unit denominations (e.g. ``0x1e wei``) is now
  disallowed.

* The prefix ``0X`` for hex numbers is disallowed, only ``0x`` is possible.

Variables
---------

* Declaring empty structs is now disallowed for clarity.

* The ``var`` keyword is now disallowed to favor explicitness.

* Assignments between tuples with different number of components is now
  disallowed.

* Values for constants that are not compile-time constants are disallowed.

* Multi-variable declarations with mismatching number of values are now
  disallowed.

* Uninitialized storage variables are now disallowed.

* Empty tuple components are now disallowed.

* Detecting cyclic dependencies in variables and structs is limited in
  recursion to 256.

* Fixed-size arrays with a length of zero are now disallowed.

Syntax
------

* Using ``constant`` as function state mutability modifier is now disallowed.

* Boolean expressions cannot use arithmetic operations.

* The unary ``+`` operator is now disallowed.

* Literals cannot anymore be used with ``abi.encodePacked`` without prior
  conversion to an explicit type.

* Empty return statements for functions with one or more return values are now
  disallowed.

* The "loose assembly" syntax is now disallowed entirely, that is, jump labels,
  jumps and non-functional instructions cannot be used anymore. Use the new
  ``while``, ``switch`` and ``if`` constructs instead.

* Functions without implementation cannot use modifiers anymore.

* Function types with named return values are now disallowed.

* Single statement variable declarations inside if/while/for bodies that are
  not blocks are now disallowed.

* New keywords: ``calldata`` and ``constructor``.

* New reserved keywords: ``alias``, ``apply``, ``auto``, ``copyof``,
  ``define``, ``immutable``, ``implements``, ``macro``, ``mutable``,
  ``override``, ``partial``, ``promise``, ``reference``, ``sealed``,
  ``sizeof``, ``supports``, ``typedef`` and ``unchecked``.

.. _interoperability:

Interoperability With Older Contracts
=====================================

It is still possible to interface with contracts written for Solidity versions prior to
v0.5.0 (or the other way around) by defining interfaces for them.
Consider you have the following pre-0.5.0 contract already deployed:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.4.25;
    // This will report a warning until version 0.4.25 of the compiler
    // This will not compile after 0.5.0
    contract OldContract {
        function someOldFunction(uint8 a) {
            //...
        }
        function anotherOldFunction() constant returns (bool) {
            //...
        }
        // ...
    }

This will no longer compile with Solidity v0.5.0. However, you can define a compatible interface for it:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.5.0 <0.9.0;
    interface OldContract {
        function someOldFunction(uint8 a) external;
        function anotherOldFunction() external returns (bool);
    }

Note that we did not declare ``anotherOldFunction`` to be ``view``, despite it being declared ``constant`` in the original
contract. This is due to the fact that starting with Solidity v0.5.0 ``staticcall`` is used to call ``view`` functions.
Prior to v0.5.0 the ``constant`` keyword was not enforced, so calling a function declared ``constant`` with ``staticcall``
may still revert, since the ``constant`` function may still attempt to modify storage. Consequently, when defining an
interface for older contracts, you should only use ``view`` in place of ``constant`` in case you are absolutely sure that
the function will work with ``staticcall``.

Given the interface defined above, you can now easily use the already deployed pre-0.5.0 contract:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.5.0 <0.9.0;

    interface OldContract {
        function someOldFunction(uint8 a) external;
        function anotherOldFunction() external returns (bool);
    }

    contract NewContract {
        function doSomething(OldContract a) public returns (bool) {
            a.someOldFunction(0x42);
            return a.anotherOldFunction();
        }
    }

Similarly, pre-0.5.0 libraries can be used by defining the functions of the library without implementation and
supplying the address of the pre-0.5.0 library during linking (see :ref:`commandline-compiler` for how to use the
commandline compiler for linking):

.. code-block:: solidity

    // This will not compile after 0.6.0
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.5.0;

    library OldLibrary {
        function someFunction(uint8 a) public returns(bool);
    }

    contract NewContract {
        function f(uint8 a) public returns (bool) {
            return OldLibrary.someFunction(a);
        }
    }


Example
=======

The following example shows a contract and its updated version for Solidity
v0.5.0 with some of the changes listed in this section.

Old version:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.4.25;
    // This will not compile after 0.5.0

    contract OtherContract {
        uint x;
        function f(uint y) external {
            x = y;
        }
        function() payable external {}
    }

    contract Old {
        OtherContract other;
        uint myNumber;

        // Function mutability not provided, not an error.
        function someInteger() internal returns (uint) { return 2; }

        // Function visibility not provided, not an error.
        // Function mutability not provided, not an error.
        function f(uint x) returns (bytes) {
            // Var is fine in this version.
            var z = someInteger();
            x += z;
            // Throw is fine in this version.
            if (x > 100)
                throw;
            bytes memory b = new bytes(x);
            y = -3 >> 1;
            // y == -1 (wrong, should be -2)
            do {
                x += 1;
                if (x > 10) continue;
                // 'Continue' causes an infinite loop.
            } while (x < 11);
            // Call returns only a Bool.
            bool success = address(other).call("f");
            if (!success)
                revert();
            else {
                // Local variables could be declared after their use.
                int y;
            }
            return b;
        }

        // No need for an explicit data location for 'arr'
        function g(uint[] arr, bytes8 x, OtherContract otherContract) public {
            otherContract.transfer(1 ether);

            // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes),
            // the first 4 bytes of x will be lost. This might lead to
            // unexpected behavior since bytesX are right padded.
            uint32 y = uint32(x);
            myNumber += y + msg.value;
        }
    }

New version:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.5.0;
    // This will not compile after 0.6.0

    contract OtherContract {
        uint x;
        function f(uint y) external {
            x = y;
        }
        function() payable external {}
    }

    contract New {
        OtherContract other;
        uint myNumber;

        // Function mutability must be specified.
        function someInteger() internal pure returns (uint) { return 2; }

        // Function visibility must be specified.
        // Function mutability must be specified.
        function f(uint x) public returns (bytes memory) {
            // The type must now be explicitly given.
            uint z = someInteger();
            x += z;
            // Throw is now disallowed.
            require(x <= 100);
            int y = -3 >> 1;
            require(y == -2);
            do {
                x += 1;
                if (x > 10) continue;
                // 'Continue' jumps to the condition below.
            } while (x < 11);

            // Call returns (bool, bytes).
            // Data location must be specified.
            (bool success, bytes memory data) = address(other).call("f");
            if (!success)
                revert();
            return data;
        }

        using AddressMakePayable for address;
        // Data location for 'arr' must be specified
        function g(uint[] memory /* arr */, bytes8 x, OtherContract otherContract, address unknownContract) public payable {
            // 'otherContract.transfer' is not provided.
            // Since the code of 'OtherContract' is known and has the fallback
            // function, address(otherContract) has type 'address payable'.
            address(otherContract).transfer(1 ether);

            // 'unknownContract.transfer' is not provided.
            // 'address(unknownContract).transfer' is not provided
            // since 'address(unknownContract)' is not 'address payable'.
            // If the function takes an 'address' which you want to send
            // funds to, you can convert it to 'address payable' via 'uint160'.
            // Note: This is not recommended and the explicit type
            // 'address payable' should be used whenever possible.
            // To increase clarity, we suggest the use of a library for
            // the conversion (provided after the contract in this example).
            address payable addr = unknownContract.makePayable();
            require(addr.send(1 ether));

            // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes),
            // the conversion is not allowed.
            // We need to convert to a common size first:
            bytes4 x4 = bytes4(x); // Padding happens on the right
            uint32 y = uint32(x4); // Conversion is consistent
            // 'msg.value' cannot be used in a 'non-payable' function.
            // We need to make the function payable
            myNumber += y + msg.value;
        }
    }

    // We can define a library for explicitly converting ``address``
    // to ``address payable`` as a workaround.
    library AddressMakePayable {
        function makePayable(address x) internal pure returns (address payable) {
            return address(uint160(x));
        }
    }

---

### 060 Breaking Changes (`docs/060-breaking-changes.rst`)

********************************
Solidity v0.6.0 Breaking Changes
********************************

This section highlights the main breaking changes introduced in Solidity
version 0.6.0, along with the reasoning behind the changes and how to update
affected code.
For the full list check
`the release changelog <https://github.com/argotorg/solidity/releases/tag/v0.6.0>`_.


Changes the Compiler Might not Warn About
=========================================

This section lists changes where the behavior of your code might
change without the compiler telling you about it.

* The resulting type of an exponentiation is the type of the base. It used to be the smallest type
  that can hold both the type of the base and the type of the exponent, as with symmetric
  operations. Additionally, signed types are allowed for the base of the exponentiation.


Explicitness Requirements
=========================

This section lists changes where the code now needs to be more explicit,
but the semantics do not change.
For most of the topics the compiler will provide suggestions.

* Functions can now only be overridden when they are either marked with the
  ``virtual`` keyword or defined in an interface. Functions without
  implementation outside an interface have to be marked ``virtual``.
  When overriding a function or modifier, the new keyword ``override``
  must be used. When overriding a function or modifier defined in multiple
  parallel bases, all bases must be listed in parentheses after the keyword
  like so: ``override(Base1, Base2)``.

* Member-access to ``length`` of arrays is now always read-only, even for storage arrays. It is no
  longer possible to resize storage arrays by assigning a new value to their length. Use ``push()``,
  ``push(value)`` or ``pop()`` instead, or assign a full array, which will of course overwrite the existing content.
  The reason behind this is to prevent storage collisions of gigantic
  storage arrays.

* The new keyword ``abstract`` can be used to mark contracts as abstract. It has to be used
  if a contract does not implement all its functions. Abstract contracts cannot be created using the ``new`` operator,
  and it is not possible to generate bytecode for them during compilation.

* Libraries have to implement all their functions, not only the internal ones.

* The names of variables declared in inline assembly may no longer end in ``_slot`` or ``_offset``.

* Variable declarations in inline assembly may no longer shadow any declaration outside the inline assembly block.
  If the name contains a dot, its prefix up to the dot may not conflict with any declaration outside the inline
  assembly block.

* In inline assembly, opcodes that do not take arguments are now represented as "built-in functions" instead of standalone identifiers. So ``gas`` is now ``gas()``.

* State variable shadowing is now disallowed.  A derived contract can only
  declare a state variable ``x``, if there is no visible state variable with
  the same name in any of its bases.


Semantic and Syntactic Changes
==============================

This section lists changes where you have to modify your code
and it does something else afterwards.

* Conversions from external function types to ``address`` are now disallowed. Instead external
  function types have a member called ``address``, similar to the existing ``selector`` member.

* The function ``push(value)`` for dynamic storage arrays does not return the new length anymore (it returns nothing).

* The unnamed function commonly referred to as "fallback function" was split up into a new
  fallback function that is defined using the ``fallback`` keyword and a receive ether function
  defined using the ``receive`` keyword.

  * If present, the receive ether function is called whenever the call data is empty (whether
    or not ether is received). This function is implicitly ``payable``.

  * The new fallback function is called when no other function matches (if the receive ether
    function does not exist then this includes calls with empty call data).
    You can make this function ``payable`` or not. If it is not ``payable`` then transactions
    not matching any other function which send value will revert. You should only need to
    implement the new fallback function if you are following an upgrade or proxy pattern.


New Features
============

This section lists things that were not possible prior to Solidity 0.6.0
or were more difficult to achieve.

* The :ref:`try/catch statement <try-catch>` allows you to react on failed external calls.
* ``struct`` and ``enum`` types can be declared at file level.
* Array slices can be used for calldata arrays, for example ``abi.decode(msg.data[4:], (uint, uint))``
  is a low-level way to decode the function call payload.
* Natspec supports multiple return parameters in developer documentation, enforcing the same naming check as ``@param``.
* Yul and Inline Assembly have a new statement called ``leave`` that exits the current function.
* Conversions from ``address`` to ``address payable`` are now possible via ``payable(x)``, where
  ``x`` must be of type ``address``.


Interface Changes
=================

This section lists changes that are unrelated to the language itself, but that have an effect on the interfaces of
the compiler. These may change the way how you use the compiler on the command-line, how you use its programmable
interface, or how you analyze the output produced by it.

New Error Reporter
~~~~~~~~~~~~~~~~~~

A new error reporter was introduced, which aims at producing more accessible error messages on the command-line.
It is enabled by default, but passing ``--old-reporter`` falls back to the deprecated old error reporter.

Metadata Hash Options
~~~~~~~~~~~~~~~~~~~~~

The compiler now appends the `IPFS <https://ipfs.io/>`_ hash of the metadata file to the end of the bytecode by default
(for details, see documentation on :doc:`contract metadata <metadata>`). Before 0.6.0, the compiler appended the
`Swarm <https://www.ethswarm.org/>`_ hash by default, and in order to still support this behavior,
the new command-line option ``--metadata-hash`` was introduced. It allows you to select the hash to be produced and
appended, by passing either ``ipfs`` or ``swarm`` as value to the ``--metadata-hash`` command-line option.
Passing the value ``none`` completely removes the hash.

These changes can also be used via the :ref:`Standard JSON Interface<compiler-api>` and effect the metadata JSON generated by the compiler.

The recommended way to read the metadata is to read the last two bytes to determine the length of the CBOR encoding
and perform a proper decoding on that data block as explained in the :ref:`metadata section<encoding-of-the-metadata-hash-in-the-bytecode>`.

Yul Optimizer
~~~~~~~~~~~~~

Together with the legacy bytecode optimizer, the :doc:`Yul <yul>` optimizer is now enabled by default when you call the compiler
with ``--optimize``. It can be disabled by calling the compiler with ``--no-optimize-yul``.
This mostly affects code that uses ABI coder v2.

C API Changes
~~~~~~~~~~~~~

The client code that uses the C API of ``libsolc`` is now in control of the memory used by the compiler. To make
this change consistent, ``solidity_free`` was renamed to ``solidity_reset``, the functions ``solidity_alloc`` and
``solidity_free`` were added and ``solidity_compile`` now returns a string that must be explicitly freed via
``solidity_free()``.


How to update your code
=======================

This section gives detailed instructions on how to update prior code for every breaking change.

* Change ``address(f)`` to ``f.address`` for ``f`` being of external function type.

* Replace ``function () external [payable] { ... }`` by either ``receive() external payable { ... }``,
  ``fallback() external [payable] { ... }`` or both. Prefer
  using a ``receive`` function only, whenever possible.

* Change ``uint length = array.push(value)`` to ``array.push(value);``. The new length can be
  accessed via ``array.length``.

* Change ``array.length++`` to ``array.push()`` to increase, and use ``pop()`` to decrease
  the length of a storage array.

* For every named return parameter in a function's ``@dev`` documentation define a ``@return``
  entry which contains the parameter's name as the first word. E.g. if you have function ``f()`` defined
  like ``function f() public returns (uint value)`` and a ``@dev`` annotating it, document its return
  parameters like so: ``@return value The return value.``. You can mix named and un-named return parameters
  documentation so long as the notices are in the order they appear in the tuple return type.

* Choose unique identifiers for variable declarations in inline assembly that do not conflict
  with declarations outside the inline assembly block.

* Add ``virtual`` to every non-interface function you intend to override. Add ``virtual``
  to all functions without implementation outside interfaces. For single inheritance, add
  ``override`` to every overriding function. For multiple inheritance, add ``override(A, B, ..)``,
  where you list all contracts that define the overridden function in the parentheses. When
  multiple bases define the same function, the inheriting contract must override all conflicting functions.

* In inline assembly, add ``()`` to all opcodes that do not otherwise accept an argument.
  For example, change ``pc`` to ``pc()``, and ``gas`` to ``gas()``.

---

### 070 Breaking Changes (`docs/070-breaking-changes.rst`)

********************************
Solidity v0.7.0 Breaking Changes
********************************

This section highlights the main breaking changes introduced in Solidity
version 0.7.0, along with the reasoning behind the changes and how to update
affected code.
For the full list check
`the release changelog <https://github.com/argotorg/solidity/releases/tag/v0.7.0>`_.


Silent Changes of the Semantics
===============================

* Exponentiation and shifts of literals by non-literals (e.g. ``1 << x`` or ``2 ** x``)
  will always use either the type ``uint256`` (for non-negative literals) or
  ``int256`` (for negative literals) to perform the operation.
  Previously, the operation was performed in the type of the shift amount / the
  exponent which can be misleading.


Changes to the Syntax
=====================

* In external function and contract creation calls, Ether and gas is now specified using a new syntax:
  ``x.f{gas: 10000, value: 2 ether}(arg1, arg2)``.
  The old syntax -- ``x.f.gas(10000).value(2 ether)(arg1, arg2)`` -- will cause an error.

* The global variable ``now`` is deprecated, ``block.timestamp`` should be used instead.
  The single identifier ``now`` is too generic for a global variable and could give the impression
  that it changes during transaction processing, whereas ``block.timestamp`` correctly
  reflects the fact that it is just a property of the block.

* NatSpec comments on variables are only allowed for public state variables and not
  for local or internal variables.

* The token ``gwei`` is a keyword now (used to specify, e.g. ``2 gwei`` as a number)
  and cannot be used as an identifier.

* String literals now can only contain printable ASCII characters and this also includes a variety of
  escape sequences, such as hexadecimal (``\xff``) and unicode escapes (``\u20ac``).

* Unicode string literals are supported now to accommodate valid UTF-8 sequences. They are identified
  with the ``unicode`` prefix: ``unicode"Hello 😃"``.

* State Mutability: The state mutability of functions can now be restricted during inheritance:
  Functions with default state mutability can be overridden by ``pure`` and ``view`` functions
  while ``view`` functions can be overridden by ``pure`` functions.
  At the same time, public state variables are considered ``view`` and even ``pure``
  if they are constants.



Inline Assembly
---------------

* Disallow ``.`` in user-defined function and variable names in inline assembly.
  It is still valid if you use Solidity in Yul-only mode.

* Slot and offset of storage pointer variable ``x`` are accessed via ``x.slot``
  and ``x.offset`` instead of ``x_slot`` and ``x_offset``.

Removal of Unused or Unsafe Features
====================================

Mappings outside Storage
------------------------

* If a struct or array contains a mapping, it can only be used in storage.
  Previously, mapping members were silently skipped in memory, which
  is confusing and error-prone.

* Assignments to structs or arrays in storage does not work if they contain
  mappings.
  Previously, mappings were silently skipped during the copy operation, which
  is misleading and error-prone.

Functions and Events
--------------------

* Visibility (``public`` / ``internal``) is not needed for constructors anymore:
  To prevent a contract from being created, it can be marked ``abstract``.
  This makes the visibility concept for constructors obsolete.

* Type Checker: Disallow ``virtual`` for library functions:
  Since libraries cannot be inherited from, library functions should not be virtual.

* Multiple events with the same name and parameter types in the same
  inheritance hierarchy are disallowed.

* ``using A for B`` only affects the contract it is mentioned in.
  Previously, the effect was inherited. Now, you have to repeat the ``using``
  statement in all derived contracts that make use of the feature.

Expressions
-----------

* Shifts by signed types are disallowed.
  Previously, shifts by negative amounts were allowed, but reverted at runtime.

* The ``finney`` and ``szabo`` denominations are removed.
  They are rarely used and do not make the actual amount readily visible. Instead, explicit
  values like ``1e20`` or the very common ``gwei`` can be used.

Declarations
------------

* The keyword ``var`` cannot be used anymore.
  Previously, this keyword would parse but result in a type error and
  a suggestion about which type to use. Now, it results in a parser error.

Interface Changes
=================

* JSON AST: Mark hex string literals with ``kind: "hexString"``.
* JSON AST: Members with value ``null`` are removed from JSON output.
* NatSpec: Constructors and functions have consistent userdoc output.


How to update your code
=======================

This section gives detailed instructions on how to update prior code for every breaking change.

* Change ``x.f.value(...)()`` to ``x.f{value: ...}()``. Similarly ``(new C).value(...)()`` to
  ``new C{value: ...}()`` and ``x.f.gas(...).value(...)()`` to ``x.f{gas: ..., value: ...}()``.
* Change ``now`` to ``block.timestamp``.
* Change types of right operand in shift operators to unsigned types. For example change ``x >> (256 - y)`` to
  ``x >> uint(256 - y)``.
* Repeat the ``using A for B`` statements in all derived contracts if needed.
* Remove the ``public`` keyword from every constructor.
* Remove the ``internal`` keyword from every constructor and add ``abstract`` to the contract (if not already present).
* Change ``_slot`` and ``_offset`` suffixes in inline assembly to ``.slot`` and ``.offset``, respectively.

---

### 080 Breaking Changes (`docs/080-breaking-changes.rst`)

********************************
Solidity v0.8.0 Breaking Changes
********************************

This section highlights the main breaking changes introduced in Solidity
version 0.8.0.
For the full list check
`the release changelog <https://github.com/argotorg/solidity/releases/tag/v0.8.0>`_.

Silent Changes of the Semantics
===============================

This section lists changes where existing code changes its behavior without
the compiler notifying you about it.

* Arithmetic operations revert on underflow and overflow. You can use ``unchecked { ... }`` to use
  the previous wrapping behavior.

  Checks for overflow are very common, so we made them the default to increase readability of code,
  even if it comes at a slight increase of gas costs.

* ABI coder v2 is activated by default.

  You can choose to use the old behavior using ``pragma abicoder v1;``.
  The pragma ``pragma experimental ABIEncoderV2;`` is still valid, but it is deprecated and has no effect.
  If you want to be explicit, please use ``pragma abicoder v2;`` instead.

  Note that ABI coder v2 supports more types than v1 and performs more sanity checks on the inputs.
  ABI coder v2 makes some function calls more expensive and it can also make contract calls
  revert that did not revert with ABI coder v1 when they contain data that does not conform to the
  parameter types.

* Exponentiation is right associative, i.e., the expression ``a**b**c`` is parsed as ``a**(b**c)``.
  Before 0.8.0, it was parsed as ``(a**b)**c``.

  This is the common way to parse the exponentiation operator.

* Failing assertions and other internal checks like division by zero or arithmetic overflow do
  not use the invalid opcode but instead the revert opcode.
  More specifically, they will use error data equal to a function call to ``Panic(uint256)`` with an error code specific
  to the circumstances.

  This will save gas on errors while it still allows static analysis tools to distinguish
  these situations from a revert on invalid input, like a failing ``require``.

* If a byte array in storage is accessed whose length is encoded incorrectly, a panic is caused.
  A contract cannot get into this situation unless inline assembly is used to modify the raw representation of storage byte arrays.

* If constants are used in array length expressions, previous versions of Solidity would use arbitrary precision
  in all branches of the evaluation tree. Now, if constant variables are used as intermediate expressions,
  their values will be properly rounded in the same way as when they are used in run-time expressions.

* The type ``byte`` has been removed. It was an alias of ``bytes1``.

New Restrictions
================

This section lists changes that might cause existing contracts to not compile anymore.

* There are new restrictions related to explicit conversions of literals. The previous behavior in
  the following cases was likely ambiguous:

  1. Explicit conversions from negative literals and literals larger than ``type(uint160).max`` to
     ``address`` are disallowed.
  2. Explicit conversions between literals and an integer type ``T`` are only allowed if the literal
     lies between ``type(T).min`` and ``type(T).max``. In particular, replace usages of ``uint(-1)``
     with ``type(uint).max``.
  3. Explicit conversions between literals and enums are only allowed if the literal can
     represent a value in the enum.
  4. Explicit conversions between literals and ``address`` type (e.g. ``address(literal)``) have the
     type ``address`` instead of ``address payable``. One can get a payable address type by using an
     explicit conversion, i.e., ``payable(literal)``.

* :ref:`Address literals<address_literals>` have the type ``address`` instead of ``address
  payable``. They can be converted to ``address payable`` by using an explicit conversion, e.g.
  ``payable(0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF)``.

* There are new restrictions on explicit type conversions. The conversion is only allowed when there
  is at most one change in sign, width or type-category (``int``, ``address``, ``bytesNN``, etc.).
  To perform multiple changes, use multiple conversions.

  Let us use the notation ``T(S)`` to denote the explicit conversion ``T(x)``, where, ``T`` and
  ``S`` are types, and ``x`` is any arbitrary variable of type ``S``. An example of such a
  disallowed conversion would be ``uint16(int8)`` since it changes both width (8 bits to 16 bits)
  and sign (signed integer to unsigned integer). In order to do the conversion, one has to go
  through an intermediate type. In the previous example, this would be ``uint16(uint8(int8))`` or
  ``uint16(int16(int8))``. Note that the two ways to convert will produce different results e.g.,
  for ``-1``. The following are some examples of conversions that are disallowed by this rule.

  - ``address(uint)`` and ``uint(address)``: converting both type-category and width. Replace this by
    ``address(uint160(uint))`` and ``uint(uint160(address))`` respectively.
  - ``payable(uint160)``, ``payable(bytes20)`` and ``payable(integer-literal)``: converting both
    type-category and state-mutability. Replace this by ``payable(address(uint160))``,
    ``payable(address(bytes20))`` and ``payable(address(integer-literal))`` respectively. Note that
    ``payable(0)`` is valid and is an exception to the rule.
  - ``int80(bytes10)`` and ``bytes10(int80)``: converting both type-category and sign. Replace this by
    ``int80(uint80(bytes10))`` and ``bytes10(uint80(int80)`` respectively.
  - ``Contract(uint)``: converting both type-category and width. Replace this by
    ``Contract(address(uint160(uint)))``.

  These conversions were disallowed to avoid ambiguity. For example, in the expression ``uint16 x =
  uint16(int8(-1))``, the value of ``x`` would depend on whether the sign or the width conversion
  was applied first.

* Function call options can only be given once, i.e. ``c.f{gas: 10000}{value: 1}()`` is invalid and has to be changed to ``c.f{gas: 10000, value: 1}()``.

* The global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4`` have been removed.

  These are low-level functions that were largely unused. Their behavior can be accessed from inline assembly.

* ``enum`` definitions cannot contain more than 256 members.

  This will make it safe to assume that the underlying type in the ABI is always ``uint8``.

* Declarations with the name ``this``, ``super`` and ``_`` are disallowed, with the exception of
  public functions and events. The exception is to make it possible to declare interfaces of contracts
  implemented in languages other than Solidity that do permit such function names.

* Remove support for the ``\b``, ``\f``, and ``\v`` escape sequences in code.
  They can still be inserted via hexadecimal escapes, e.g. ``\x08``, ``\x0c``, and ``\x0b``, respectively.

* The global variables ``tx.origin`` and ``msg.sender`` have the type ``address`` instead of
  ``address payable``. One can convert them into ``address payable`` by using an explicit
  conversion, i.e., ``payable(tx.origin)`` or ``payable(msg.sender)``.

  This change was done since the compiler cannot determine whether or not these addresses
  are payable or not, so it now requires an explicit conversion to make this requirement visible.

* Explicit conversion into ``address`` type always returns a non-payable ``address`` type. In
  particular, the following explicit conversions have the type ``address`` instead of ``address
  payable``:

  - ``address(u)`` where ``u`` is a variable of type ``uint160``. One can convert ``u``
    into the type ``address payable`` by using two explicit conversions, i.e.,
    ``payable(address(u))``.
  - ``address(b)`` where ``b`` is a variable of type ``bytes20``. One can convert ``b``
    into the type ``address payable`` by using two explicit conversions, i.e.,
    ``payable(address(b))``.
  - ``address(c)`` where ``c`` is a contract. Previously, the return type of this
    conversion depended on whether the contract can receive Ether (either by having a receive
    function or a payable fallback function). The conversion ``payable(c)`` has the type ``address
    payable`` and is only allowed when the contract ``c`` can receive Ether. In general, one can
    always convert ``c`` into the type ``address payable`` by using the following explicit
    conversion: ``payable(address(c))``. Note that ``address(this)`` falls under the same category
    as ``address(c)`` and the same rules apply for it.

* The ``chainid`` builtin in inline assembly is now considered ``view`` instead of ``pure``.

* Unary negation cannot be used on unsigned integers anymore, only on signed integers.

Interface Changes
=================

* The output of ``--combined-json`` has changed: JSON fields ``abi``, ``devdoc``, ``userdoc`` and
  ``storage-layout`` are sub-objects now. Before 0.8.0 they used to be serialised as strings.

* The "legacy AST" has been removed (``--ast-json`` on the commandline interface and ``legacyAST`` for standard JSON).
  Use the "compact AST" (``--ast-compact-json`` resp. ``AST``) as replacement.

* The old error reporter (``--old-reporter``) has been removed.


How to update your code
=======================

- If you rely on wrapping arithmetic, surround each operation with ``unchecked { ... }``.
- Optional: If you use SafeMath or a similar library, change ``x.add(y)`` to ``x + y``, ``x.mul(y)`` to ``x * y`` etc.
- Add ``pragma abicoder v1;`` if you want to stay with the old ABI coder.
- Optionally remove ``pragma experimental ABIEncoderV2`` or ``pragma abicoder v2`` since it is redundant.
- Change ``byte`` to ``bytes1``.
- Add intermediate explicit type conversions if required.
- Combine ``c.f{gas: 10000}{value: 1}()`` to ``c.f{gas: 10000, value: 1}()``.
- Change ``msg.sender.transfer(x)`` to ``payable(msg.sender).transfer(x)`` or use a stored variable of ``address payable`` type.
- Change ``x**y**z`` to ``(x**y)**z``.
- Use inline assembly as a replacement for ``log0``, ..., ``log4``.
- Negate unsigned integers by subtracting them from the maximum value of the type and adding 1 (e.g. ``type(uint256).max - x + 1``, while ensuring that ``x`` is not zero)

---

### Abi Spec (`docs/abi-spec.rst`)

.. index:: abi, application binary interface

.. _ABI:

**************************
Contract ABI Specification
**************************

Basic Design
============

The Contract Application Binary Interface (ABI) is the standard way to interact with contracts in the Ethereum ecosystem, both
from outside the blockchain and for contract-to-contract interaction. Data is encoded according to its type,
as described in this specification. The encoding is not self describing and thus requires a schema in order to decode.

We assume that the interface functions of a contract are strongly typed, known at compilation time and static.
We assume that all contracts will have the interface definitions of any contracts they call available at compile-time.

This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. Also, the ABI specification for libraries is :ref:`slightly different <library-selectors>`.

.. _abi_function_selector:
.. index:: ! selector; of a function

Function Selector
=================

The first four bytes of the call data for a function call specifies the function to be called. It is the
first (left, high-order in big-endian) four bytes of the Keccak-256 hash of the signature of
the function. The signature is defined as the canonical expression of the basic prototype without data
location specifier, i.e.
the function name with the parenthesised list of parameter types. Parameter types are split by a single
comma — no spaces are used.

.. note::
    The return type of a function is not part of this signature. In
    :ref:`Solidity's function overloading <overload-function>` return types are not considered.
    The reason is to keep function call resolution context-independent.
    The :ref:`JSON description of the ABI<abi_json>` however contains both inputs and outputs.

Argument Encoding
=================

Starting from the fifth byte, the encoded arguments follow. This encoding is also used in
other places, e.g. the return values and also event arguments are encoded in the same way,
without the four bytes specifying the function.

Types
=====

Note that the library ABIs can take types different than below e.g. for non-storage structs. See :ref:`library selectors <library-selectors>` for details.

The following elementary types exist:

- ``uint<M>``: unsigned integer type of ``M`` bits, ``0 < M <= 256``, ``M % 8 == 0``. e.g. ``uint32``, ``uint8``, ``uint256``.

- ``int<M>``: two's complement signed integer type of ``M`` bits, ``0 < M <= 256``, ``M % 8 == 0``.

- ``address``: equivalent to ``uint160``, except for the assumed interpretation and language typing.
  For computing the function selector, ``address`` is used.

- ``uint``, ``int``: synonyms for ``uint256``, ``int256`` respectively. For computing the function
  selector, ``uint256`` and ``int256`` have to be used.

- ``bool``: equivalent to ``uint8`` restricted to the values 0 and 1. For computing the function selector, ``bool`` is used.

- ``fixed<M>x<N>``: signed fixed-point decimal number of ``M`` bits, ``8 <= M <= 256``,
  ``M % 8 == 0``, and ``0 < N <= 80``, which denotes the value ``v`` as ``v / (10 ** N)``.

- ``ufixed<M>x<N>``: unsigned variant of ``fixed<M>x<N>``.

- ``fixed``, ``ufixed``: synonyms for ``fixed128x18``, ``ufixed128x18`` respectively. For
  computing the function selector, ``fixed128x18`` and ``ufixed128x18`` have to be used.

- ``bytes<M>``: binary type of ``M`` bytes, ``0 < M <= 32``.

- ``function``: an address (20 bytes) followed by a function selector (4 bytes). Encoded identical to ``bytes24``.

The following (fixed-size) array type exists:

- ``<type>[M]``: a fixed-length array of ``M`` elements, ``M >= 0``, of the given type.

  .. note::

      While this ABI specification can express fixed-length arrays with zero elements, they're not supported by the compiler.

The following non-fixed-size types exist:

- ``bytes``: dynamic sized byte sequence.

- ``string``: dynamic sized unicode string assumed to be UTF-8 encoded.

- ``<type>[]``: a variable-length array of elements of the given type.

Types can be combined to a tuple by enclosing them inside parentheses, separated by commas:

- ``(T1,T2,...,Tn)``: tuple consisting of the types ``T1``, ..., ``Tn``, ``n >= 0``

It is possible to form tuples of tuples, arrays of tuples and so on. It is also possible to form zero-tuples (where ``n == 0``).

Mapping Solidity to ABI types
-----------------------------

Solidity supports all the types presented above with the same names with the
exception of tuples. On the other hand, some Solidity types are not supported
by the ABI. The following table shows on the left column Solidity types that
are not part of the ABI, and on the right column the ABI types that represent
them.

+-------------------------------+-----------------------------------------------------------------------------+
|      Solidity                 |                                           ABI                               |
+===============================+=============================================================================+
|:ref:`address payable<address>`|``address``                                                                  |
+-------------------------------+-----------------------------------------------------------------------------+
|:ref:`contract<contracts>`     |``address``                                                                  |
+-------------------------------+-----------------------------------------------------------------------------+
|:ref:`enum<enums>`             |``uint8``                                                                    |
+-------------------------------+-----------------------------------------------------------------------------+
|:ref:`user defined value types |its underlying value type                                                    |
|<user-defined-value-types>`    |                                                                             |
+-------------------------------+-----------------------------------------------------------------------------+
|:ref:`struct<structs>`         |``tuple``                                                                    |
+-------------------------------+-----------------------------------------------------------------------------+

.. warning::
    Before version ``0.8.0`` enums could have more than 256 members and were represented by the
    smallest integer type just big enough to hold the value of any member.

Design Criteria for the Encoding
================================

The encoding is designed to have the following properties, which are especially useful if some arguments are nested arrays:

1. The number of reads necessary to access a value is at most the depth of the value
   inside the argument array structure, i.e. four reads are needed to retrieve ``a_i[k][l][r]``. In a
   previous version of the ABI, the number of reads scaled linearly with the total number of dynamic
   parameters in the worst case.

2. The data of a variable or an array element is not interleaved with other data and it is
   relocatable, i.e. it only uses relative "addresses".


Formal Specification of the Encoding
====================================

We distinguish static and dynamic types. Static types are encoded in-place and dynamic types are
encoded at a separately allocated location after the current block.

**Definition:** The following types are called "dynamic":

* ``bytes``
* ``string``
* ``T[]`` for any ``T``
* ``T[k]`` for any dynamic ``T`` and any ``k >= 0``
* ``(T1,...,Tk)`` if ``Ti`` is dynamic for some ``1 <= i <= k``

All other types are called "static".

**Definition:** ``len(a)`` is the number of bytes in a binary string ``a``.
The type of ``len(a)`` is assumed to be ``uint256``.

We define ``enc``, the actual encoding, as a mapping of values of the ABI types to binary strings such
that ``len(enc(X))`` depends on the value of ``X`` if and only if the type of ``X`` is dynamic.

**Definition:** For any ABI value ``X``, we recursively define ``enc(X)``, depending
on the type of ``X`` being

- ``(T1,...,Tk)`` for ``k >= 0`` and any types ``T1``, ..., ``Tk``

  ``enc(X) = head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(k))``

  where ``X = (X(1), ..., X(k))`` and
  ``head`` and ``tail`` are defined for ``Ti`` as follows:

  if ``Ti`` is static:

    ``head(X(i)) = enc(X(i))`` and ``tail(X(i)) = ""`` (the empty string)

  otherwise, i.e. if ``Ti`` is dynamic:

    ``head(X(i)) = enc(len( head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(i-1)) ))``
    ``tail(X(i)) = enc(X(i))``

  Note that in the dynamic case, ``head(X(i))`` is well-defined since the lengths of
  the head parts only depend on the types and not the values. The value of ``head(X(i))`` is the offset
  of the beginning of ``tail(X(i))`` relative to the start of ``enc(X)``.

- ``T[k]`` for any ``T`` and ``k``:

  ``enc(X) = enc((X[0], ..., X[k-1]))``

  i.e. it is encoded as if it were a tuple with ``k`` elements
  of the same type.

- ``T[]`` where ``X`` has ``k`` elements (``k`` is assumed to be of type ``uint256``):

  ``enc(X) = enc(k) enc((X[0], ..., X[k-1]))``

  i.e. it is encoded as if it were a tuple with ``k`` elements of the same type (resp. an array of static size ``k``), prefixed with
  the number of elements.

- ``bytes``, of length ``k`` (which is assumed to be of type ``uint256``):

  ``enc(X) = enc(k) pad_right(X)``, i.e. the number of bytes is encoded as a
  ``uint256`` followed by the actual value of ``X`` as a byte sequence, followed by
  the minimum number of zero-bytes such that ``len(enc(X))`` is a multiple of 32.

- ``string``:

  ``enc(X) = enc(enc_utf8(X))``, i.e. ``X`` is UTF-8 encoded and this value is interpreted
  as of ``bytes`` type and encoded further. Note that the length used in this subsequent
  encoding is the number of bytes of the UTF-8 encoded string, not its number of characters.

- ``uint<M>``: ``enc(X)`` is the big-endian encoding of ``X``, padded on the higher-order
  (left) side with zero-bytes such that the length is 32 bytes.
- ``address``: as in the ``uint160`` case
- ``int<M>``: ``enc(X)`` is the big-endian two's complement encoding of ``X``, padded on the higher-order (left) side with ``0xff`` bytes for negative ``X`` and with zero-bytes for non-negative ``X`` such that the length is 32 bytes.
- ``bool``: as in the ``uint8`` case, where ``1`` is used for ``true`` and ``0`` for ``false``
- ``fixed<M>x<N>``: ``enc(X)`` is ``enc(X * 10**N)`` where ``X * 10**N`` is interpreted as a ``int256``.
- ``fixed``: as in the ``fixed128x18`` case
- ``ufixed<M>x<N>``: ``enc(X)`` is ``enc(X * 10**N)`` where ``X * 10**N`` is interpreted as a ``uint256``.
- ``ufixed``: as in the ``ufixed128x18`` case
- ``bytes<M>``: ``enc(X)`` is the sequence of bytes in ``X`` padded with trailing zero-bytes to a length of 32 bytes.

Note that for any ``X``, ``len(enc(X))`` is a multiple of 32.

Function Selector and Argument Encoding
=======================================

All in all, a call to the function ``f`` with parameters ``a_1, ..., a_n`` is encoded as

  ``function_selector(f) enc((a_1, ..., a_n))``

and the return values ``v_1, ..., v_k`` of ``f`` are encoded as

  ``enc((v_1, ..., v_k))``

i.e. the values are combined into a tuple and encoded.

Examples
========

Given the contract:

.. code-block:: solidity
    :force:

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.4.16 <0.9.0;

    contract Foo {
        function bar(bytes3[2] memory) public pure {}
        function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; }
        function sam(bytes memory, bool, uint[] memory) public pure {}
    }


Thus, for our ``Foo`` example, if we wanted to call ``bar`` with the argument ``["abc", "def"]``, we would pass 68 bytes total, broken down into:

- ``0xfce353f6``: the Method ID. This is derived from the signature ``bar(bytes3[2])``.
- ``0x6162630000000000000000000000000000000000000000000000000000000000``: the first part of the first
  parameter, a ``bytes3`` value ``"abc"`` (left-aligned).
- ``0x6465660000000000000000000000000000000000000000000000000000000000``: the second part of the first
  parameter, a ``bytes3`` value ``"def"`` (left-aligned).

In total:

.. code-block:: none

    0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000

If we wanted to call ``baz`` with the parameters ``69`` and
``true``, we would pass 68 bytes total, which can be broken down into:

- ``0xcdcd77c0``: the Method ID. This is derived as the first 4 bytes of the Keccak hash of
  the ASCII form of the signature ``baz(uint32,bool)``.
- ``0x0000000000000000000000000000000000000000000000000000000000000045``: the first parameter,
  a uint32 value ``69`` padded to 32 bytes
- ``0x0000000000000000000000000000000000000000000000000000000000000001``: the second parameter - boolean
  ``true``, padded to 32 bytes

In total:

.. code-block:: none

    0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001

It returns a single ``bool``. If, for example, it were to return ``false``, its output would be
the single byte array ``0x0000000000000000000000000000000000000000000000000000000000000000``, a single bool.

If we wanted to call ``sam`` with the arguments ``"dave"``, ``true`` and ``[1,2,3]``, we would
pass 292 bytes total, broken down into:

- ``0xa5643bf2``: the Method ID. This is derived from the signature ``sam(bytes,bool,uint256[])``. Note that ``uint`` is replaced with its canonical representation ``uint256``.
- ``0x0000000000000000000000000000000000000000000000000000000000000060``: the location of the data part of the first parameter (dynamic type), measured in bytes from the start of the arguments block. In this case, ``0x60``.
- ``0x0000000000000000000000000000000000000000000000000000000000000001``: the second parameter: boolean true.
- ``0x00000000000000000000000000000000000000000000000000000000000000a0``: the location of the data part of the third parameter (dynamic type), measured in bytes. In this case, ``0xa0``.
- ``0x0000000000000000000000000000000000000000000000000000000000000004``: the data part of the first argument, it starts with the length of the byte array in elements, in this case, 4.
- ``0x6461766500000000000000000000000000000000000000000000000000000000``: the contents of the first argument: the UTF-8 (equal to ASCII in this case) encoding of ``"dave"``, padded on the right to 32 bytes.
- ``0x0000000000000000000000000000000000000000000000000000000000000003``: the data part of the third argument, it starts with the length of the array in elements, in this case, 3.
- ``0x0000000000000000000000000000000000000000000000000000000000000001``: the first entry of the third parameter.
- ``0x0000000000000000000000000000000000000000000000000000000000000002``: the second entry of the third parameter.
- ``0x0000000000000000000000000000000000000000000000000000000000000003``: the third entry of the third parameter.

In total:

.. code-block:: none

    0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003

Use of Dynamic Types
====================

A call to a function with the signature ``f(uint256,uint32[],bytes10,bytes)`` with values
``(0x123, [0x456, 0x789], "1234567890", "Hello, world!")`` is encoded in the following way:

We take the first four bytes of ``keccak("f(uint256,uint32[],bytes10,bytes)")``, i.e. ``0x8be65246``.
Then we encode the head parts of all four arguments. For the static types ``uint256`` and ``bytes10``,
these are directly the values we want to pass, whereas for the dynamic types ``uint32[]`` and ``bytes``,
we use the offset in bytes to the start of their data area, measured from the start of the value
encoding (i.e. not counting the first four bytes containing the hash of the function signature). These are:

- ``0x0000000000000000000000000000000000000000000000000000000000000123`` (``0x123`` padded to 32 bytes)
- ``0x0000000000000000000000000000000000000000000000000000000000000080`` (offset to start of data part of second parameter, 4*32 bytes, exactly the size of the head part)
- ``0x3132333435363738393000000000000000000000000000000000000000000000`` (``"1234567890"`` padded to 32 bytes on the right)
- ``0x00000000000000000000000000000000000000000000000000000000000000e0`` (offset to start of data part of fourth parameter = offset to start of data part of first dynamic parameter + size of data part of first dynamic parameter = 4\*32 + 3\*32 (see below))

After this, the data part of the first dynamic argument, ``[0x456, 0x789]`` follows:

- ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements of the array, 2)
- ``0x0000000000000000000000000000000000000000000000000000000000000456`` (first element)
- ``0x0000000000000000000000000000000000000000000000000000000000000789`` (second element)

Finally, we encode the data part of the second dynamic argument, ``"Hello, world!"``:

- ``0x000000000000000000000000000000000000000000000000000000000000000d`` (number of elements (bytes in this case): 13)
- ``0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000`` (``"Hello, world!"`` padded to 32 bytes on the right)

All together, the encoding is (newline after function selector and each 32-bytes for clarity):

.. code-block:: none

    0x8be65246
      0000000000000000000000000000000000000000000000000000000000000123
      0000000000000000000000000000000000000000000000000000000000000080
      3132333435363738393000000000000000000000000000000000000000000000
      00000000000000000000000000000000000000000000000000000000000000e0
      0000000000000000000000000000000000000000000000000000000000000002
      0000000000000000000000000000000000000000000000000000000000000456
      0000000000000000000000000000000000000000000000000000000000000789
      000000000000000000000000000000000000000000000000000000000000000d
      48656c6c6f2c20776f726c642100000000000000000000000000000000000000

Let us apply the same principle to encode the data for a function with a signature ``g(uint256[][],string[])``
with values ``([[1, 2], [3]], ["one", "two", "three"])`` but start from the most atomic parts of the encoding:

First we encode the length and data of the first embedded dynamic array ``[1, 2]`` of the first root array ``[[1, 2], [3]]``:

- ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements in the first array, 2; the elements themselves are ``1`` and ``2``)
- ``0x0000000000000000000000000000000000000000000000000000000000000001`` (first element)
- ``0x0000000000000000000000000000000000000000000000000000000000000002`` (second element)

Then we encode the length and data of the second embedded dynamic array ``[3]`` of the first root array ``[[1, 2], [3]]``:

- ``0x0000000000000000000000000000000000000000000000000000000000000001`` (number of elements in the second array, 1; the element is ``3``)
- ``0x0000000000000000000000000000000000000000000000000000000000000003`` (first element)

Then we need to find the offsets ``a`` and ``b`` for their respective dynamic arrays ``[1, 2]`` and ``[3]``.
To calculate the offsets we can take a look at the encoded data of the first root array ``[[1, 2], [3]]``
enumerating each line in the encoding:

.. code-block:: none

    0 - a                                                                - offset of [1, 2]
    1 - b                                                                - offset of [3]
    2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2]
    3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1
    4 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2
    5 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3]
    6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3

Offset ``a`` points to the start of the content of the array ``[1, 2]`` which is line
2 (64 bytes); thus ``a = 0x0000000000000000000000000000000000000000000000000000000000000040``.

Offset ``b`` points to the start of the content of the array ``[3]`` which is line 5 (160 bytes);
thus ``b = 0x00000000000000000000000000000000000000000000000000000000000000a0``.


Then we encode the embedded strings of the second root array:

- ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of characters in word ``"one"``)
- ``0x6f6e650000000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"one"``)
- ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of characters in word ``"two"``)
- ``0x74776f0000000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"two"``)
- ``0x0000000000000000000000000000000000000000000000000000000000000005`` (number of characters in word ``"three"``)
- ``0x7468726565000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"three"``)

In parallel to the first root array, since strings are dynamic elements we need to find their offsets ``c``, ``d`` and ``e``:

.. code-block:: none

    0 - c                                                                - offset for "one"
    1 - d                                                                - offset for "two"
    2 - e                                                                - offset for "three"
    3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one"
    4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one"
    5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two"
    6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two"
    7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three"
    8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three"

Offset ``c`` points to the start of the content of the string ``"one"`` which is line 3 (96 bytes);
thus ``c = 0x0000000000000000000000000000000000000000000000000000000000000060``.

Offset ``d`` points to the start of the content of the string ``"two"`` which is line 5 (160 bytes);
thus ``d = 0x00000000000000000000000000000000000000000000000000000000000000a0``.

Offset ``e`` points to the start of the content of the string ``"three"`` which is line 7 (224 bytes);
thus ``e = 0x00000000000000000000000000000000000000000000000000000000000000e0``.


Note that the encodings of the embedded elements of the root arrays are not dependent on each other
and have the same encodings for a function with a signature ``g(string[],uint256[][])``.

Then we encode the length of the first root array:

- ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements in the first root array, 2; the elements themselves are ``[1, 2]``  and ``[3]``)

Then we encode the length of the second root array:

- ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of strings in the second root array, 3; the strings themselves are ``"one"``, ``"two"`` and ``"three"``)

Finally we find the offsets ``f`` and ``g`` for their respective root dynamic arrays ``[[1, 2], [3]]`` and
``["one", "two", "three"]``, and assemble parts in the correct order:

.. code-block:: none

    0x2289b18c                                                            - function signature
     0 - f                                                                - offset of [[1, 2], [3]]
     1 - g                                                                - offset of ["one", "two", "three"]
     2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]]
     3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2]
     4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3]
     5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2]
     6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1
     7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2
     8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3]
     9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3
    10 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"]
    11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one"
    12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two"
    13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three"
    14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one"
    15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one"
    16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two"
    17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two"
    18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three"
    19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three"

Offset ``f`` points to the start of the content of the array ``[[1, 2], [3]]`` which is line 2 (64 bytes);
thus ``f = 0x0000000000000000000000000000000000000000000000000000000000000040``.

Offset ``g`` points to the start of the content of the array ``["one", "two", "three"]`` which is line 10 (320 bytes);
thus ``g = 0x0000000000000000000000000000000000000000000000000000000000000140``.

.. _abi_events:

Events
======

Events are an abstraction of the Ethereum logging/event-watching protocol. Log entries provide the contract's
address, a series of up to four topics and some arbitrary length binary data. Events leverage the existing function
ABI in order to interpret this (together with an interface spec) as a properly typed structure.

Given an event name and series of event parameters, we split them into two sub-series: those which are indexed and
those which are not.
Those which are indexed, which may number up to 3 (for non-anonymous events) or 4 (for anonymous ones), are used
alongside the Keccak hash of the event signature to form the topics of the log entry.
Those which are not indexed form the byte array of the event.

In effect, a log entry using this ABI is described as:

- ``address``: the address of the contract (intrinsically provided by Ethereum);
- ``topics[0]``: ``keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")`` (``canonical_type_of``
  is a function that simply returns the canonical type of a given argument, e.g. for ``uint indexed foo``, it would
  return ``uint256``). This value is only present in ``topics[0]`` if the event is not declared as ``anonymous``;
- ``topics[n]``: ``abi_encode(EVENT_INDEXED_ARGS[n - 1])`` if the event is not declared as ``anonymous``
  or ``abi_encode(EVENT_INDEXED_ARGS[n])`` if it is (``EVENT_INDEXED_ARGS`` is the series of ``EVENT_ARGS`` that
  are indexed);
- ``data``: ABI encoding of ``EVENT_NON_INDEXED_ARGS`` (``EVENT_NON_INDEXED_ARGS`` is the series of ``EVENT_ARGS``
  that are not indexed, ``abi_encode`` is the ABI encoding function used for returning a series of typed values
  from a function, as described above).

For all types of length at most 32 bytes, the ``EVENT_INDEXED_ARGS`` array contains
the value directly, padded or sign-extended (for signed integers) to 32 bytes, just as for regular ABI encoding.
However, for all "complex" types or types of dynamic length, including all arrays, ``string``, ``bytes`` and structs,
``EVENT_INDEXED_ARGS`` will contain the *Keccak hash* of a special in-place encoded value
(see :ref:`indexed_event_encoding`), rather than the encoded value directly.
This allows applications to efficiently query for values of dynamic-length types
(by setting the hash of the encoded value as the topic), but leaves applications unable
to decode indexed values they have not queried for. For dynamic-length types,
application developers face a trade-off between fast search for predetermined values
(if the argument is indexed) and legibility of arbitrary values (which requires that
the arguments not be indexed). Developers may overcome this tradeoff and achieve both
efficient search and arbitrary legibility by defining events with two arguments — one
indexed, one not — intended to hold the same value.

.. _abi_errors:
.. index:: error, selector; of an error

Errors
======

In case of a failure inside a contract, the contract can use a special opcode to abort execution and revert
all state changes. In addition to these effects, descriptive data can be returned to the caller.
This descriptive data is the encoding of an error and its arguments in the same way as data for a function
call.

As an example, let us consider the following contract whose ``transfer`` function always
reverts with a custom error of "insufficient balance":

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;

    contract TestToken {
        error InsufficientBalance(uint256 available, uint256 required);
        function transfer(address /*to*/, uint amount) public pure {
            revert InsufficientBalance(0, amount);
        }
    }

The return data would be encoded in the same way as the function call
``InsufficientBalance(0, amount)`` to the function ``InsufficientBalance(uint256,uint256)``,
i.e. ``0xcf479181``, ``uint256(0)``, ``uint256(amount)``.

The error selectors ``0x00000000`` and ``0xffffffff`` are reserved for future use.

.. warning::
    Never trust error data.
    The error data by default bubbles up through the chain of external calls, which
    means that a contract may receive an error not defined in any of the contracts
    it calls directly.
    Furthermore, any contract can fake any error by returning data that matches
    an error signature, even if the error is not defined anywhere.

.. _abi_json:

JSON
====

The JSON format for a contract's interface is given by an array of function, event and error descriptions.
A function description is a JSON object with the fields:

- ``type``: ``"function"``, ``"constructor"``, ``"receive"`` (the :ref:`"receive Ether" function <receive-ether-function>`) or ``"fallback"`` (the :ref:`"default" function <fallback-function>`);
- ``name``: the name of the function;
- ``inputs``: an array of objects, each of which contains:

  * ``name``: the name of the parameter.
  * ``type``: the canonical type of the parameter (more below).
  * ``components``: used for tuple types (more below).

- ``outputs``: an array of objects similar to ``inputs``.
- ``stateMutability``: a string with one of the following values: ``pure`` (:ref:`specified to not read
  blockchain state <pure-functions>`), ``view`` (:ref:`specified to not modify the blockchain
  state <view-functions>`), ``nonpayable`` (function does not accept Ether - the default) and ``payable`` (function accepts Ether).

Constructor, receive, and fallback never have ``name`` or ``outputs``. Receive and fallback do not have ``inputs`` either.

.. note::
    Sending non-zero Ether to non-payable function will revert the transaction.

.. note::
    The state mutability ``nonpayable`` is reflected in Solidity by not specifying
    a state mutability modifier at all.

An event description is a JSON object with fairly similar fields:

- ``type``: always ``"event"``
- ``name``: the name of the event.
- ``inputs``: an array of objects, each of which contains:

  * ``name``: the name of the parameter.
  * ``type``: the canonical type of the parameter (more below).
  * ``components``: used for tuple types (more below).
  * ``indexed``: ``true`` if the field is part of the log's topics, ``false`` if it is one of the log's data segments.

- ``anonymous``: ``true`` if the event was declared as ``anonymous``.

Errors look as follows:

- ``type``: always ``"error"``
- ``name``: the name of the error.
- ``inputs``: an array of objects, each of which contains:

  * ``name``: the name of the parameter.
  * ``type``: the canonical type of the parameter (more below).
  * ``components``: used for tuple types (more below).

.. note::
  There can be multiple errors with the same name and even with identical signature
  in the JSON array; for example, if the errors originate from different
  files in the smart contract or are referenced from another smart contract.
  For the ABI, only the name of the error itself is relevant and not where it is
  defined.


For example,

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;


    contract Test {
        constructor() { b = hex"12345678901234567890123456789012"; }
        event Event(uint indexed a, bytes32 b);
        event Event2(uint indexed a, bytes32 b);
        error InsufficientBalance(uint256 available, uint256 required);
        function foo(uint a) public { emit Event(a, b); }
        bytes32 b;
    }

would result in the JSON:

.. code-block:: json

    [{
    "type":"error",
    "inputs": [{"name":"available","type":"uint256"},{"name":"required","type":"uint256"}],
    "name":"InsufficientBalance"
    }, {
    "type":"event",
    "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}],
    "name":"Event"
    }, {
    "type":"event",
    "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}],
    "name":"Event2"
    }, {
    "type":"function",
    "inputs": [{"name":"a","type":"uint256"}],
    "name":"foo",
    "outputs": []
    }]

Handling tuple types
--------------------

Despite the fact that names are intentionally not part of the ABI encoding, they do make a lot of sense to be included
in the JSON to enable displaying it to the end user. The structure is nested in the following way:

An object with members ``name``, ``type`` and potentially ``components`` describes a typed variable.
The canonical type is determined until a tuple type is reached and the string description up
to that point is stored in ``type`` prefix with the word ``tuple``, i.e. it will be ``tuple`` followed by
a sequence of ``[]`` and ``[k]`` with
integers ``k``. The components of the tuple are then stored in the member ``components``,
which is of an array type and has the same structure as the top-level object except that
``indexed`` is not allowed there.

As an example, the code

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.7.5 <0.9.0;
    pragma abicoder v2;

    contract Test {
        struct S { uint a; uint[] b; T[] c; }
        struct T { uint x; uint y; }
        function f(S memory, T memory, uint) public pure {}
        function g() public pure returns (S memory, T memory, uint) {}
    }

would result in the JSON:

.. code-block:: json

    [
      {
        "name": "f",
        "type": "function",
        "inputs": [
          {
            "name": "s",
            "type": "tuple",
            "components": [
              {
                "name": "a",
                "type": "uint256"
              },
              {
                "name": "b",
                "type": "uint256[]"
              },
              {
                "name": "c",
                "type": "tuple[]",
                "components": [
                  {
                    "name": "x",
                    "type": "uint256"
                  },
                  {
                    "name": "y",
                    "type": "uint256"
                  }
                ]
              }
            ]
          },
          {
            "name": "t",
            "type": "tuple",
            "components": [
              {
                "name": "x",
                "type": "uint256"
              },
              {
                "name": "y",
                "type": "uint256"
              }
            ]
          },
          {
            "name": "a",
            "type": "uint256"
          }
        ],
        "outputs": []
      }
    ]

.. _abi_packed_mode:

Strict Encoding Mode
====================

Strict encoding mode is the mode that leads to exactly the same encoding as defined in the formal specification above.
This means that offsets have to be as small as possible while still not creating overlaps in the data areas, and thus no gaps are
allowed.

Usually, ABI decoders are written in a straightforward way by just following offset pointers, but some decoders
might enforce strict mode. The Solidity ABI decoder currently does not enforce strict mode, but the encoder
always creates data in strict mode.

Non-standard Packed Mode
========================

Through ``abi.encodePacked()``, Solidity supports a non-standard packed mode where:

- types shorter than 32 bytes are concatenated directly, without padding or sign extension
- dynamic types are encoded in-place and without the length.
- array elements are padded, but still encoded in-place

Furthermore, structs as well as nested arrays are not supported.

As an example, the encoding of ``int16(-1), bytes1(0x42), uint16(0x03), string("Hello, world!")`` results in:

.. code-block:: none

    0xffff42000348656c6c6f2c20776f726c6421
      ^^^^                                 int16(-1)
          ^^                               bytes1(0x42)
            ^^^^                           uint16(0x03)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field

More specifically:

- During the encoding, everything is encoded in-place. This means that there is
  no distinction between head and tail, as in the ABI encoding, and the length
  of an array is not encoded.
- The direct arguments of ``abi.encodePacked`` are encoded without padding,
  as long as they are not arrays (or ``string`` or ``bytes``).
- The encoding of an array is the concatenation of the
  encoding of its elements **with** padding.
- Dynamically-sized types like ``string``, ``bytes`` or ``uint[]`` are encoded
  without their length field.
- The encoding of ``string`` or ``bytes`` does not apply padding at the end,
  unless it is part of an array or struct (then it is padded to a multiple of
  32 bytes).

In general, the encoding is ambiguous as soon as there are two dynamically-sized elements,
because of the missing length field.

If padding is needed, explicit type conversions can be used: ``abi.encodePacked(uint16(0x12)) == hex"0012"``.

Since packed encoding is not used when calling functions, there is no special support
for prepending a function selector. Since the encoding is ambiguous, there is no decoding function.

.. warning::

    If you use ``keccak256(abi.encodePacked(a, b))`` and both ``a`` and ``b`` are dynamic types,
    it is easy to craft collisions in the hash value by moving parts of ``a`` into ``b`` and
    vice-versa. More specifically, ``abi.encodePacked("a", "bc") == abi.encodePacked("ab", "c")``.
    If you use ``abi.encodePacked`` for signatures, authentication or data integrity, make
    sure to always use the same types and check that at most one of them is dynamic.
    Unless there is a compelling reason, ``abi.encode`` should be preferred.


.. _indexed_event_encoding:

Encoding of Indexed Event Parameters
====================================

Indexed event parameters that are not value types, i.e. arrays and structs are not
stored directly but instead a Keccak-256 hash of an encoding is stored. This encoding
is defined as follows:

- the encoding of a ``bytes`` and ``string`` value is just the string contents
  without any padding or length prefix.
- the encoding of a struct is the concatenation of the encoding of its members,
  always padded to a multiple of 32 bytes (even ``bytes`` and ``string``).
- the encoding of an array (both dynamically- and statically-sized) is
  the concatenation of the encoding of its elements, always padded to a multiple
  of 32 bytes (even ``bytes`` and ``string``) and without any length prefix

In the above, as usual, a negative number is padded by sign extension and not zero padded.
``bytesNN`` types are padded on the right while ``uintNN`` / ``intNN`` are padded on the left.

.. warning::

    The encoding of a struct is ambiguous if it contains more than one dynamically-sized
    array. Because of that, always re-check the event data and do not rely on the search result
    based on the indexed parameters alone.

---

### Analysing Compilation Output (`docs/analysing-compilation-output.rst`)

.. index:: analyse, asm

#############################
Analysing the Compiler Output
#############################

It is often useful to look at the assembly code generated by the compiler. The generated binary,
i.e., the output of ``solc --bin contract.sol``, is generally difficult to read. It is recommended
to use the flag ``--asm`` to analyse the assembly output. Even for large contracts, looking at a
visual diff of the assembly before and after a change is often very enlightening.

Consider the following contract (named, say ``contract.sol``):

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.5.0 <0.9.0;
    contract C {
        function one() public pure returns (uint) {
            return 1;
        }
    }

The following would be the output of ``solc --asm contract.sol``

.. code-block:: none

    ======= contract.sol:C =======
    EVM assembly:
        /* "contract.sol":0:86  contract C {... */
      mstore(0x40, 0x80)
      callvalue
      dup1
      iszero
      tag_1
      jumpi
      0x00
      dup1
      revert
    tag_1:
      pop
      dataSize(sub_0)
      dup1
      dataOffset(sub_0)
      0x00
      codecopy
      0x00
      return
    stop

    sub_0: assembly {
            /* "contract.sol":0:86  contract C {... */
          mstore(0x40, 0x80)
          callvalue
          dup1
          iszero
          tag_1
          jumpi
          0x00
          dup1
          revert
        tag_1:
          pop
          jumpi(tag_2, lt(calldatasize, 0x04))
          shr(0xe0, calldataload(0x00))
          dup1
          0x901717d1
          eq
          tag_3
          jumpi
        tag_2:
          0x00
          dup1
          revert
            /* "contract.sol":17:84  function one() public pure returns (uint) {... */
        tag_3:
          tag_4
          tag_5
          jump	// in
        tag_4:
          mload(0x40)
          tag_6
          swap2
          swap1
          tag_7
          jump	// in
        tag_6:
          mload(0x40)
          dup1
          swap2
          sub
          swap1
          return
        tag_5:
            /* "contract.sol":53:57  uint */
          0x00
            /* "contract.sol":76:77  1 */
          0x01
            /* "contract.sol":69:77  return 1 */
          swap1
          pop
            /* "contract.sol":17:84  function one() public pure returns (uint) {... */
          swap1
          jump	// out
            /* "#utility.yul":7:125   */
        tag_10:
            /* "#utility.yul":94:118   */
          tag_12
            /* "#utility.yul":112:117   */
          dup2
            /* "#utility.yul":94:118   */
          tag_13
          jump	// in
        tag_12:
            /* "#utility.yul":89:92   */
          dup3
            /* "#utility.yul":82:119   */
          mstore
            /* "#utility.yul":72:125   */
          pop
          pop
          jump	// out
            /* "#utility.yul":131:353   */
        tag_7:
          0x00
            /* "#utility.yul":262:264   */
          0x20
            /* "#utility.yul":251:260   */
          dup3
            /* "#utility.yul":247:265   */
          add
            /* "#utility.yul":239:265   */
          swap1
          pop
            /* "#utility.yul":275:346   */
          tag_15
            /* "#utility.yul":343:344   */
          0x00
            /* "#utility.yul":332:341   */
          dup4
            /* "#utility.yul":328:345   */
          add
            /* "#utility.yul":319:325   */
          dup5
            /* "#utility.yul":275:346   */
          tag_10
          jump	// in
        tag_15:
            /* "#utility.yul":229:353   */
          swap3
          swap2
          pop
          pop
          jump	// out
            /* "#utility.yul":359:436   */
        tag_13:
          0x00
            /* "#utility.yul":425:430   */
          dup2
            /* "#utility.yul":414:430   */
          swap1
          pop
            /* "#utility.yul":404:436   */
          swap2
          swap1
          pop
          jump	// out

        auxdata: 0xa2646970667358221220a5874f19737ddd4c5d77ace1619e5160c67b3d4bedac75fce908fed32d98899864736f6c637827302e382e342d646576656c6f702e323032312e332e33302b636f6d6d69742e65613065363933380058
    }

Alternatively, the above output can also be obtained from `Remix <https://remix.ethereum.org/>`_,
under the option "Compilation Details" after compiling a contract.

Notice that the ``asm`` output starts with the creation / constructor code. The deploy code is
provided as part of the sub object (in the above example, it is part of the sub-object ``sub_0``).
The ``auxdata`` field corresponds to the contract :ref:`metadata
<encoding-of-the-metadata-hash-in-the-bytecode>`. The comments in the assembly output point to the
source location. Note that ``#utility.yul`` is an internally generated file of utility functions
that can be obtained using the flags ``--combined-json
generated-sources,generated-sources-runtime``.

Similarly, the optimized assembly can be obtained with the command: ``solc --optimize --asm
contract.sol``. Often times, it is interesting to see if two different sources in Solidity result in
the same optimized code. For example, to see if the expressions ``(a * b) / c``, ``a * b / c``
generates the same bytecode. This can be easily done by taking a ``diff`` of the corresponding
assembly output, after potentially stripping comments that reference the source locations.

.. note::

   The ``--asm`` output is not designed to be machine readable. Therefore, there may be breaking
   changes on the output between minor versions of solc.

---

### Assembly (`docs/assembly.rst`)

.. _inline-assembly:

###############
Inline Assembly
###############

.. index:: ! assembly, ! asm, ! evmasm


You can interleave Solidity statements with inline assembly in a language close
to the one of the Ethereum Virtual Machine. This gives you more fine-grained control,
which is especially useful when you are enhancing the language by writing libraries or
optimizing gas usage.

The language used for inline assembly in Solidity is called :ref:`Yul <yul>`
and it is documented in its own section. This section will only cover
how the inline assembly code can interface with the surrounding Solidity code.


.. warning::
    Inline assembly is a way to access the Ethereum Virtual Machine
    at a low level. This bypasses several important safety
    features and checks of Solidity. You should only use it for
    tasks that need it, and only if you are confident with using it.


An inline assembly block is marked by ``assembly { ... }``, where the code inside
the curly braces is code in the :ref:`Yul <yul>` language.

The inline assembly code can access local Solidity variables as explained below.

Different inline assembly blocks share no namespace, i.e. it is not possible
to call a Yul function or access a Yul variable defined in a different inline assembly block.

Example
-------

The following example provides library code to access the code of another contract and
load it into a ``bytes`` variable. This is possible with "plain Solidity" too, by using
``<address>.code``. But the point here is that reusable assembly libraries can enhance the
Solidity language without a compiler change.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.4.16 <0.9.0;

    library GetCode {
        // This will report a warning - `at` will be promoted to reserved keyword
        function at(address addr) public view returns (bytes memory code) {
            assembly {
                // retrieve the size of the code, this needs assembly
                let size := extcodesize(addr)
                // allocate output byte array - this could also be done without assembly
                // by using code = new bytes(size)
                code := mload(0x40)
                // new "memory end" including padding
                mstore(0x40, add(code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
                // store length in memory
                mstore(code, size)
                // actually retrieve the code, this needs assembly
                extcodecopy(addr, add(code, 0x20), 0, size)
            }
        }
    }

Inline assembly is also beneficial in cases where the optimizer fails to produce
efficient code, for example:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.4.16 <0.9.0;


    library VectorSum {
        // This function is less efficient because the optimizer currently fails to
        // remove the bounds checks in array access.
        function sumSolidity(uint[] memory data) public pure returns (uint sum) {
            for (uint i = 0; i < data.length; ++i)
                sum += data[i];
        }

        // We know that we only access the array in bounds, so we can avoid the check.
        // 0x20 needs to be added to an array because the first slot contains the
        // array length.
        function sumAsm(uint[] memory data) public pure returns (uint sum) {
            for (uint i = 0; i < data.length; ++i) {
                assembly {
                    sum := add(sum, mload(add(add(data, 0x20), mul(i, 0x20))))
                }
            }
        }

        // Same as above, but accomplish the entire code within inline assembly.
        function sumPureAsm(uint[] memory data) public pure returns (uint sum) {
            assembly {
                // Load the length (first 32 bytes)
                let len := mload(data)

                // Skip over the length field.
                //
                // Keep temporary variable so it can be incremented in place.
                //
                // NOTE: incrementing data would result in an unusable
                //       data variable after this assembly block
                let dataElementLocation := add(data, 0x20)

                // Iterate until the bound is not met.
                for
                    { let end := add(dataElementLocation, mul(len, 0x20)) }
                    lt(dataElementLocation, end)
                    { dataElementLocation := add(dataElementLocation, 0x20) }
                {
                    sum := add(sum, mload(dataElementLocation))
                }
            }
        }
    }

.. index:: selector; of a function

Access to External Variables, Functions and Libraries
-----------------------------------------------------

You can access Solidity variables and other identifiers by using their name.

Local variables of value type are directly usable in inline assembly.
They can both be read and assigned to.

Local variables that refer to memory evaluate to the address of the variable in memory, not the value itself.
Such variables can also be assigned to, but note that an assignment will only change the pointer and not the data
and that it is your responsibility to respect Solidity's memory management.
See :ref:`Conventions in Solidity <conventions-in-solidity>`.

Similarly, local variables that refer to statically-sized calldata arrays or calldata structs
evaluate to the address of the variable in calldata, not the value itself.
The variable can also be assigned a new offset, but note that no validation is performed to ensure that
the variable will not point beyond ``calldatasize()``.

For external function pointers the address and the function selector can be
accessed using ``x.address`` and ``x.selector``.
The selector consists of four right-aligned bytes.
Both values can be assigned to. For example:

.. code-block:: solidity
    :force:

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.8.10 <0.9.0;

    contract C {
        // Assigns a new selector and address to the return variable @fun
        function combineToFunctionPointer(address newAddress, uint newSelector) public pure returns (function() external fun) {
            assembly {
                fun.selector := newSelector
                fun.address  := newAddress
            }
        }
    }

For dynamic calldata arrays, you can access
their calldata offset (in bytes) and length (number of elements) using ``x.offset`` and ``x.length``.
Both expressions can also be assigned to, but as for the static case, no validation will be performed
to ensure that the resulting data area is within the bounds of ``calldatasize()``.

For local storage variables or state variables (including transient storage) a single Yul identifier
is not sufficient, since they do not necessarily occupy a single full storage slot.
Therefore, their "address" is composed of a slot and a byte-offset
inside that slot. To retrieve the slot pointed to by the variable ``x``, you
use ``x.slot``, and to retrieve the byte-offset you use ``x.offset``.
Using ``x`` itself will result in an error.

You can also assign to the ``.slot`` part of a local storage variable pointer.
For these (structs, arrays or mappings), the ``.offset`` part is always zero.
It is not possible to assign to the ``.slot`` or ``.offset`` part of a state variable,
though.

Local Solidity variables are available for assignments, for example:

.. code-block:: solidity
    :force:

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.8.28 <0.9.0;

    // This will report a warning
    contract C {
        bool transient a;
        uint b;
        function f(uint x) public returns (uint r) {
            assembly {
                // We ignore the storage slot offset, we know it is zero
                // in this special case.
                r := mul(x, sload(b.slot))
                tstore(a.slot, true)
            }
        }
    }

.. warning::
    If you access variables of a type that spans less than 256 bits
    (for example ``uint64``, ``address``, or ``bytes16``),
    you cannot make any assumptions about bits not part of the
    encoding of the type. Especially, do not assume them to be zero.
    To be safe, always clear the data properly before you use it
    in a context where this is important:
    ``uint32 x = f(); assembly { x := and(x, 0xffffffff) /* now use x */ }``
    To clean signed types, you can use the ``signextend`` opcode:
    ``assembly { signextend(<num_bytes_of_x_minus_one>, x) }``


Since Solidity 0.6.0, the name of an inline assembly variable may not
shadow any declaration visible in the scope of the inline assembly block
(including variable, contract and function declarations).

Since Solidity 0.7.0, variables and functions declared inside the
inline assembly block may not contain ``.``, but using ``.`` is
valid to access Solidity variables from outside the inline assembly block.
However, it is still valid to use dots if you use Solidity in Yul-only mode.

Things to Avoid
---------------

Inline assembly might have a quite high-level look, but it actually is extremely
low-level. Function calls, loops, ifs and switches are converted by simple
rewriting rules and after that, the only thing the assembler does for you is re-arranging
functional-style opcodes, counting stack height for
variable access and removing stack slots for assembly-local variables when the end
of their block is reached.

.. _conventions-in-solidity:

Conventions in Solidity
-----------------------

.. _assembly-typed-variables:

Values of Typed Variables
=========================

In contrast to EVM assembly, Solidity has types which are narrower than 256 bits,
e.g. ``uint24``. For efficiency, most arithmetic operations ignore the fact that
types can be shorter than 256
bits, and the higher-order bits are cleaned when necessary,
i.e., shortly before they are written to memory or before comparisons are performed.
This means that if you access such a variable
from within inline assembly, you might have to manually clean the higher-order bits
first.

.. _assembly-memory-management:

Memory Management
=================

Solidity manages memory in the following way. There is a "free memory pointer"
at position ``0x40`` in memory. If you want to allocate memory, use the memory
starting from where this pointer points at and update it.
There is no guarantee that the memory has not been used before and thus
you cannot assume that its contents are zero bytes.
There is no built-in mechanism to release or free allocated memory.
Solidity does not guarantee and does not require that the values in memory
are placed at positions aligned to a multiple of any value.
Here is an assembly snippet you can use for allocating memory that follows the process outlined above:

.. code-block:: yul

    function allocate(length) -> pos {
      pos := mload(0x40)
      mstore(0x40, add(pos, length))
    }

The first 64 bytes of memory can be used as "scratch space" for short-term
allocation. The 32 bytes after the free memory pointer (i.e., starting at ``0x60``)
are meant to be zero permanently and is used as the initial value for
empty dynamic memory arrays.
This means that the allocatable memory starts at ``0x80``, which is the initial value
of the free memory pointer.

Elements in memory arrays in Solidity always occupy multiples of 32 bytes (this is
even true for ``bytes1[]``, but not for ``bytes`` and ``string``). Multi-dimensional memory
arrays are pointers to memory arrays. The length of a dynamic array is stored at the
first slot of the array and followed by the array elements.

.. warning::
    Statically-sized memory arrays do not have a length field, but it might be added later
    to allow better convertibility between statically and dynamically-sized arrays; so,
    do not rely on this.

Memory Safety
=============

Without the use of inline assembly, the compiler can rely on memory to remain in a well-defined
state at all times. This is especially relevant for :ref:`the new code generation pipeline via Yul IR <ir-breaking-changes>`:
this code generation path can move local variables from stack to memory to avoid stack-too-deep errors and
perform additional memory optimizations, if it can rely on certain assumptions about memory use.

While we recommend to always respect Solidity's memory model, inline assembly allows you to use memory
in an incompatible way. Therefore, moving stack variables to memory and additional memory optimizations are,
by default, globally disabled in the presence of any inline assembly block that contains a memory operation
or assigns to Solidity variables in memory.

However, you can specifically annotate an assembly block to indicate that it in fact respects Solidity's memory
model as follows:

.. code-block:: solidity

    assembly ("memory-safe") {
        ...
    }

In particular, a memory-safe assembly block may only access the following memory ranges:

- Memory allocated by yourself using a mechanism like the ``allocate`` function described above.
- Memory allocated by Solidity, e.g. memory within the bounds of a memory array you reference.
- The scratch space between memory offset 0 and 64 mentioned above.
- Temporary memory that is located *after* the value of the free memory pointer at the beginning of the assembly block,
  i.e. memory that is "allocated" at the free memory pointer without updating the free memory pointer.

Furthermore, if the assembly block assigns to Solidity variables in memory, you need to assure that accesses to
the Solidity variables only access these memory ranges.

Since this is mainly about the optimizer, these restrictions still need to be followed, even if the assembly block
reverts or terminates. As an example, the following assembly snippet is not memory safe, because the value of
``returndatasize()`` may exceed the 64 byte scratch space:

.. code-block:: solidity

    assembly {
      returndatacopy(0, 0, returndatasize())
      revert(0, returndatasize())
    }

On the other hand, the following code *is* memory safe, because memory beyond the location pointed to by the
free memory pointer can safely be used as temporary scratch space:

.. code-block:: solidity

    assembly ("memory-safe") {
      let p := mload(0x40)
      returndatacopy(p, 0, returndatasize())
      revert(p, returndatasize())
    }

Note that you do not need to update the free memory pointer if there is no following allocation,
but you can only use memory starting from the current offset given by the free memory pointer.

If the memory operations use a length of zero, it is also fine to just use any offset (not only if it falls into the scratch space):

.. code-block:: solidity

    assembly ("memory-safe") {
      revert(0, 0)
    }

Note that not only memory operations in inline assembly itself can be memory-unsafe, but also assignments to
Solidity variables of reference type in memory. For example the following is not memory-safe:

.. code-block:: solidity

    bytes memory x;
    assembly {
      x := 0x40
    }
    x[0x20] = 0x42;

Inline assembly that neither involves any operations that access memory nor assigns to any Solidity variables
in memory is automatically considered memory-safe and does not need to be annotated.

.. warning::
    It is your responsibility to make sure that the assembly actually satisfies the memory model. If you annotate
    an assembly block as memory-safe, but violate one of the memory assumptions, this **will** lead to incorrect and
    undefined behavior that cannot easily be discovered by testing.

In case you are developing a library that is meant to be compatible across multiple versions
of Solidity, you can use a special comment to annotate an assembly block as memory-safe:

.. code-block:: solidity

    /// @solidity memory-safe-assembly
    assembly {
        ...
    }

.. warning::
    The ``memory-safe-assembly`` special comment is deprecated and scheduled for removal.
    In new code targeting recent compilers, use the assembly block annotation.

Advanced Safe Use of Memory
---------------------------

Beyond the strict definition of memory-safety given above, there are cases in which you may want to use more than 64 bytes
of scratch space starting at memory offset ``0``. If you are careful, it can be admissible to use memory up to (and not
including) offset ``0x80`` and still safely declare the assembly block as ``memory-safe``.
This is admissible under either of the following conditions:

- By the end of the assembly block, the free memory pointer at offset ``0x40`` is restored to a sane value (i.e. it is either
  restored to its original value or an increment of it due to a manual memory allocation), and the memory word at offset ``0x60``
  is restored to a value of zero.

- The assembly block terminates, i.e. execution can never return to high-level Solidity code. This is the case, for example,
  if your assembly block unconditionally ends in calling the ``revert`` opcode.

Furthermore, you need to be aware that the default-value of dynamic arrays in Solidity point to memory offset ``0x60``, so
for the duration of temporarily changing the value at memory offset ``0x60``, you can no longer rely on getting accurate
length values when reading dynamic arrays, until you restore the zero value at ``0x60``. To be more precise, we only guarantee
safety when overwriting the zero pointer, if the remainder of the assembly snippet does not interact with the memory of
high-level Solidity objects (including by reading from offsets previously stored in variables).

---

### Brand Guide (`docs/brand-guide.rst`)

####################
Solidity Brand Guide
####################

This brand guide features information on Solidity's brand policy and
logo usage guidelines.

The Solidity Brand
==================

The Solidity programming language is an open-source, community project
governed by a core team. The core team is part of the `Argot Collective
<https://argot.org/>`_, a non-profit that develops and maintains Solidity.
The project was originally started at and sponsored by the `Ethereum
Foundation <https://ethereum.foundation/>`_.

This document aims to provide information about how to best use the
Solidity brand name and logo.

We encourage you to read this document carefully before using the
brand name or the logo. Your cooperation is highly appreciated!

Solidity Brand Name
===================

"Solidity" should be used to refer to the Solidity programming language
solely.

Please do not use "Solidity":

- To refer to any other programming language.

- In a way that is misleading or may imply association of unrelated
  modules, tools, documentation, or other resources with the Solidity
  programming language.

- In ways that confuse the community as to whether the Solidity
  programming language is open-source and free to use.

Solidity Logo License
=====================

.. image:: https://i.creativecommons.org/l/by/4.0/88x31.png
  :width: 88
  :alt: Creative Commons License

The Solidity logo is distributed and licensed under a `Creative Commons
Attribution 4.0 International License <https://creativecommons.org/licenses/by/4.0/>`_.

This is the most permissive Creative Commons license and allows reuse
and modifications for any purpose.

You are free to:

- **Share** — Copy and redistribute the material in any medium or format.

- **Adapt** — Remix, transform, and build upon the material for any
  purpose, even commercially.

Under the following terms:

- **Attribution** — You must give appropriate credit, provide a link to
  the license, and indicate if changes were made. You may do so in any
  reasonable manner, but not in any way that suggests that the Solidity
  core team endorses you or your use.

When using the Solidity logo, please respect the Solidity logo guidelines.

Solidity Logo Guidelines
========================

.. image:: solidity_logo.svg
  :width: 256

*(Right click on the logo to download it.)*

Please do not:

- Change the ratio of the logo (do not stretch it or cut it).

- Change the colors of the logo, unless it is absolutely necessary.

Credits
=======

This document was, in parts, derived from the `Python Software
Foundation Trademark Usage Policy <https://www.python.org/psf/trademarks/>`_
and the `Rust Media Guide <https://www.rust-lang.org/policies/media-guide>`_.

---

### Bugs.Json (`docs/bugs.json`)

[
    {
        "uid": "SOL-2026-7",
        "name": "YulOptimizerKnowledgeBaseStaleBookkeeping",
        "summary": "The Yul optimizer could consider two memory or storage locations distinct even though their addresses were computed from different values of the same reassigned variable and coincided at runtime. This could lead to loads being replaced with outdated values and to needed stores being removed.",
        "description": "The Yul optimizer steps ``LoadResolver`` and ``EqualStoreEliminator`` keep track of what was stored in memory and storage. ``LoadResolver`` uses this to replace loads and ``keccak256`` calls with known values, and ``EqualStoreEliminator`` uses it to remove stores of a value that the location already contains. Whenever a store is encountered whose exact location cannot be determined, the optimizer has to forget what it knows about every location the store might overwrite. To decide this, the optimizer represents an address symbolically as a constant offset either from zero or from another variable (its base variable). Two addresses with the same base can then be determined to be distinct if their offsets differ (for storage) or are at least 32 bytes apart (for memory). These representations were cached per variable. The base variable, however, may be reassigned afterwards. The optimizer did not always notice and then compared an address computed from the old value of the base with an address computed from the new value as if both used the same base. As a result, it could consider two locations distinct even though they coincided at runtime, keeping a stale entry for a location that had just been overwritten. A subsequent load from that location could then be replaced with an outdated value, a subsequent store of that value to the location could be removed, and ``keccak256`` over the location could be replaced with the hash of an outdated value. Whether the bug is triggered depends on the structure of the intermediate code these optimizer steps receive. It is therefore sensitive to the optimizer sequence and to the surrounding code, and the two locations additionally have to coincide at runtime. In optimized IR code generation, any code may be affected, including code without inline assembly. In optimized evmasm code generation, only inline assembly that does not refer to any Solidity variables or functions and compiler-generated Yul utility functions could be affected. Unoptimized code is unaffected.",
        "link": "https://blog.soliditylang.org/2026/10/22/yul-optimizer-knowledge-base-stale-bookkeeping-bug/",
        "introduced": "0.8.19",
        "fixed": "0.8.38",
        "severity": "low",
        "conditions": {
            "yulOptimizer": true
        }
    },
    {
        "uid": "SOL-2026-6",
        "name": "MisorderedNamedParametersInRequireWithCustomErrors",
        "summary": "Custom error arguments passed to ``require`` using named-parameter syntax are ABI-encoded in call-site order instead of declaration order when compiling via IR.",
        "description": "When a custom error was passed into the second argument of ``require`` and instantiated using named parameter syntax (e.g., ``require(condition, MyError({b: 1, a: 2}))``), the IR-based code generator would pass the arguments to the ABI encoder in the order they appeared at the call site, without reordering them to match the error definition. The arguments were type-checked against the parameters with matching names, not the ones they were actually passed into by the codegen, so the bug would not result in a compilation error. Instead, the encoder would produce a structurally valid encoding matching the error signature but not reflecting the values used to instantiate the error. The arguments on the stack would be reordered and possibly reinterpreted as different types by the encoder. In case of reference types, the reinterpretation would result in the content being obtained from wrong offsets in memory, storage or calldata. In some cases large values misinterpreted as offsets or lengths would make the encoder revert due to running out of gas. Types that occupy more than one slot on the stack would further complicate the behavior by leading to not only reordering but also misalignment of argument boundaries. The only unaffected types were string literals, which are not being passed to the encoder through the stack. The bug was specific to custom errors passed as the second argument of ``require``. Standalone ``revert ErrorName({...})`` statements, event emissions, function calls, struct constructor invocations and other constructs supporting named parameters were not affected. The evmasm pipeline was also unaffected.",
        "link": "https://blog.soliditylang.org/2026/09/10/misordered-named-parameters-in-require-with-custom-errors-bug/",
        "introduced": "0.8.26",
        "fixed": "0.8.37",
        "severity": "very low",
        "conditions": {
            "viaIR": true
        }
    },
    {
        "uid": "SOL-2026-5",
        "name": "MemoryByteArrayElementDeleteClearsWholeWord",
        "summary": "Applying ``delete`` to a single element of a ``bytes`` array in memory clears not only that element but the whole 32-byte word starting at the element's location, zeroing up to 31 bytes beyond the element.",
        "description": "Elements of ``bytes`` arrays in memory are packed, each occupying a single byte. When a value is assigned to such an element, the evmasm code generator correctly stores it with a single-byte ``MSTORE8`` instruction. The code path in the evmasm pipeline implementing ``delete`` on such an element, however, wrote the zero value with a full-word ``MSTORE``, clearing the 32 bytes starting at the element's location. The bytes following the element within the array were silently zeroed. If the element was within the last 31 bytes of the array's allocation, the write also extended past it into the area where the allocator places the next memory object, clearing the most significant bytes of that object's first word. How many elements are in reach depends on the size of the allocation: arrays created with ``new bytes(n)`` or from literals occupy their length rounded up to a multiple of 32 bytes, so only elements falling within the last 31 bytes of that rounded-up area, if any, could be affected. The results of ``bytes.concat``, ``string.concat``, and the ``abi.encode*`` functions, on the other hand, are placed by the evmasm pipeline in an allocation of exactly the size of their data, so the next object starts immediately after their last element and each of their last 31 elements is in reach. Assigning zero to an element (``b[i] = 0``) was not affected, only the ``delete`` operator, and neither were byte arrays in transient storage, storage, or calldata. The bug exists only in the evmasm pipeline. Code compiled via IR is unaffected. Optimizer settings have no influence. The defective code predates the first released version of the compiler.",
        "link": "https://blog.soliditylang.org/2026/09/10/memory-byte-array-element-delete-clears-whole-word-bug/",
        "fixed": "0.8.37",
        "severity": "low/medium",
        "conditions": {
            "viaIR": false
        }
    },
    {
        "uid": "SOL-2026-4",
        "name": "SpillSlotCollisionAcrossMutualRecursion",
        "summary": "Local variables of two simultaneously active functions moved to fixed memory offsets by the stack limit evader may be assigned the same offset if the call graph contains mutual recursion, so that one variable is silently overwritten by the other.",
        "description": "To work around the 16-slot stack access limit of the EVM, the IR-based code generator can, under some preconditions, move local variables to fixed memory offsets. Variables that can never be active at the same time may safely share an offset, so the reserved memory area is sized by a depth-first walk of the call graph that computes for every node the number of slots it and its callees need. To keep this walk from descending infinitely into recursive call chains, the slot count was initialized with zero upon entering it. This provisional zero was observable: a function reached again through a call graph cycle reported an empty footprint to its caller, the caller's count was finalized and cached on that basis, and the undercount propagated to every later caller, including functions outside the cycle. As a result, a function called by such a cycle and a function calling into it could be assigned the same memory slot even though both can be active at the same time. A relocated variable still needed after the call into the cycle returned had then been silently overwritten by the called function, producing wrong results. Triggering the bug requires the IR pipeline and a call graph in which a cycle of at least two mutually recursive functions both reaches a function needing relocation of variables to memory and is entered from a separate call chain whose own relocated variable is read again after the call towards the cycle returns. From 0.8.21 onward, it is independent of whether the optimizer is enabled.",
        "link": "https://blog.soliditylang.org/2026/09/10/spill-slot-collision-across-mutual-recursion-bug/",
        "introduced": "0.7.2",
        "fixed": "0.8.37",
        "severity": "low/medium",
        "conditions": {
            "viaIR": true
        }
    },
    {
        "uid": "SOL-2026-3",
        "name": "InheritanceOrderReversalOnStorageEndWarning",
        "summary": "Emitting a warning about storage base location being too close to the storage end unintentionally reversed the ``linearizedBaseContracts`` annotation, possibly leading to miscompilation due to reversing the order in which inheritance is resolved.",
        "description": "When the compiler detects that a custom layout specifier puts contract's static storage area too close to the end of the address space, it emits a warning. To make the warning more useful, the compiler tries to point at the last storage variable in that area. For this reason it walks the linearized inheritance hierarchy in reverse (from the least to the most derived). The list is calculated once and stored in an AST annotation called ``linearizedBaseContracts``. The direct cause of the bug was the fact that the code that reverses the list was doing it in place rather than on a copy, modifying the annotation. This effectively reversed the order of base contracts seen by any component that runs after layout checks: later phases of analysis, AST export, code generator, SMTChecker, etc. The observable effect was a reversed order of state variable initialization, constructor invocation, virtual function/modifier resolution, leading either to miscompilations or internal compiler errors, depending on the specific usage. Since the source of the bug was in the analysis stage, it was independent of the codegen pipeline or optimizer settings. The main condition necessary to trigger the bug was the presence of the warning in the output. The other is presence of language constructs whose evaluation depends on the inheritance order. While potential effects are very serious, this requirement excludes the vast majority of contracts as intentionally placing the storage variables in the last 2**64 slots is highly discouraged, which was actually the main reason for adding this warning.",
        "link": "https://blog.soliditylang.org/2026/07/09/inheritance-order-reversal-on-storage-end-warning-bug/",
        "introduced": "0.8.29",
        "fixed": "0.8.36",
        "severity": "medium"
    },
    {
        "uid": "SOL-2026-2",
        "name": "UnsoundSpillInMutualRecursion",
        "summary": "Local variables of a function involved in mutual recursion may spuriously be moved to fixed memory offsets and overwritten across recursive calls.",
        "description": "To work around the 16-slot stack access limit of the EVM, the IR-based code generator can move local variables of stack-too-deep functions to fixed memory offsets. This relocation is unsound for recursive functions: a fixed offset would be shared by all activations of the function, so a recursive call would overwrite the caller's value. The stack limit evader therefore must not relocate variables of functions that are part of a recursive call chain. To this end, the call graph was searched for cycles using a path-based depth-first search that, once a function had been fully explored and popped from the search path, short-circuited on it on any later visit. As a result, a function shared between several intersecting cycles could be reached first through a path that did not yet close a cycle through it, get marked as finished, and then be skipped when a later path would have revealed that it does lie on a cycle. Such a function was misclassified as non-recursive. When a misclassified function was complex enough for the stack limit evader to relocate some of its variables, those variables were moved to fixed memory offsets and silently corrupted on recursion, producing wrong results rather than a compile-time error. Triggering the bug requires the IR pipeline, a set of mutually recursive functions whose call graph contains intersecting cycles, at least one of the functions in an undetected part of a cycle being complex enough to require relocation to memory, and an unfortunate processing order of the functions (which depends on the hashes of their Yul names). It is independent of whether the optimizer is enabled.",
        "link": "https://blog.soliditylang.org/2026/07/09/unsound-spill-in-mutual-recursion-bug/",
        "introduced": "0.7.2",
        "fixed": "0.8.36",
        "severity": "medium",
        "conditions": {
            "viaIR": true
        }
    },
    {
        "uid": "SOL-2026-1",
        "name": "TransientStorageClearingHelperCollision",
        "summary": "Clearing both storage and transient storage variables in the same contract may result in only one of these locations being cleared.",
        "description": "The IR-based code generator provides a set of Yul helper functions for basic operations, such as clearing, copying, encoding or type conversions. Not all functions are used by every contract. The codegen appends them to the generated sources individually, only when an operation that would invoke one of them is encountered. Utility functions are often specialized for different types and locations. Since Yul does not support generic functions, specialization is done by generating multiple versions of the same function, with the information distinguishing the variants embedded in their names. However, if not all the necessary bits of distinguishing information are properly accounted for, two helpers may end up with the same name, causing a collision. In this situation the codegen includes only one of them, with calls to both variants invoking it. This happened with the ``set_to_zero`` helper used when an area of transient or persistent storage needs to be cleared. The helper name was missing the location information, which resulted in a collision between the persistent and transient storage variants for the same type. This meant that contracts clearing both locations would actually clear only one, leaving the other untouched. Which location ended up being cleared depended on the order in which the code generator processed the input. The necessary condition to trigger the bug was the use of ``delete`` operator on a transient storage variable. This was due to value types being the only types supported in transient storage and ``delete`` being the only operation invoking the helper allowed on such types. The other necessary condition was clearing of persistent storage and in this case the range of affected operations was wider: operator ``delete``, array ``pop()`` or assignment that resulted in a longer array being overwritten with a shorter one. The cleared variable itself also did not necessarily have to be of the same type. It was enough that a matching value type was nested in it. It also did not always have to be the exact same value type - clearing operations on reference types are usually performed at slot granularity, treating every slot as ``uint256`` rather than clearing every value packed into it individually. To trigger the bug both operations had to be present within the same piece of bytecode. Independent contracts, not related through inheritance, would not affect each other this way. The presence of one operation only in creation code and the other only in deployed code would not trigger the bug either.",
        "link": "https://blog.soliditylang.org/2026/02/18/transient-storage-clearing-helper-collision-bug/",
        "introduced": "0.8.28",
        "fixed": "0.8.34",
        "severity": "high",
        "conditions": {
            "viaIR": true,
            "evmVersion": ">=cancun"
        }
    },
    {
        "uid": "SOL-2025-1",
        "name": "LostStorageArrayWriteOnSlotOverflow",
        "summary": "Operations that involve clearing or copying from arrays that straddle the end of storage could result in silent data retention.",
        "description": "Solidity makes it possible to define variables that extend past the last (2**256-th) slot of storage, which results in wrap-around back to slot zero. Since EVM uses 256-bit integer arithmetic, most operations on such variables just work. The only situation which requires special attention is iteration against absolute slot addresses: the invariant that the last slot belonging to a variable has the highest address does not hold. When implemented incorrectly, a loop over an array will immediately terminate if the container spans the end of storage - due to the initial position already being greater than the end position. This affected storage array clearing loops generated by both evmasm and IR pipelines. Additionally, (only in the evmasm pipeline) copying operations whose source was an array straddling the end of storage were also affected. At the language level, the buggy code would be generated for array assignment, array initialization, delete operator, <array>.pop() and <array>.push(). Note that a clearing loop is inserted by the compiler not only for invocations of the delete operator, but also to zero storage when overwriting a longer array with a shorter one, popping an element or even pushing an empty element to a dynamic array. Since clearing is a separate loop, it is possible for the bug to only affect it and not the copy operation it follows (which is always the case in the IR pipeline). The bug is extremely unlikely to be triggered accidentally due to the probabilistic impossibility of a short dynamic array being allocated right at the storage boundary. On the other hand, scenarios in which a user may place a static array there intentionally do not seem realistic and are limited to unusual layouts, in which a contract does not place any storage variables at slot zero (otherwise they would overlap the array).",
        "link": "https://blog.soliditylang.org/2025/12/18/lost-storage-array-write-on-slot-overflow-bug/",
        "introduced": "0.1.0",
        "fixed": "0.8.32",
        "severity": "low"
    },
    {
        "uid": "SOL-2023-3",
        "name": "VerbatimInvalidDeduplication",
        "summary": "All ``verbatim`` blocks are considered identical by deduplicator and can incorrectly be unified when surrounded by identical opcodes.",
        "description": "The block deduplicator is a step of the opcode-based optimizer which identifies equivalent assembly blocks and merges them into a single one. However, when blocks contained ``verbatim``, their comparison was performed incorrectly, leading to the collapse of assembly blocks which are identical except for the contents of the ``verbatim`` items. Since ``verbatim`` is only available in Yul, compilation of Solidity sources is not affected.",
        "link": "https://blog.soliditylang.org/2023/11/08/verbatim-invalid-deduplication-bug/",
        "introduced": "0.8.5",
        "fixed": "0.8.23",
        "severity": "low"
    },
    {
        "uid": "SOL-2023-2",
        "name": "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
        "summary": "Optimizer sequences containing FullInliner do not preserve the evaluation order of arguments of inlined function calls in code that is not in expression-split form.",
        "description": "Function call arguments in Yul are evaluated right to left. This order matters when the argument expressions have side-effects, and changing it may change contract behavior. FullInliner is an optimizer step that can replace a function call with the body of that function. The transformation involves assigning argument expressions to temporary variables, which imposes an explicit evaluation order. FullInliner was written with the assumption that this order does not necessarily have to match usual argument evaluation order because the argument expressions have no side-effects. In most circumstances this assumption is true because the default optimization step sequence contains the ExpressionSplitter step. ExpressionSplitter ensures that the code is in *expression-split form*, which means that function calls cannot appear nested inside expressions, and all function call arguments have to be variables. The assumption is, however, not guaranteed to be true in general. Version 0.6.7 introduced a setting allowing users to specify an arbitrary optimization step sequence, making it possible for the FullInliner to actually encounter argument expressions with side-effects, which can result in behavior differences between optimized and unoptimized bytecode. Contracts compiled without optimization or with the default optimization sequence are not affected. To trigger the bug the user has to explicitly choose compiler settings that contain a sequence with FullInliner step not preceded by ExpressionSplitter.",
        "link": "https://blog.soliditylang.org/2023/07/19/full-inliner-non-expression-split-argument-evaluation-order-bug/",
        "introduced": "0.6.7",
        "fixed": "0.8.21",
        "severity": "low",
        "conditions": {
            "yulOptimizer": true
        }
    },
    {
        "uid": "SOL-2023-1",
        "name": "MissingSideEffectsOnSelectorAccess",
        "summary": "Accessing the ``.selector`` member on complex expressions leaves the expression unevaluated in the legacy code generation.",
        "description": "When accessing the ``.selector`` member on an expression with side-effects, like an assignment, a function call or a conditional, the expression would not be evaluated in the legacy code generation. This would happen in expressions where the functions used in the expression were all known at compilation time, regardless of whether the whole expression could be evaluated at compilation time or not. Note that the code generated by the IR pipeline was unaffected and would behave as expected.",
        "link": "https://blog.soliditylang.org/2023/07/19/missing-side-effects-on-selector-access-bug/",
        "introduced": "0.6.2",
        "fixed": "0.8.21",
        "severity": "low",
        "conditions": {
            "viaIR": false
        }
    },
    {
        "uid": "SOL-2022-7",
        "name": "StorageWriteRemovalBeforeConditionalTermination",
        "summary": "Calling functions that conditionally terminate the external EVM call using the assembly statements ``return(...)`` or ``stop()`` may result in incorrect removals of prior storage writes.",
        "description": "A call to a Yul function that conditionally terminates the external EVM call could result in prior storage writes being incorrectly removed by the Yul optimizer. This used to happen in cases in which it would have been valid to remove the store, if the Yul function in question never actually terminated the external call, and the control flow always returned back to the caller instead. Conditional termination within the same Yul block instead of within a called function was not affected. In Solidity with optimized via-IR code generation, any storage write before a function conditionally calling ``return(...)`` or ``stop()`` in inline assembly, may have been incorrectly removed, whenever it would have been valid to remove the write without the ``return(...)`` or ``stop()``. In optimized legacy code generation, only inline assembly that did not refer to any Solidity variables and that involved conditionally-terminating user-defined assembly functions could be affected.",
        "link": "https://blog.soliditylang.org/2022/09/08/storage-write-removal-before-conditional-termination/",
        "introduced": "0.8.13",
        "fixed": "0.8.17",
        "severity": "medium/high",
        "conditions": {
            "yulOptimizer": true
        }
    },
    {
        "uid": "SOL-2022-6",
        "name": "AbiReencodingHeadOverflowWithStaticArrayCleanup",
        "summary": "ABI-encoding a tuple with a statically-sized calldata array in the last component would corrupt 32 leading bytes of its first dynamically encoded component.",
        "description": "When ABI-encoding a statically-sized calldata array, the compiler always pads the data area to a multiple of 32-bytes and ensures that the padding bytes are zeroed. In some cases, this cleanup used to be performed by always writing exactly 32 bytes, regardless of how many needed to be zeroed. This was done with the assumption that the data that would eventually occupy the area past the end of the array had not yet been written, because the encoder processes tuple components in the order they were given. While this assumption is mostly true, there is an important corner case: dynamically encoded tuple components are stored separately from the statically-sized ones in an area called the *tail* of the encoding and the tail immediately follows the *head*, which is where the statically-sized components are placed. The aforementioned cleanup, if performed for the last component of the head would cross into the tail and overwrite up to 32 bytes of the first component stored there with zeros. The only array type for which the cleanup could actually result in an overwrite were arrays with ``uint256`` or ``bytes32`` as the base element type and in this case the size of the corrupted area was always exactly 32 bytes. The problem affected tuples at any nesting level. This included also structs, which are encoded as tuples in the ABI. Note also that lists of parameters and return values of functions, events and errors are encoded as tuples.",
        "link": "https://blog.soliditylang.org/2022/08/08/calldata-tuple-reencoding-head-overflow-bug/",
        "introduced": "0.5.8",
        "fixed": "0.8.16",
        "severity": "medium",
        "conditions": {
            "ABIEncoderV2": true
        }
    },
    {
        "uid": "SOL-2022-5",
        "name": "DirtyBytesArrayToStorage",
        "summary": "Copying ``bytes`` arrays from memory or calldata to storage may result in dirty storage values.",
        "description": "Copying ``bytes`` arrays from memory or calldata to storage is done in chunks of 32 bytes even if the length is not a multiple of 32. Thereby, extra bytes past the end of the array may be copied from calldata or memory to storage. These dirty bytes may then become observable after a ``.push()`` without arguments to the bytes array in storage, i.e. such a push will not result in a zero value at the end of the array as expected. This bug only affects the legacy code generation pipeline, the new code generation pipeline via IR is not affected.",
        "link": "https://blog.soliditylang.org/2022/06/15/dirty-bytes-array-to-storage-bug/",
        "introduced": "0.0.1",
        "fixed": "0.8.15",
        "severity": "low"
    },
    {
        "uid": "SOL-2022-4",
        "name": "InlineAssemblyMemorySideEffects",
        "summary": "The Yul optimizer may incorrectly remove memory writes from inline assembly blocks, that do not access solidity variables.",
        "description": "The Yul optimizer considers all memory writes in the outermost Yul block that are never read from as unused and removes them. This is valid when that Yul block is the entire Yul program, which is always the case for the Yul code generated by the new via-IR pipeline. Inline assembly blocks are never optimized in isolation when using that pipeline. Instead they are optimized as a part of the whole Yul input. However, the legacy code generation pipeline (which is still the default) runs the Yul optimizer individually on an inline assembly block if the block does not refer to any local variables defined in the surrounding Solidity code. Consequently, memory writes in such inline assembly blocks are removed as well, if the written memory is never read from in the same assembly block, even if the written memory is accessed later, for example by a subsequent inline assembly block.",
        "link": "https://blog.soliditylang.org/2022/06/15/inline-assembly-memory-side-effects-bug/",
        "introduced": "0.8.13",
        "fixed": "0.8.15",
        "severity": "medium",
        "conditions": {
            "yulOptimizer": true
        }
    },
    {
        "uid": "SOL-2022-3",
        "name": "DataLocationChangeInInternalOverride",
        "summary": "It was possible to change the data location of the parameters or return variables from ``calldata`` to ``memory`` and vice-versa while overriding internal and public functions. This caused invalid code to be generated when calling such a function internally through virtual function calls.",
        "description": "When calling external functions, it is irrelevant if the data location of the parameters is ``calldata`` or ``memory``, the encoding of the data does not change. Because of that, changing the data location when overriding external functions is allowed. The compiler incorrectly also allowed a change in the data location for overriding public and internal functions. Since public functions can be called internally as well as externally, this causes invalid code to be generated when such an incorrectly overridden function is called internally through the base contract. The caller provides a memory pointer, but the called function interprets it as a calldata pointer or vice-versa.",
        "link": "https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/",
        "introduced": "0.6.9",
        "fixed": "0.8.14",
        "severity": "very low"
    },
    {
        "uid": "SOL-2022-2",
        "name": "NestedCalldataArrayAbiReencodingSizeValidation",
        "summary": "ABI-reencoding of nested dynamic calldata arrays did not always perform proper size checks against the size of calldata and could read beyond ``calldatasize()``.",
        "description": "Calldata validation for nested dynamic types is deferred until the first access to the nested values. Such an access may for example be a copy to memory or an index or member access to the outer type. While in most such accesses calldata validation correctly checks that the data area of the nested array is completely contained in the passed calldata (i.e. in the range [0, calldatasize()]), this check may not be performed, when ABI encoding such nested types again directly from calldata. For instance, this can happen, if a value in calldata with a nested dynamic array is passed to an external call, used in ``abi.encode`` or emitted as event. In such cases, if the data area of the nested array extends beyond ``calldatasize()``, ABI encoding it did not revert, but continued reading values from beyond ``calldatasize()`` (i.e. zero values).",
        "link": "https://blog.soliditylang.org/2022/05/17/calldata-reencode-size-check-bug/",
        "introduced": "0.5.8",
        "fixed": "0.8.14",
        "severity": "very low"
    },
    {
        "uid": "SOL-2022-1",
        "name": "AbiEncodeCallLiteralAsFixedBytesBug",
        "summary": "Literals used for a fixed length bytes parameter in ``abi.encodeCall`` were encoded incorrectly.",
        "description": "For the encoding, the compiler only considered the types of the expressions in the second argument of ``abi.encodeCall`` itself, but not the parameter types of the function given as first argument. In almost all cases the abi encoding of the type of the expression matches the abi encoding of the parameter type of the given function. This is because the type checker ensures the expression is implicitly convertible to the respective parameter type. However this is not true for number literals used for fixed bytes types shorter than 32 bytes, nor for string literals used for any fixed bytes type. Number literals were encoded as numbers instead of being shifted to become left-aligned. String literals were encoded as dynamically sized memory strings instead of being converted to a left-aligned bytes value.",
        "link": "https://blog.soliditylang.org/2022/03/16/encodecall-bug/",
        "introduced": "0.8.11",
        "fixed": "0.8.13",
        "severity": "very low"
    },
    {
        "uid": "SOL-2021-4",
        "name": "UserDefinedValueTypesBug",
        "summary": "User defined value types with underlying type shorter than 32 bytes used incorrect storage layout and wasted storage",
        "description": "The compiler did not correctly compute the storage layout of user defined value types based on types that are shorter than 32 bytes. It would always use a full storage slot for these types, even if the underlying type was shorter. This was wasteful and might have problems with tooling or contract upgrades.",
        "link": "https://blog.soliditylang.org/2021/09/29/user-defined-value-types-bug/",
        "introduced": "0.8.8",
        "fixed": "0.8.9",
        "severity": "very low"
    },
    {
        "uid": "SOL-2021-3",
        "name": "SignedImmutables",
        "summary": "Immutable variables of signed integer type shorter than 256 bits can lead to values with invalid higher order bits if inline assembly is used.",
        "description": "When immutable variables of signed integer type shorter than 256 bits are read, their higher order bits were unconditionally set to zero. The correct operation would be to sign-extend the value, i.e. set the higher order bits to one if the sign bit is one. This sign-extension is performed by Solidity just prior to when it matters, i.e. when a value is stored in memory, when it is compared or when a division is performed. Because of that, to our knowledge, the only way to access the value in its unclean state is by reading it through inline assembly.",
        "link": "https://blog.soliditylang.org/2021/09/29/signed-immutables-bug/",
        "introduced": "0.6.5",
        "fixed": "0.8.9",
        "severity": "very low"
    },
    {
        "uid": "SOL-2021-2",
        "name": "ABIDecodeTwoDimensionalArrayMemory",
        "summary": "If used on memory byte arrays, result of the function ``abi.decode`` can depend on the contents of memory outside of the actual byte array that is decoded.",
        "description": "The ABI specification uses pointers to data areas for everything that is dynamically-sized. When decoding data from memory (instead of calldata), the ABI decoder did not properly validate some of these pointers. More specifically, it was possible to use large values for the pointers inside arrays such that computing the offset resulted in an undetected overflow. This could lead to these pointers targeting areas in memory outside of the actual area to be decoded. This way, it was possible for ``abi.decode`` to return different values for the same encoded byte array.",
        "link": "https://blog.soliditylang.org/2021/04/21/decoding-from-memory-bug/",
        "introduced": "0.4.16",
        "fixed": "0.8.4",
        "conditions": {
            "ABIEncoderV2": true
        },
        "severity": "very low"
    },
    {
        "uid": "SOL-2021-1",
        "name": "KeccakCaching",
        "summary": "The bytecode optimizer incorrectly reused previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.",
        "description": "Solidity's bytecode optimizer has a step that can compute Keccak-256 hashes, if the contents of the memory are known during compilation time. This step also has a mechanism to determine that two Keccak-256 hashes are equal even if the values in memory are not known during compile time. This mechanism had a bug where Keccak-256 of the same memory content, but different sizes were considered equal. More specifically, ``keccak256(mpos1, length1)`` and ``keccak256(mpos2, length2)`` in some cases were considered equal if ``length1`` and ``length2``, when rounded up to nearest multiple of 32 were the same, and when the memory contents at ``mpos1`` and ``mpos2`` can be deduced to be equal. You maybe affected if you compute multiple Keccak-256 hashes of the same content, but with different lengths inside inline assembly. You are unaffected if your code uses ``keccak256`` with a length that is not a compile-time constant or if it is always a multiple of 32.",
        "link": "https://blog.soliditylang.org/2021/03/23/keccak-optimizer-bug/",
        "fixed": "0.8.3",
        "conditions": {
            "optimizer": true
        },
        "severity": "medium"
    },
    {
        "uid": "SOL-2020-11",
        "name": "EmptyByteArrayCopy",
        "summary": "Copying an empty byte array (or string) from memory or calldata to storage can result in data corruption if the target array's length is increased subsequently without storing new data.",
        "description": "The routine that copies byte arrays from memory or calldata to storage stores unrelated data from after the source array in the storage slot if the source array is empty. If the storage array's length is subsequently increased either by using ``.push()`` or by assigning to its ``.length`` attribute (only before 0.6.0), the newly created byte array elements will not be zero-initialized, but contain the unrelated data. You are not affected if you do not assign to ``.length`` and do not use ``.push()`` on byte arrays, or only use ``.push(<arg>)`` or manually initialize the new elements.",
        "link": "https://blog.soliditylang.org/2020/10/19/empty-byte-array-copy-bug/",
        "fixed": "0.7.4",
        "severity": "medium"
    },
    {
        "uid": "SOL-2020-10",
        "name": "DynamicArrayCleanup",
        "summary": "When assigning a dynamically-sized array with types of size at most 16 bytes in storage causing the assigned array to shrink, some parts of deleted slots were not zeroed out.",
        "description": "Consider a dynamically-sized array in storage whose base-type is small enough such that multiple values can be packed into a single slot, such as `uint128[]`. Let us define its length to be `l`. When this array gets assigned from another array with a smaller length, say `m`, the slots between elements `m` and `l` have to be cleaned by zeroing them out. However, this cleaning was not performed properly. Specifically, after the slot corresponding to `m`, only the first packed value was cleaned up. If this array gets resized to a length larger than `m`, the indices corresponding to the unclean parts of the slot contained the original value, instead of 0. The resizing here is performed by assigning to the array `length`, by a `push()` or via inline assembly. You are not affected if you are only using `.push(<arg>)` or if you assign a value (even zero) to the new elements after increasing the length of the array.",
        "link": "https://blog.soliditylang.org/2020/10/07/solidity-dynamic-array-cleanup-bug/",
        "fixed": "0.7.3",
        "severity": "medium"
    },
    {
        "uid": "SOL-2020-9",
        "name": "FreeFunctionRedefinition",
        "summary": "The compiler does not flag an error when two or more free functions with the same name and parameter types are defined in a source unit or when an imported free function alias shadows another free function with a different name but identical parameter types.",
        "description": "In contrast to functions defined inside contracts, free functions with identical names and parameter types did not create an error. Both definition of free functions with identical name and parameter types and an imported free function with an alias that shadows another function with a different name but identical parameter types were permitted due to which a call to either the multiply defined free function or the imported free function alias within a contract led to the execution of that free function which was defined first within the source unit. Subsequently defined identical free function definitions were silently ignored and their code generation was skipped.",
        "introduced": "0.7.1",
        "fixed": "0.7.2",
        "severity": "low"
    },
    {
        "uid": "SOL-2020-8",
        "name": "UsingForCalldata",
        "summary": "Function calls to internal library functions with calldata parameters called via ``using for`` can result in invalid data being read.",
        "description": "Function calls to internal library functions using the ``using for`` mechanism copied all calldata parameters to memory first and passed them on like that, regardless of whether it was an internal or an external call. Due to that, the called function would receive a memory pointer that is interpreted as a calldata pointer. Since dynamically sized arrays are passed using two stack slots for calldata, but only one for memory, this can lead to stack corruption. An affected library call will consider the JUMPDEST to which it is supposed to return as part of its arguments and will instead jump out to whatever was on the stack before the call.",
        "introduced": "0.6.9",
        "fixed": "0.6.10",
        "severity": "very low"
    },
    {
        "uid": "SOL-2020-7",
        "name": "MissingEscapingInFormatting",
        "summary": "String literals containing double backslash characters passed directly to external or encoding function calls can lead to a different string being used when ABIEncoderV2 is enabled.",
        "description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intermediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.",
        "introduced": "0.5.14",
        "fixed": "0.6.8",
        "severity": "very low",
        "conditions": {
            "ABIEncoderV2": true
        }
    },
    {
        "uid": "SOL-2020-6",
        "name": "ArraySliceDynamicallyEncodedBaseType",
        "summary": "Accessing array slices of arrays with dynamically encoded base types (e.g. multi-dimensional arrays) can result in invalid data being read.",
        "description": "For arrays with dynamically sized base types, index range accesses that use a start expression that is non-zero will result in invalid array slices. Any index access to such array slices will result in data being read from incorrect calldata offsets. Array slices are only supported for dynamic calldata types and all problematic type require ABIEncoderV2 to be enabled.",
        "introduced": "0.6.0",
        "fixed": "0.6.8",
        "severity": "very low",
        "conditions": {
            "ABIEncoderV2": true
        }
    },
    {
        "uid": "SOL-2020-5",
        "name": "ImplicitConstructorCallvalueCheck",
        "summary": "The creation code of a contract that does not define a constructor but has a base that does define a constructor did not revert for calls with non-zero value.",
        "description": "Starting from Solidity 0.4.5 the creation code of contracts without explicit payable constructor is supposed to contain a callvalue check that results in contract creation reverting, if non-zero value is passed. However, this check was missing in case no explicit constructor was defined in a contract at all, but the contract has a base that does define a constructor. In these cases it is possible to send value in a contract creation transaction or using inline assembly without revert, even though the creation code is supposed to be non-payable.",
        "introduced": "0.4.5",
        "fixed": "0.6.8",
        "severity": "very low"
    },
    {
        "uid": "SOL-2020-4",
        "name": "TupleAssignmentMultiStackSlotComponents",
        "summary": "Tuple assignments with components that occupy several stack slots, i.e. nested tuples, pointers to external functions or references to dynamically sized calldata arrays, can result in invalid values.",
        "description": "Tuple assignments did not correctly account for tuple components that occupy multiple stack slots in case the number of stack slots differs between left-hand-side and right-hand-side. This can either happen in the presence of nested tuples or if the right-hand-side contains external function pointers or references to dynamic calldata arrays, while the left-hand-side contains an omission.",
        "introduced": "0.1.6",
        "fixed": "0.6.6",
        "severity": "very low"
    },
    {
        "uid": "SOL-2020-3",
        "name": "MemoryArrayCreationOverflow",
        "summary": "The creation of very large memory arrays can result in overlapping memory regions and thus memory corruption.",
        "description": "No runtime overflow checks were performed for the length of memory arrays during creation. In cases for which the memory size of an array in bytes, i.e. the array length times 32, is larger than 2^256-1, the memory allocation will overflow, potentially resulting in overlapping memory areas. The length of the array is still stored correctly, so copying or iterating over such an array will result in out-of-gas.",
        "link": "https://blog.soliditylang.org/2020/04/06/memory-creation-overflow-bug/",
        "introduced": "0.2.0",
        "fixed": "0.6.5",
        "severity": "low"
    },
    {
        "uid": "SOL-2020-1",
        "name": "YulOptimizerRedundantAssignmentBreakContinue",
        "summary": "The Yul optimizer can remove essential assignments to variables declared inside for loops when Yul's continue or break statement is used. You are unlikely to be affected if you do not use inline assembly with for loops and continue and break statements.",
        "description": "The Yul optimizer has a stage that removes assignments to variables that are overwritten again or are not used in all following control-flow branches. This logic incorrectly removes such assignments to variables declared inside a for loop if they can be removed in a control-flow branch that ends with ``break`` or ``continue`` even though they cannot be removed in other control-flow branches. Variables declared outside of the respective for loop are not affected.",
        "introduced": "0.6.0",
        "fixed": "0.6.1",
        "severity": "medium",
        "conditions": {
            "yulOptimizer": true
        }
    },
    {
        "uid": "SOL-2020-2",
        "name": "privateCanBeOverridden",
        "summary": "Private methods can be overridden by inheriting contracts.",
        "description": "While private methods of base contracts are not visible and cannot be called directly from the derived contract, it is still possible to declare a function of the same name and type and thus change the behaviour of the base contract's function.",
        "introduced": "0.3.0",
        "fixed": "0.5.17",
        "severity": "low"
    },
    {
        "uid": "SOL-2020-1",
        "name": "YulOptimizerRedundantAssignmentBreakContinue0.5",
        "summary": "The Yul optimizer can remove essential assignments to variables declared inside for loops when Yul's continue or break statement is used. You are unlikely to be affected if you do not use inline assembly with for loops and continue and break statements.",
        "description": "The Yul optimizer has a stage that removes assignments to variables that are overwritten again or are not used in all following control-flow branches. This logic incorrectly removes such assignments to variables declared inside a for loop if they can be removed in a control-flow branch that ends with ``break`` or ``continue`` even though they cannot be removed in other control-flow branches. Variables declared outside of the respective for loop are not affected.",
        "introduced": "0.5.8",
        "fixed": "0.5.16",
        "severity": "low",
        "conditions": {
            "yulOptimizer": true
        }
    },
    {
        "uid": "SOL-2019-10",
        "name": "ABIEncoderV2LoopYulOptimizer",
        "summary": "If both the experimental ABIEncoderV2 and the experimental Yul optimizer are activated, one component of the Yul optimizer may reuse data in memory that has been changed in the meantime.",
        "description": "The Yul optimizer incorrectly replaces ``mload`` and ``sload`` calls with values that have been previously written to the load location (and potentially changed in the meantime) if all of the following conditions are met: (1) there is a matching ``mstore`` or ``sstore`` call before; (2) the contents of memory or storage is only changed in a function that is called (directly or indirectly) in between the first store and the load call; (3) called function contains a for loop where the same memory location is changed in the condition or the post or body block. When used in Solidity mode, this can only happen if the experimental ABIEncoderV2 is activated and the experimental Yul optimizer has been activated manually in addition to the regular optimizer in the compiler settings.",
        "introduced": "0.5.14",
        "fixed": "0.5.15",
        "severity": "low",
        "conditions": {
            "ABIEncoderV2": true,
            "optimizer": true,
            "yulOptimizer": true
        }
    },
    {
        "uid": "SOL-2019-9",
        "name": "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
        "summary": "Reading from calldata structs that contain dynamically encoded, but statically-sized members can result in incorrect values.",
        "description": "When a calldata struct contains a dynamically encoded, but statically-sized member, the offsets for all subsequent struct members are calculated incorrectly. All reads from such members will result in invalid values. Only calldata structs are affected, i.e. this occurs in external functions with such structs as argument. Using affected structs in storage or memory or as arguments to public functions on the other hand works correctly.",
        "introduced": "0.5.6",
        "fixed": "0.5.11",
        "severity": "low",
        "conditions": {
            "ABIEncoderV2": true
        }
    },
    {
        "uid": "SOL-2019-8",
        "name": "SignedArrayStorageCopy",
        "summary": "Assigning an array of signed integers to a storage array of different type can lead to data corruption in that array.",
        "description": "In two's complement, negative integers have their higher order bits set. In order to fit into a shared storage slot, these have to be set to zero. When a conversion is done at the same time, the bits to set to zero were incorrectly determined from the source and not the target type. This means that such copy operations can lead to incorrect values being stored.",
        "link": "https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/",
        "introduced": "0.4.7",
        "fixed": "0.5.10",
        "severity": "low/medium"
    },
    {
        "uid": "SOL-2019-7",
        "name": "ABIEncoderV2StorageArrayWithMultiSlotElement",
        "summary": "Storage arrays containing structs or other statically-sized arrays are not read properly when directly encoded in external function calls or in abi.encode*.",
        "description": "When storage arrays whose elements occupy more than a single storage slot are directly encoded in external function calls or using abi.encode*, their elements are read in an overlapping manner, i.e. the element pointer is not properly advanced between reads. This is not a problem when the storage data is first copied to a memory variable or if the storage array only contains value types or dynamically-sized arrays.",
        "link": "https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/",
        "introduced": "0.4.16",
        "fixed": "0.5.10",
        "severity": "low",
        "conditions": {
            "ABIEncoderV2": true
        }
    },
    {
        "uid": "SOL-2019-6",
        "name": "DynamicConstructorArgumentsClippedABIV2",
        "summary": "A contract's constructor that takes structs or arrays that contain dynamically-sized arrays reverts or decodes to invalid data.",
        "description": "During construction of a contract, constructor parameters are copied from the code section to memory for decoding. The amount of bytes to copy was calculated incorrectly in case all parameters are statically-sized but contain dynamically-sized arrays as struct members or inner arrays. Such types are only available if ABIEncoderV2 is activated.",
        "introduced": "0.4.16",
        "fixed": "0.5.9",
        "severity": "very low",
        "conditions": {
            "ABIEncoderV2": true
        }
    },
    {
        "uid": "SOL-2019-5",
        "name": "UninitializedFunctionPointerInConstructor",
        "summary": "Calling uninitialized internal function pointers created in the constructor does not always revert and can cause unexpected behaviour.",
        "description": "Uninitialized internal function pointers point to a special piece of code that causes a revert when called. Jump target positions are different during construction and after deployment, but the code for setting this special jump target only considered the situation after deployment.",
        "introduced": "0.5.0",
        "fixed": "0.5.8",
        "severity": "very low"
    },
    {
        "uid": "SOL-2019-5",
        "name": "UninitializedFunctionPointerInConstructor_0.4.x",
        "summary": "Calling uninitialized internal function pointers created in the constructor does not always revert and can cause unexpected behaviour.",
        "description": "Uninitialized internal function pointers point to a special piece of code that causes a revert when called. Jump target positions are different during construction and after deployment, but the code for setting this special jump target only considered the situation after deployment.",
        "introduced": "0.4.5",
        "fixed": "0.4.26",
        "severity": "very low"
    },
    {
        "uid": "SOL-2019-4",
        "name": "IncorrectEventSignatureInLibraries",
        "summary": "Contract types used in events in libraries cause an incorrect event signature hash",
        "description": "Instead of using the type `address` in the hashed signature, the actual contract name was used, leading to a wrong hash in the logs.",
        "introduced": "0.5.0",
        "fixed": "0.5.8",
        "severity": "very low"
    },
    {
        "uid": "SOL-2019-4",
        "name": "IncorrectEventSignatureInLibraries_0.4.x",
        "summary": "Contract types used in events in libraries cause an incorrect event signature hash",
        "description": "Instead of using the type `address` in the hashed signature, the actual contract name was used, leading to a wrong hash in the logs.",
        "introduced": "0.3.0",
        "fixed": "0.4.26",
        "severity": "very low"
    },
    {
        "uid": "SOL-2019-3",
        "name": "ABIEncoderV2PackedStorage",
        "summary": "Storage structs and arrays with types shorter than 32 bytes can cause data corruption if encoded directly from storage using the experimental ABIEncoderV2.",
        "description": "Elements of structs and arrays that are shorter than 32 bytes are not properly decoded from storage when encoded directly (i.e. not via a memory type) using ABIEncoderV2. This can cause corruption in the values themselves but can also overwrite other parts of the encoded data.",
        "link": "https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/",
        "introduced": "0.5.0",
        "fixed": "0.5.7",
        "severity": "low",
        "conditions": {
            "ABIEncoderV2": true
        }
    },
    {
        "uid": "SOL-2019-3",
        "name": "ABIEncoderV2PackedStorage_0.4.x",
        "summary": "Storage structs and arrays with types shorter than 32 bytes can cause data corruption if encoded directly from storage using the experimental ABIEncoderV2.",
        "description": "Elements of structs and arrays that are shorter than 32 bytes are not properly decoded from storage when encoded directly (i.e. not via a memory type) using ABIEncoderV2. This can cause corruption in the values themselves but can also overwrite other parts of the encoded data.",
        "link": "https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/",
        "introduced": "0.4.19",
        "fixed": "0.4.26",
        "severity": "low",
        "conditions": {
            "ABIEncoderV2": true
        }
    },
    {
        "uid": "SOL-2019-2",
        "name": "IncorrectByteInstructionOptimization",
        "summary": "The optimizer incorrectly handles byte opcodes whose second argument is 31 or a constant expression that evaluates to 31. This can result in unexpected values.",
        "description": "The optimizer incorrectly handles byte opcodes that use the constant 31 as second argument. This can happen when performing index access on bytesNN types with a compile-time constant value (not index) of 31 or when using the byte opcode in inline assembly.",
        "link": "https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/",
        "introduced": "0.5.5",
        "fixed": "0.5.7",
        "severity": "very low",
        "conditions": {
            "optimizer": true
        }
    },
    {
        "uid": "SOL-2019-1",
        "name": "DoubleShiftSizeOverflow",
        "summary": "Double bitwise shifts by large constants whose sum overflows 256 bits can result in unexpected values.",
        "description": "Nested logical shift operations whose total shift size is 2**256 or more are incorrectly optimized. This only applies to shifts by numbers of bits that are compile-time constant expressions.",
        "link": "https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/",
        "introduced": "0.5.5",
        "fixed": "0.5.6",
        "severity": "low",
        "conditions": {
            "optimizer": true,
            "evmVersion": ">=constantinople"
        }
    },
    {
        "uid": "SOL-2018-4",
        "name": "ExpExponentCleanup",
        "summary": "Using the ** operator with an exponent of type shorter than 256 bits can result in unexpected values.",
        "description": "Higher order bits in the exponent are not properly cleaned before the EXP opcode is applied if the type of the exponent expression is smaller than 256 bits and not smaller than the type of the base. In that case, the result might be larger than expected if the exponent is assumed to lie within the value range of the type. Literal numbers as exponents are unaffected as are exponents or bases of type uint256.",
        "link": "https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/",
        "fixed": "0.4.25",
        "severity": "medium/high",
        "check": {
            "regex-source": "[^/]\\*\\* *[^/0-9 ]"
        }
    },
    {
        "uid": "SOL-2018-3",
        "name": "EventStructWrongData",
        "summary": "Using structs in events logged wrong data.",
        "description": "If a struct is used in an event, the address of the struct is logged instead of the actual data.",
        "link": "https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/",
        "introduced": "0.4.17",
        "fixed": "0.4.25",
        "severity": "very low",
        "check": {
            "ast-compact-json-path": "$..[?(@.nodeType === 'EventDefinition')]..[?(@.nodeType === 'UserDefinedTypeName' && @.typeDescriptions.typeString.startsWith('struct'))]"
        }
    },
    {
        "uid": "SOL-2018-2",
        "name": "NestedArrayFunctionCallDecoder",
        "summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.",
        "description": "If Solidity code calls a function that returns a multi-dimensional fixed-size array, array elements are incorrectly interpreted as memory pointers and thus can cause memory corruption if the return values are accessed. Calling functions with multi-dimensional fixed-size arrays is unaffected as is returning fixed-size arrays from function calls. The regular expression only checks if such functions are present, not if they are called, which is required for the contract to be affected.",
        "link": "https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/",
        "introduced": "0.1.4",
        "fixed": "0.4.22",
        "severity": "medium",
        "check": {
            "regex-source": "returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]"
        }
    },
    {
        "uid": "SOL-2018-1",
        "name": "OneOfTwoConstructorsSkipped",
        "summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.",
        "description": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored. There will be a compiler warning about the old-style constructor, so contracts only using new-style constructors are fine.",
        "introduced": "0.4.22",
        "fixed": "0.4.23",
        "severity": "very low"
    },
    {
        "uid": "SOL-2017-5",
        "name": "ZeroFunctionSelector",
        "summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.",
        "description": "If a function has a selector consisting only of zeros, is payable and part of a contract that does not have a fallback function and at most five external functions in total, this function is called instead of the fallback function if Ether is sent to the contract without data.",
        "fixed": "0.4.18",
        "severity": "very low"
    },
    {
        "uid": "SOL-2017-4",
        "name": "DelegateCallReturnValue",
        "summary": "The low-level .delegatecall() does not return the execution outcome, but converts the value returned by the functioned called to a boolean instead.",
        "description": "The return value of the low-level .delegatecall() function is taken from a position in memory, where the call data or the return data resides. This value is interpreted as a boolean and put onto the stack. This means if the called function returns at least 32 zero bytes, .delegatecall() returns false even if the call was successful.",
        "introduced": "0.3.0",
        "fixed": "0.4.15",
        "severity": "low"
    },
    {
        "uid": "SOL-2017-3",
        "name": "ECRecoverMalformedInput",
        "summary": "The ecrecover() builtin can return garbage for malformed input.",
        "description": "The ecrecover precompile does not properly signal failure for malformed input (especially in the 'v' argument) and thus the Solidity function can return data that was previously present in the return area in memory.",
        "fixed": "0.4.14",
        "severity": "medium"
    },
    {
        "uid": "SOL-2017-2",
        "name": "SkipEmptyStringLiteral",
        "summary": "If \"\" is used in a function call, the following function arguments will not be correctly passed to the function.",
        "description": "If the empty string literal \"\" is used as an argument in a function call, it is skipped by the encoder. This has the effect that the encoding of all arguments following this is shifted left by 32 bytes and thus the function call data is corrupted.",
        "fixed": "0.4.12",
        "severity": "low"
    },
    {
        "uid": "SOL-2017-1",
        "name": "ConstantOptimizerSubtraction",
        "summary": "In some situations, the optimizer replaces certain numbers in the code with routines that compute different numbers.",
        "description": "The optimizer tries to represent any number in the bytecode by routines that compute them with less gas. For some special numbers, an incorrect routine is generated. This could allow an attacker to e.g. trick victims about a specific amount of ether, or function calls to call different functions (or none at all).",
        "link": "https://blog.soliditylang.org/2017/05/03/solidity-optimizer-bug/",
        "fixed": "0.4.11",
        "severity": "low",
        "conditions": {
            "optimizer": true
        }
    },
    {
        "uid": "SOL-2016-11",
        "name": "IdentityPrecompileReturnIgnored",
        "summary": "Failure of the identity precompile was ignored.",
        "description": "Calls to the identity contract, which is used for copying memory, ignored its return value. On the public chain, calls to the identity precompile can be made in a way that they never fail, but this might be different on private chains.",
        "severity": "low",
        "fixed": "0.4.7"
    },
    {
        "uid": "SOL-2016-10",
        "name": "OptimizerStateKnowledgeNotResetForJumpdest",
        "summary": "The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.",
        "description": "The optimizer performs symbolic execution at certain stages. At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges. Computing this common state was simplified to just use the empty state, but this implementation was not done properly. This bug can cause data corruption.",
        "severity": "medium",
        "introduced": "0.4.5",
        "fixed": "0.4.6",
        "conditions": {
            "optimizer": true
        }
    },
    {
        "uid": "SOL-2016-9",
        "name": "HighOrderByteCleanStorage",
        "summary": "For short types, the high order bytes were not cleaned properly and could overwrite existing data.",
        "description": "Types shorter than 32 bytes are packed together into the same 32 byte storage slot, but storage writes always write 32 bytes. For some types, the higher order bytes were not cleaned properly, which made it sometimes possible to overwrite a variable in storage when writing to another one.",
        "link": "https://blog.soliditylang.org/2016/11/01/security-alert-solidity-variables-can-overwritten-storage/",
        "severity": "high",
        "introduced": "0.1.6",
        "fixed": "0.4.4"
    },
    {
        "uid": "SOL-2016-8",
        "name": "OptimizerStaleKnowledgeAboutSHA3",
        "summary": "The optimizer did not properly reset its knowledge about SHA3 operations resulting in some hashes (also used for storage variable positions) not being calculated correctly.",
        "description": "The optimizer performs symbolic execution in order to save re-evaluating expressions whose value is already known. This knowledge was not properly reset across control flow paths and thus the optimizer sometimes thought that the result of a SHA3 operation is already present on the stack. This could result in data corruption by accessing the wrong storage slot.",
        "severity": "medium",
        "fixed": "0.4.3",
        "conditions": {
            "optimizer": true
        }
    },
    {
        "uid": "SOL-2016-7",
        "name": "LibrariesNotCallableFromPayableFunctions",
        "summary": "Library functions threw an exception when called from a call that received Ether.",
        "description": "Library functions are protected against sending them Ether through a call. Since the DELEGATECALL opcode forwards the information about how much Ether was sent with a call, the library function incorrectly assumed that Ether was sent to the library and threw an exception.",
        "severity": "low",
        "introduced": "0.4.0",
        "fixed": "0.4.2"
    },
    {
        "uid": "SOL-2016-6",
        "name": "SendFailsForZeroEther",
        "summary": "The send function did not provide enough gas to the recipient if no Ether was sent with it.",
        "description": "The recipient of an Ether transfer automatically receives a certain amount of gas from the EVM to handle the transfer. In the case of a zero-transfer, this gas is not provided which causes the recipient to throw an exception.",
        "severity": "low",
        "fixed": "0.4.0"
    },
    {
        "uid": "SOL-2016-5",
        "name": "DynamicAllocationInfiniteLoop",
        "summary": "Dynamic allocation of an empty memory array caused an infinite loop and thus an exception.",
        "description": "Memory arrays can be created provided a length. If this length is zero, code was generated that did not terminate and thus consumed all gas.",
        "severity": "low",
        "fixed": "0.3.6"
    },
    {
        "uid": "SOL-2016-4",
        "name": "OptimizerClearStateOnCodePathJoin",
        "summary": "The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.",
        "description": "The optimizer performs symbolic execution at certain stages. At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges. Computing this common state was not done correctly. This bug can cause data corruption, but it is probably quite hard to use for targeted attacks.",
        "severity": "low",
        "fixed": "0.3.6",
        "conditions": {
            "optimizer": true
        }
    },
    {
        "uid": "SOL-2016-3",
        "name": "CleanBytesHigherOrderBits",
        "summary": "The higher order bits of short bytesNN types were not cleaned before comparison.",
        "description": "Two variables of type bytesNN were considered different if their higher order bits, which are not part of the actual value, were different. An attacker might use this to reach seemingly unreachable code paths by providing incorrectly formatted input data.",
        "severity": "medium/high",
        "fixed": "0.3.3"
    },
    {
        "uid": "SOL-2016-2",
        "name": "ArrayAccessCleanHigherOrderBits",
        "summary": "Access to array elements for arrays of types with less than 32 bytes did not correctly clean the higher order bits, causing corruption in other array elements.",
        "description": "Multiple elements of an array of values that are shorter than 17 bytes are packed into the same storage slot. Writing to a single element of such an array did not properly clean the higher order bytes and thus could lead to data corruption.",
        "severity": "medium/high",
        "fixed": "0.3.1"
    },
    {
        "uid": "SOL-2016-1",
        "name": "AncientCompiler",
        "summary": "This compiler version is ancient and might contain several undocumented or undiscovered bugs.",
        "description": "The list of bugs is only kept for compiler versions starting from 0.3.0, so older versions might contain undocumented bugs.",
        "severity": "high",
        "fixed": "0.3.0"
    }
]

---

### Bugs (`docs/bugs.rst`)

.. index:: Bugs

.. _known_bugs:

##################
List of Known Bugs
##################

Below, you can find a JSON-formatted list of some of the known security-relevant bugs in the
Solidity compiler. The file itself is hosted in the `GitHub repository
<https://github.com/argotorg/solidity/blob/develop/docs/bugs.json>`_.
The list stretches back as far as version 0.3.0, bugs known to be present only
in versions preceding that are not listed.

There is another file called `bugs_by_version.json
<https://github.com/argotorg/solidity/blob/develop/docs/bugs_by_version.json>`_,
which can be used to check which bugs affect a specific version of the compiler.

When reporting a security-relevant bug, please make sure that the behavior is unintentional and outside of documented language guarantees.
Some regularly misreported behaviors are collected in :ref:`Frequently Reported Non-Bugs<frequently-reported-non-bugs>`.

Contract source verification tools and also other tools interacting with
contracts should consult this list according to the following criteria:

- It is mildly suspicious if a contract was compiled with a nightly
  compiler version instead of a released version. This list does not keep
  track of unreleased or nightly versions.
- It is also mildly suspicious if a contract was compiled with a version that was
  not the most recent at the time the contract was created. For contracts
  created from other contracts, you have to follow the creation chain
  back to a transaction and use the date of that transaction as creation date.
- It is highly suspicious if a contract was compiled with a compiler that
  contains a known bug and the contract was created at a time where a newer
  compiler version containing a fix was already released.

The JSON file of known bugs below is an array of objects, one for each bug,
with the following keys:

uid
    Unique identifier given to the bug in the form of ``SOL-<year>-<number>``.
    It is possible that multiple entries exists with the same uid. This means
    multiple version ranges are affected by the same bug.
name
    Unique name given to the bug
summary
    Short description of the bug
description
    Detailed description of the bug
link
    URL of a website with more detailed information, optional
introduced
    The first published compiler version that contained the bug, optional
fixed
    The first published compiler version that did not contain the bug anymore
publish
    The date at which the bug became known publicly, optional
severity
    Severity of the bug: very low, low, medium, high. Takes into account
    discoverability in contract tests, likelihood of occurrence and
    potential damage by exploits.
conditions
    Conditions that have to be met to trigger the bug. The following
    keys can be used:
    ``optimizer``, Boolean value which
    means that the optimizer has to be switched on to enable the bug.
    ``evmVersion``, a string that indicates which EVM version compiler
    settings trigger the bug. The string can contain comparison
    operators. For example, ``">=constantinople"`` means that the bug
    is present when the EVM version is set to ``constantinople`` or
    later.
    If no conditions are given, assume that the bug is present.
check
    This field contains different checks that report whether the smart contract
    contains the bug or not. The first type of check are JavaScript regular
    expressions that are to be matched against the source code ("source-regex")
    if the bug is present.  If there is no match, then the bug is very likely
    not present. If there is a match, the bug might be present.  For improved
    accuracy, the checks should be applied to the source code after stripping
    comments.
    The second type of check are patterns to be checked on the compact AST of
    the Solidity program ("ast-compact-json-path"). The specified search query
    is a `JsonPath <https://github.com/json-path/JsonPath>`_ expression.
    If at least one path of the Solidity AST matches the query, the bug is
    likely present.

.. literalinclude:: bugs.json
   :language: js

---

### Bugs.Yaml (`docs/bugs.yaml`)

- uid: SOL-2026-7
  name: YulOptimizerKnowledgeBaseStaleBookkeeping
  summary: >-
    The Yul optimizer could consider two memory or storage locations distinct even though their addresses were computed from different values of the same reassigned variable and coincided at runtime.
    This could lead to loads being replaced with outdated values and to needed stores being removed.
  description: >-
    The Yul optimizer steps ``LoadResolver`` and ``EqualStoreEliminator`` keep track of what was stored in memory and storage.
    ``LoadResolver`` uses this to replace loads and ``keccak256`` calls with known values, and ``EqualStoreEliminator`` uses it to remove stores of a value that the location already contains.
    Whenever a store is encountered whose exact location cannot be determined, the optimizer has to forget what it knows about every location the store might overwrite.
    To decide this, the optimizer represents an address symbolically as a constant offset either from zero or from another variable (its base variable).
    Two addresses with the same base can then be determined to be distinct if their offsets differ (for storage) or are at least 32 bytes apart (for memory).
    These representations were cached per variable.
    The base variable, however, may be reassigned afterwards.
    The optimizer did not always notice and then compared an address computed from the old value of the base with an address computed from the new value as if both used the same base.
    As a result, it could consider two locations distinct even though they coincided at runtime, keeping a stale entry for a location that had just been overwritten.
    A subsequent load from that location could then be replaced with an outdated value, a subsequent store of that value to the location could be removed, and ``keccak256`` over the location could be replaced with the hash of an outdated value.
    Whether the bug is triggered depends on the structure of the intermediate code these optimizer steps receive.
    It is therefore sensitive to the optimizer sequence and to the surrounding code, and the two locations additionally have to coincide at runtime.
    In optimized IR code generation, any code may be affected, including code without inline assembly.
    In optimized evmasm code generation, only inline assembly that does not refer to any Solidity variables or functions and compiler-generated Yul utility functions could be affected.
    Unoptimized code is unaffected.
  link: https://blog.soliditylang.org/2026/10/22/yul-optimizer-knowledge-base-stale-bookkeeping-bug/
  introduced: 0.8.19
  fixed: 0.8.38
  severity: low
  conditions:
    yulOptimizer: true

- uid: SOL-2026-6
  name: MisorderedNamedParametersInRequireWithCustomErrors
  summary: >-
    Custom error arguments passed to ``require`` using named-parameter syntax are ABI-encoded in call-site order instead of declaration order when compiling via IR.
  description: >-
    When a custom error was passed into the second argument of ``require`` and instantiated using named parameter syntax (e.g., ``require(condition, MyError({b: 1, a: 2}))``), the IR-based code generator would pass the arguments to the ABI encoder in the order they appeared at the call site, without reordering them to match the error definition.
    The arguments were type-checked against the parameters with matching names, not the ones they were actually passed into by the codegen, so the bug would not result in a compilation error.
    Instead, the encoder would produce a structurally valid encoding matching the error signature but not reflecting the values used to instantiate the error.
    The arguments on the stack would be reordered and possibly reinterpreted as different types by the encoder.
    In case of reference types, the reinterpretation would result in the content being obtained from wrong offsets in memory, storage or calldata.
    In some cases large values misinterpreted as offsets or lengths would make the encoder revert due to running out of gas.
    Types that occupy more than one slot on the stack would further complicate the behavior by leading to not only reordering but also misalignment of argument boundaries.
    The only unaffected types were string literals, which are not being passed to the encoder through the stack.
    The bug was specific to custom errors passed as the second argument of ``require``.
    Standalone ``revert ErrorName({...})`` statements, event emissions, function calls, struct constructor invocations and other constructs supporting named parameters were not affected.
    The evmasm pipeline was also unaffected.
  link: https://blog.soliditylang.org/2026/09/10/misordered-named-parameters-in-require-with-custom-errors-bug/
  introduced: 0.8.26
  fixed: 0.8.37
  severity: very low
  conditions:
    viaIR: true

- uid: SOL-2026-5
  name: MemoryByteArrayElementDeleteClearsWholeWord
  summary: >-
    Applying ``delete`` to a single element of a ``bytes`` array in memory clears not only that element but the whole 32-byte word starting at the element's location, zeroing up to 31 bytes beyond the element.
  description: >-
    Elements of ``bytes`` arrays in memory are packed, each occupying a single byte.
    When a value is assigned to such an element, the evmasm code generator correctly stores it with a single-byte ``MSTORE8`` instruction.
    The code path in the evmasm pipeline implementing ``delete`` on such an element, however, wrote the zero value with a full-word ``MSTORE``, clearing the 32 bytes starting at the element's location.
    The bytes following the element within the array were silently zeroed.
    If the element was within the last 31 bytes of the array's allocation, the write also extended past it into the area where the allocator places the next memory object, clearing the most significant bytes of that object's first word.
    How many elements are in reach depends on the size of the allocation: arrays created with ``new bytes(n)`` or from literals occupy their length rounded up to a multiple of 32 bytes, so only elements falling within the last 31 bytes of that rounded-up area, if any, could be affected.
    The results of ``bytes.concat``, ``string.concat``, and the ``abi.encode*`` functions, on the other hand, are placed by the evmasm pipeline in an allocation of exactly the size of their data, so the next object starts immediately after their last element and each of their last 31 elements is in reach.
    Assigning zero to an element (``b[i] = 0``) was not affected, only the ``delete`` operator, and neither were byte arrays in transient storage, storage, or calldata.
    The bug exists only in the evmasm pipeline.
    Code compiled via IR is unaffected.
    Optimizer settings have no influence.
    The defective code predates the first released version of the compiler.
  link: https://blog.soliditylang.org/2026/09/10/memory-byte-array-element-delete-clears-whole-word-bug/
  fixed: 0.8.37
  severity: low/medium
  conditions:
    viaIR: false

- uid: SOL-2026-4
  name: SpillSlotCollisionAcrossMutualRecursion
  summary: >-
    Local variables of two simultaneously active functions moved to fixed memory offsets by the stack limit evader may be assigned the same offset if the call graph contains mutual recursion, so that one variable is silently overwritten by the other.
  description: >-
    To work around the 16-slot stack access limit of the EVM, the IR-based code generator can, under some preconditions, move local variables to fixed memory offsets.
    Variables that can never be active at the same time may safely share an offset, so the reserved memory area is sized by a depth-first walk of the call graph that computes for every node the number of slots it and its callees need.
    To keep this walk from descending infinitely into recursive call chains, the slot count was initialized with zero upon entering it.
    This provisional zero was observable: a function reached again through a call graph cycle reported an empty footprint to its caller, the caller's count was finalized and cached on that basis, and the undercount propagated to every later caller, including functions outside the cycle.
    As a result, a function called by such a cycle and a function calling into it could be assigned the same memory slot even though both can be active at the same time.
    A relocated variable still needed after the call into the cycle returned had then been silently overwritten by the called function, producing wrong results.
    Triggering the bug requires the IR pipeline and a call graph in which a cycle of at least two mutually recursive functions both reaches a function needing relocation of variables to memory and is entered from a separate call chain whose own relocated variable is read again after the call towards the cycle returns.
    From 0.8.21 onward, it is independent of whether the optimizer is enabled.
  link: https://blog.soliditylang.org/2026/09/10/spill-slot-collision-across-mutual-recursion-bug/
  introduced: 0.7.2
  fixed: 0.8.37
  severity: low/medium
  conditions:
    viaIR: true

- uid: SOL-2026-3
  name: InheritanceOrderReversalOnStorageEndWarning
  summary: >-
    Emitting a warning about storage base location being too close to the storage end unintentionally reversed the ``linearizedBaseContracts`` annotation, possibly leading to miscompilation due to reversing the order in which inheritance is resolved.
  description: >-
    When the compiler detects that a custom layout specifier puts contract's static storage area too close to the end of the address space, it emits a warning.
    To make the warning more useful, the compiler tries to point at the last storage variable in that area.
    For this reason it walks the linearized inheritance hierarchy in reverse (from the least to the most derived).
    The list is calculated once and stored in an AST annotation called ``linearizedBaseContracts``.
    The direct cause of the bug was the fact that the code that reverses the list was doing it in place rather than on a copy, modifying the annotation.
    This effectively reversed the order of base contracts seen by any component that runs after layout checks: later phases of analysis, AST export, code generator, SMTChecker, etc.
    The observable effect was a reversed order of state variable initialization, constructor invocation, virtual function/modifier resolution, leading either to miscompilations or internal compiler errors, depending on the specific usage.
    Since the source of the bug was in the analysis stage, it was independent of the codegen pipeline or optimizer settings.
    The main condition necessary to trigger the bug was the presence of the warning in the output.
    The other is presence of language constructs whose evaluation depends on the inheritance order.
    While potential effects are very serious, this requirement excludes the vast majority of contracts as intentionally placing the storage variables in the last 2**64 slots is highly discouraged, which was actually the main reason for adding this warning.
  link: https://blog.soliditylang.org/2026/07/09/inheritance-order-reversal-on-storage-end-warning-bug/
  introduced: 0.8.29
  fixed: 0.8.36
  severity: medium

- uid: SOL-2026-2
  name: UnsoundSpillInMutualRecursion
  summary: >-
    Local variables of a function involved in mutual recursion may spuriously be moved to fixed memory offsets and overwritten across recursive calls.
  description: >-
    To work around the 16-slot stack access limit of the EVM, the IR-based code generator can move local variables of stack-too-deep functions to fixed memory offsets.
    This relocation is unsound for recursive functions: a fixed offset would be shared by all activations of the function, so a recursive call would overwrite the caller's value.
    The stack limit evader therefore must not relocate variables of functions that are part of a recursive call chain.
    To this end, the call graph was searched for cycles using a path-based depth-first search that, once a function had been fully explored and popped from the search path, short-circuited on it on any later visit.
    As a result, a function shared between several intersecting cycles could be reached first through a path that did not yet close a cycle through it, get marked as finished, and then be skipped when a later path would have revealed that it does lie on a cycle.
    Such a function was misclassified as non-recursive.
    When a misclassified function was complex enough for the stack limit evader to relocate some of its variables, those variables were moved to fixed memory offsets and silently corrupted on recursion, producing wrong results rather than a compile-time error.
    Triggering the bug requires the IR pipeline, a set of mutually recursive functions whose call graph contains intersecting cycles, at least one of the functions in an undetected part of a cycle being complex enough to require relocation to memory, and an unfortunate processing order of the functions (which depends on the hashes of their Yul names).
    It is independent of whether the optimizer is enabled.
  link: https://blog.soliditylang.org/2026/07/09/unsound-spill-in-mutual-recursion-bug/
  introduced: 0.7.2
  fixed: 0.8.36
  severity: medium
  conditions:
    viaIR: true

- uid: SOL-2026-1
  name: TransientStorageClearingHelperCollision
  summary: >-
    Clearing both storage and transient storage variables in the same contract may result in only one of these locations being cleared.
  description: >-
    The IR-based code generator provides a set of Yul helper functions for basic operations, such as clearing, copying, encoding or type conversions.
    Not all functions are used by every contract.
    The codegen appends them to the generated sources individually, only when an operation that would invoke one of them is encountered.
    Utility functions are often specialized for different types and locations.
    Since Yul does not support generic functions, specialization is done by generating multiple versions of the same function, with the information distinguishing the variants embedded in their names.
    However, if not all the necessary bits of distinguishing information are properly accounted for, two helpers may end up with the same name, causing a collision.
    In this situation the codegen includes only one of them, with calls to both variants invoking it.
    This happened with the ``set_to_zero`` helper used when an area of transient or persistent storage needs to be cleared.
    The helper name was missing the location information, which resulted in a collision between the persistent and transient storage variants for the same type.
    This meant that contracts clearing both locations would actually clear only one, leaving the other untouched.
    Which location ended up being cleared depended on the order in which the code generator processed the input.
    The necessary condition to trigger the bug was the use of ``delete`` operator on a transient storage variable.
    This was due to value types being the only types supported in transient storage and ``delete`` being the only operation invoking the helper allowed on such types.
    The other necessary condition was clearing of persistent storage and in this case the range of affected operations was wider: operator ``delete``, array ``pop()`` or assignment that resulted in a longer array being overwritten with a shorter one.
    The cleared variable itself also did not necessarily have to be of the same type.
    It was enough that a matching value type was nested in it.
    It also did not always have to be the exact same value type - clearing operations on reference types are usually performed at slot granularity, treating every slot as ``uint256`` rather than clearing every value packed into it individually.
    To trigger the bug both operations had to be present within the same piece of bytecode.
    Independent contracts, not related through inheritance, would not affect each other this way.
    The presence of one operation only in creation code and the other only in deployed code would not trigger the bug either.
  link: https://blog.soliditylang.org/2026/02/18/transient-storage-clearing-helper-collision-bug/
  introduced: 0.8.28
  fixed: 0.8.34
  severity: high
  conditions:
    viaIR: true
    evmVersion: '>=cancun'

- uid: SOL-2025-1
  name: LostStorageArrayWriteOnSlotOverflow
  summary: >-
    Operations that involve clearing or copying from arrays that straddle the end of storage could result in silent data retention.
  description: >-
    Solidity makes it possible to define variables that extend past the last (2**256-th) slot of storage, which results in wrap-around back to slot zero.
    Since EVM uses 256-bit integer arithmetic, most operations on such variables just work.
    The only situation which requires special attention is iteration against absolute slot addresses: the invariant that the last slot belonging to a variable has the highest address does not hold.
    When implemented incorrectly, a loop over an array will immediately terminate if the container spans the end of storage - due to the initial position already being greater than the end position.
    This affected storage array clearing loops generated by both evmasm and IR pipelines.
    Additionally, (only in the evmasm pipeline) copying operations whose source was an array straddling the end of storage were also affected.
    At the language level, the buggy code would be generated for array assignment, array initialization, delete operator, <array>.pop() and <array>.push().
    Note that a clearing loop is inserted by the compiler not only for invocations of the delete operator, but also to zero storage when overwriting a longer array with a shorter one, popping an element or even pushing an empty element to a dynamic array.
    Since clearing is a separate loop, it is possible for the bug to only affect it and not the copy operation it follows (which is always the case in the IR pipeline).
    The bug is extremely unlikely to be triggered accidentally due to the probabilistic impossibility of a short dynamic array being allocated right at the storage boundary.
    On the other hand, scenarios in which a user may place a static array there intentionally do not seem realistic and are limited to unusual layouts, in which a contract does not place any storage variables at slot zero (otherwise they would overlap the array).
  link: https://blog.soliditylang.org/2025/12/18/lost-storage-array-write-on-slot-overflow-bug/
  introduced: 0.1.0
  fixed: 0.8.32
  severity: low

- uid: SOL-2023-3
  name: VerbatimInvalidDeduplication
  summary: >-
    All ``verbatim`` blocks are considered identical by deduplicator and can incorrectly be unified when surrounded by identical opcodes.
  description: >-
    The block deduplicator is a step of the opcode-based optimizer which identifies equivalent assembly blocks and merges them into a single one.
    However, when blocks contained ``verbatim``, their comparison was performed incorrectly, leading to the collapse of assembly blocks which are identical except for the contents of the ``verbatim`` items.
    Since ``verbatim`` is only available in Yul, compilation of Solidity sources is not affected.
  link: https://blog.soliditylang.org/2023/11/08/verbatim-invalid-deduplication-bug/
  introduced: 0.8.5
  fixed: 0.8.23
  severity: low

- uid: SOL-2023-2
  name: FullInlinerNonExpressionSplitArgumentEvaluationOrder
  summary: >-
    Optimizer sequences containing FullInliner do not preserve the evaluation order of arguments of inlined function calls in code that is not in expression-split form.
  description: >-
    Function call arguments in Yul are evaluated right to left.
    This order matters when the argument expressions have side-effects, and changing it may change contract behavior.
    FullInliner is an optimizer step that can replace a function call with the body of that function.
    The transformation involves assigning argument expressions to temporary variables, which imposes an explicit evaluation order.
    FullInliner was written with the assumption that this order does not necessarily have to match usual argument evaluation order because the argument expressions have no side-effects.
    In most circumstances this assumption is true because the default optimization step sequence contains the ExpressionSplitter step.
    ExpressionSplitter ensures that the code is in *expression-split form*, which means that function calls cannot appear nested inside expressions, and all function call arguments have to be variables.
    The assumption is, however, not guaranteed to be true in general.
    Version 0.6.7 introduced a setting allowing users to specify an arbitrary optimization step sequence, making it possible for the FullInliner to actually encounter argument expressions with side-effects, which can result in behavior differences between optimized and unoptimized bytecode.
    Contracts compiled without optimization or with the default optimization sequence are not affected.
    To trigger the bug the user has to explicitly choose compiler settings that contain a sequence with FullInliner step not preceded by ExpressionSplitter.
  link: https://blog.soliditylang.org/2023/07/19/full-inliner-non-expression-split-argument-evaluation-order-bug/
  introduced: 0.6.7
  fixed: 0.8.21
  severity: low
  conditions:
    yulOptimizer: true

- uid: SOL-2023-1
  name: MissingSideEffectsOnSelectorAccess
  summary: >-
    Accessing the ``.selector`` member on complex expressions leaves the expression unevaluated in the legacy code generation.
  description: >-
    When accessing the ``.selector`` member on an expression with side-effects, like an assignment, a function call or a conditional, the expression would not be evaluated in the legacy code generation.
    This would happen in expressions where the functions used in the expression were all known at compilation time, regardless of whether the whole expression could be evaluated at compilation time or not.
    Note that the code generated by the IR pipeline was unaffected and would behave as expected.
  link: https://blog.soliditylang.org/2023/07/19/missing-side-effects-on-selector-access-bug/
  introduced: 0.6.2
  fixed: 0.8.21
  severity: low
  conditions:
    viaIR: false

- uid: SOL-2022-7
  name: StorageWriteRemovalBeforeConditionalTermination
  summary: >-
    Calling functions that conditionally terminate the external EVM call using the assembly statements ``return(...)`` or ``stop()`` may result in incorrect removals of prior storage writes.
  description: >-
    A call to a Yul function that conditionally terminates the external EVM call could result in prior storage writes being incorrectly removed by the Yul optimizer.
    This used to happen in cases in which it would have been valid to remove the store, if the Yul function in question never actually terminated the external call, and the control flow always returned back to the caller instead.
    Conditional termination within the same Yul block instead of within a called function was not affected.
    In Solidity with optimized via-IR code generation, any storage write before a function conditionally calling ``return(...)`` or ``stop()`` in inline assembly, may have been incorrectly removed, whenever it would have been valid to remove the write without the ``return(...)`` or ``stop()``.
    In optimized legacy code generation, only inline assembly that did not refer to any Solidity variables and that involved conditionally-terminating user-defined assembly functions could be affected.
  link: https://blog.soliditylang.org/2022/09/08/storage-write-removal-before-conditional-termination/
  introduced: 0.8.13
  fixed: 0.8.17
  severity: medium/high
  conditions:
    yulOptimizer: true

- uid: SOL-2022-6
  name: AbiReencodingHeadOverflowWithStaticArrayCleanup
  summary: >-
    ABI-encoding a tuple with a statically-sized calldata array in the last component would corrupt 32 leading bytes of its first dynamically encoded component.
  description: >-
    When ABI-encoding a statically-sized calldata array, the compiler always pads the data area to a multiple of 32-bytes and ensures that the padding bytes are zeroed.
    In some cases, this cleanup used to be performed by always writing exactly 32 bytes, regardless of how many needed to be zeroed.
    This was done with the assumption that the data that would eventually occupy the area past the end of the array had not yet been written, because the encoder processes tuple components in the order they were given.
    While this assumption is mostly true, there is an important corner case: dynamically encoded tuple components are stored separately from the statically-sized ones in an area called the *tail* of the encoding and the tail immediately follows the *head*, which is where the statically-sized components are placed.
    The aforementioned cleanup, if performed for the last component of the head would cross into the tail and overwrite up to 32 bytes of the first component stored there with zeros.
    The only array type for which the cleanup could actually result in an overwrite were arrays with ``uint256`` or ``bytes32`` as the base element type and in this case the size of the corrupted area was always exactly 32 bytes.
    The problem affected tuples at any nesting level.
    This included also structs, which are encoded as tuples in the ABI.
    Note also that lists of parameters and return values of functions, events and errors are encoded as tuples.
  link: https://blog.soliditylang.org/2022/08/08/calldata-tuple-reencoding-head-overflow-bug/
  introduced: 0.5.8
  fixed: 0.8.16
  severity: medium
  conditions:
    ABIEncoderV2: true

- uid: SOL-2022-5
  name: DirtyBytesArrayToStorage
  summary: >-
    Copying ``bytes`` arrays from memory or calldata to storage may result in dirty storage values.
  description: >-
    Copying ``bytes`` arrays from memory or calldata to storage is done in chunks of 32 bytes even if the length is not a multiple of 32.
    Thereby, extra bytes past the end of the array may be copied from calldata or memory to storage.
    These dirty bytes may then become observable after a ``.push()`` without arguments to the bytes array in storage, i.e. such a push will not result in a zero value at the end of the array as expected.
    This bug only affects the legacy code generation pipeline, the new code generation pipeline via IR is not affected.
  link: https://blog.soliditylang.org/2022/06/15/dirty-bytes-array-to-storage-bug/
  introduced: 0.0.1
  fixed: 0.8.15
  severity: low

- uid: SOL-2022-4
  name: InlineAssemblyMemorySideEffects
  summary: >-
    The Yul optimizer may incorrectly remove memory writes from inline assembly blocks, that do not access solidity variables.
  description: >-
    The Yul optimizer considers all memory writes in the outermost Yul block that are never read from as unused and removes them.
    This is valid when that Yul block is the entire Yul program, which is always the case for the Yul code generated by the new via-IR pipeline.
    Inline assembly blocks are never optimized in isolation when using that pipeline.
    Instead they are optimized as a part of the whole Yul input.
    However, the legacy code generation pipeline (which is still the default) runs the Yul optimizer individually on an inline assembly block if the block does not refer to any local variables defined in the surrounding Solidity code.
    Consequently, memory writes in such inline assembly blocks are removed as well, if the written memory is never read from in the same assembly block, even if the written memory is accessed later, for example by a subsequent inline assembly block.
  link: https://blog.soliditylang.org/2022/06/15/inline-assembly-memory-side-effects-bug/
  introduced: 0.8.13
  fixed: 0.8.15
  severity: medium
  conditions:
    yulOptimizer: true

- uid: SOL-2022-3
  name: DataLocationChangeInInternalOverride
  summary: >-
    It was possible to change the data location of the parameters or return variables from ``calldata`` to ``memory`` and vice-versa while overriding internal and public functions.
    This caused invalid code to be generated when calling such a function internally through virtual function calls.
  description: >-
    When calling external functions, it is irrelevant if the data location of the parameters is ``calldata`` or ``memory``, the encoding of the data does not change.
    Because of that, changing the data location when overriding external functions is allowed.
    The compiler incorrectly also allowed a change in the data location for overriding public and internal functions.
    Since public functions can be called internally as well as externally, this causes invalid code to be generated when such an incorrectly overridden function is called internally through the base contract.
    The caller provides a memory pointer, but the called function interprets it as a calldata pointer or vice-versa.
  link: https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/
  introduced: 0.6.9
  fixed: 0.8.14
  severity: very low

- uid: SOL-2022-2
  name: NestedCalldataArrayAbiReencodingSizeValidation
  summary: >-
    ABI-reencoding of nested dynamic calldata arrays did not always perform proper size checks against the size of calldata and could read beyond ``calldatasize()``.
  description: >-
    Calldata validation for nested dynamic types is deferred until the first access to the nested values.
    Such an access may for example be a copy to memory or an index or member access to the outer type.
    While in most such accesses calldata validation correctly checks that the data area of the nested array is completely contained in the passed calldata (i.e. in the range [0, calldatasize()]), this check may not be performed, when ABI encoding such nested types again directly from calldata.
    For instance, this can happen, if a value in calldata with a nested dynamic array is passed to an external call, used in ``abi.encode`` or emitted as event.
    In such cases, if the data area of the nested array extends beyond ``calldatasize()``, ABI encoding it did not revert, but continued reading values from beyond ``calldatasize()`` (i.e. zero values).
  link: https://blog.soliditylang.org/2022/05/17/calldata-reencode-size-check-bug/
  introduced: 0.5.8
  fixed: 0.8.14
  severity: very low

- uid: SOL-2022-1
  name: AbiEncodeCallLiteralAsFixedBytesBug
  summary: >-
    Literals used for a fixed length bytes parameter in ``abi.encodeCall`` were encoded incorrectly.
  description: >-
    For the encoding, the compiler only considered the types of the expressions in the second argument of ``abi.encodeCall`` itself, but not the parameter types of the function given as first argument.
    In almost all cases the abi encoding of the type of the expression matches the abi encoding of the parameter type of the given function.
    This is because the type checker ensures the expression is implicitly convertible to the respective parameter type.
    However this is not true for number literals used for fixed bytes types shorter than 32 bytes, nor for string literals used for any fixed bytes type.
    Number literals were encoded as numbers instead of being shifted to become left-aligned.
    String literals were encoded as dynamically sized memory strings instead of being converted to a left-aligned bytes value.
  link: https://blog.soliditylang.org/2022/03/16/encodecall-bug/
  introduced: 0.8.11
  fixed: 0.8.13
  severity: very low

- uid: SOL-2021-4
  name: UserDefinedValueTypesBug
  summary: >-
    User defined value types with underlying type shorter than 32 bytes used incorrect storage layout and wasted storage
  description: >-
    The compiler did not correctly compute the storage layout of user defined value types based on types that are shorter than 32 bytes.
    It would always use a full storage slot for these types, even if the underlying type was shorter.
    This was wasteful and might have problems with tooling or contract upgrades.
  link: https://blog.soliditylang.org/2021/09/29/user-defined-value-types-bug/
  introduced: 0.8.8
  fixed: 0.8.9
  severity: very low

- uid: SOL-2021-3
  name: SignedImmutables
  summary: >-
    Immutable variables of signed integer type shorter than 256 bits can lead to values with invalid higher order bits if inline assembly is used.
  description: >-
    When immutable variables of signed integer type shorter than 256 bits are read, their higher order bits were unconditionally set to zero.
    The correct operation would be to sign-extend the value, i.e. set the higher order bits to one if the sign bit is one.
    This sign-extension is performed by Solidity just prior to when it matters, i.e. when a value is stored in memory, when it is compared or when a division is performed.
    Because of that, to our knowledge, the only way to access the value in its unclean state is by reading it through inline assembly.
  link: https://blog.soliditylang.org/2021/09/29/signed-immutables-bug/
  introduced: 0.6.5
  fixed: 0.8.9
  severity: very low

- uid: SOL-2021-2
  name: ABIDecodeTwoDimensionalArrayMemory
  summary: >-
    If used on memory byte arrays, result of the function ``abi.decode`` can depend on the contents of memory outside of the actual byte array that is decoded.
  description: >-
    The ABI specification uses pointers to data areas for everything that is dynamically-sized.
    When decoding data from memory (instead of calldata), the ABI decoder did not properly validate some of these pointers.
    More specifically, it was possible to use large values for the pointers inside arrays such that computing the offset resulted in an undetected overflow.
    This could lead to these pointers targeting areas in memory outside of the actual area to be decoded.
    This way, it was possible for ``abi.decode`` to return different values for the same encoded byte array.
  link: https://blog.soliditylang.org/2021/04/21/decoding-from-memory-bug/
  introduced: 0.4.16
  fixed: 0.8.4
  conditions:
    ABIEncoderV2: true
  severity: very low

- uid: SOL-2021-1
  name: KeccakCaching
  summary: >-
    The bytecode optimizer incorrectly reused previously evaluated Keccak-256 hashes.
    You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.
  description: >-
    Solidity's bytecode optimizer has a step that can compute Keccak-256 hashes, if the contents of the memory are known during compilation time.
    This step also has a mechanism to determine that two Keccak-256 hashes are equal even if the values in memory are not known during compile time.
    This mechanism had a bug where Keccak-256 of the same memory content, but different sizes were considered equal.
    More specifically, ``keccak256(mpos1, length1)`` and ``keccak256(mpos2, length2)`` in some cases were considered equal if ``length1`` and ``length2``, when rounded up to nearest multiple of 32 were the same, and when the memory contents at ``mpos1`` and ``mpos2`` can be deduced to be equal.
    You maybe affected if you compute multiple Keccak-256 hashes of the same content, but with different lengths inside inline assembly.
    You are unaffected if your code uses ``keccak256`` with a length that is not a compile-time constant or if it is always a multiple of 32.
  link: https://blog.soliditylang.org/2021/03/23/keccak-optimizer-bug/
  fixed: 0.8.3
  conditions:
    optimizer: true
  severity: medium

- uid: SOL-2020-11
  name: EmptyByteArrayCopy
  summary: >-
    Copying an empty byte array (or string) from memory or calldata to storage can result in data corruption if the target array's length is increased subsequently without storing new data.
  description: >-
    The routine that copies byte arrays from memory or calldata to storage stores unrelated data from after the source array in the storage slot if the source array is empty.
    If the storage array's length is subsequently increased either by using ``.push()`` or by assigning to its ``.length`` attribute (only before 0.6.0), the newly created byte array elements will not be zero-initialized, but contain the unrelated data.
    You are not affected if you do not assign to ``.length`` and do not use ``.push()`` on byte arrays, or only use ``.push(<arg>)`` or manually initialize the new elements.
  link: https://blog.soliditylang.org/2020/10/19/empty-byte-array-copy-bug/
  fixed: 0.7.4
  severity: medium

- uid: SOL-2020-10
  name: DynamicArrayCleanup
  summary: >-
    When assigning a dynamically-sized array with types of size at most 16 bytes in storage causing the assigned array to shrink, some parts of deleted slots were not zeroed out.
  description: >-
    Consider a dynamically-sized array in storage whose base-type is small enough such that multiple values can be packed into a single slot, such as `uint128[]`.
    Let us define its length to be `l`.
    When this array gets assigned from another array with a smaller length, say `m`, the slots between elements `m` and `l` have to be cleaned by zeroing them out.
    However, this cleaning was not performed properly.
    Specifically, after the slot corresponding to `m`, only the first packed value was cleaned up.
    If this array gets resized to a length larger than `m`, the indices corresponding to the unclean parts of the slot contained the original value, instead of 0.
    The resizing here is performed by assigning to the array `length`, by a `push()` or via inline assembly.
    You are not affected if you are only using `.push(<arg>)` or if you assign a value (even zero) to the new elements after increasing the length of the array.
  link: https://blog.soliditylang.org/2020/10/07/solidity-dynamic-array-cleanup-bug/
  fixed: 0.7.3
  severity: medium

- uid: SOL-2020-9
  name: FreeFunctionRedefinition
  summary: >-
    The compiler does not flag an error when two or more free functions with the same name and parameter types are defined in a source unit or when an imported free function alias shadows another free function with a different name but identical parameter types.
  description: >-
    In contrast to functions defined inside contracts, free functions with identical names and parameter types did not create an error.
    Both definition of free functions with identical name and parameter types and an imported free function with an alias that shadows another function with a different name but identical parameter types were permitted due to which a call to either the multiply defined free function or the imported free function alias within a contract led to the execution of that free function which was defined first within the source unit.
    Subsequently defined identical free function definitions were silently ignored and their code generation was skipped.
  introduced: 0.7.1
  fixed: 0.7.2
  severity: low

- uid: SOL-2020-8
  name: UsingForCalldata
  summary: >-
    Function calls to internal library functions with calldata parameters called via ``using for`` can result in invalid data being read.
  description: >-
    Function calls to internal library functions using the ``using for`` mechanism copied all calldata parameters to memory first and passed them on like that, regardless of whether it was an internal or an external call.
    Due to that, the called function would receive a memory pointer that is interpreted as a calldata pointer.
    Since dynamically sized arrays are passed using two stack slots for calldata, but only one for memory, this can lead to stack corruption.
    An affected library call will consider the JUMPDEST to which it is supposed to return as part of its arguments and will instead jump out to whatever was on the stack before the call.
  introduced: 0.6.9
  fixed: 0.6.10
  severity: very low

- uid: SOL-2020-7
  name: MissingEscapingInFormatting
  summary: >-
    String literals containing double backslash characters passed directly to external or encoding function calls can lead to a different string being used when ABIEncoderV2 is enabled.
  description: >-
    When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intermediate code.
    Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure.
    This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.
  introduced: 0.5.14
  fixed: 0.6.8
  severity: very low
  conditions:
    ABIEncoderV2: true

- uid: SOL-2020-6
  name: ArraySliceDynamicallyEncodedBaseType
  summary: >-
    Accessing array slices of arrays with dynamically encoded base types (e.g. multi-dimensional arrays) can result in invalid data being read.
  description: >-
    For arrays with dynamically sized base types, index range accesses that use a start expression that is non-zero will result in invalid array slices.
    Any index access to such array slices will result in data being read from incorrect calldata offsets.
    Array slices are only supported for dynamic calldata types and all problematic type require ABIEncoderV2 to be enabled.
  introduced: 0.6.0
  fixed: 0.6.8
  severity: very low
  conditions:
    ABIEncoderV2: true

- uid: SOL-2020-5
  name: ImplicitConstructorCallvalueCheck
  summary: >-
    The creation code of a contract that does not define a constructor but has a base that does define a constructor did not revert for calls with non-zero value.
  description: >-
    Starting from Solidity 0.4.5 the creation code of contracts without explicit payable constructor is supposed to contain a callvalue check that results in contract creation reverting, if non-zero value is passed.
    However, this check was missing in case no explicit constructor was defined in a contract at all, but the contract has a base that does define a constructor.
    In these cases it is possible to send value in a contract creation transaction or using inline assembly without revert, even though the creation code is supposed to be non-payable.
  introduced: 0.4.5
  fixed: 0.6.8
  severity: very low

- uid: SOL-2020-4
  name: TupleAssignmentMultiStackSlotComponents
  summary: >-
    Tuple assignments with components that occupy several stack slots, i.e. nested tuples, pointers to external functions or references to dynamically sized calldata arrays, can result in invalid values.
  description: >-
    Tuple assignments did not correctly account for tuple components that occupy multiple stack slots in case the number of stack slots differs between left-hand-side and right-hand-side.
    This can either happen in the presence of nested tuples or if the right-hand-side contains external function pointers or references to dynamic calldata arrays, while the left-hand-side contains an omission.
  introduced: 0.1.6
  fixed: 0.6.6
  severity: very low

- uid: SOL-2020-3
  name: MemoryArrayCreationOverflow
  summary: >-
    The creation of very large memory arrays can result in overlapping memory regions and thus memory corruption.
  description: >-
    No runtime overflow checks were performed for the length of memory arrays during creation.
    In cases for which the memory size of an array in bytes, i.e. the array length times 32, is larger than 2^256-1, the memory allocation will overflow, potentially resulting in overlapping memory areas.
    The length of the array is still stored correctly, so copying or iterating over such an array will result in out-of-gas.
  link: https://blog.soliditylang.org/2020/04/06/memory-creation-overflow-bug/
  introduced: 0.2.0
  fixed: 0.6.5
  severity: low

- uid: SOL-2020-1
  name: YulOptimizerRedundantAssignmentBreakContinue
  summary: >-
    The Yul optimizer can remove essential assignments to variables declared inside for loops when Yul's continue or break statement is used.
    You are unlikely to be affected if you do not use inline assembly with for loops and continue and break statements.
  description: >-
    The Yul optimizer has a stage that removes assignments to variables that are overwritten again or are not used in all following control-flow branches.
    This logic incorrectly removes such assignments to variables declared inside a for loop if they can be removed in a control-flow branch that ends with ``break`` or ``continue`` even though they cannot be removed in other control-flow branches.
    Variables declared outside of the respective for loop are not affected.
  introduced: 0.6.0
  fixed: 0.6.1
  severity: medium
  conditions:
    yulOptimizer: true

- uid: SOL-2020-2
  name: privateCanBeOverridden
  summary: >-
    Private methods can be overridden by inheriting contracts.
  description: >-
    While private methods of base contracts are not visible and cannot be called directly from the derived contract, it is still possible to declare a function of the same name and type and thus change the behaviour of the base contract's function.
  introduced: 0.3.0
  fixed: 0.5.17
  severity: low

- uid: SOL-2020-1
  name: YulOptimizerRedundantAssignmentBreakContinue0.5
  summary: >-
    The Yul optimizer can remove essential assignments to variables declared inside for loops when Yul's continue or break statement is used.
    You are unlikely to be affected if you do not use inline assembly with for loops and continue and break statements.
  description: >-
    The Yul optimizer has a stage that removes assignments to variables that are overwritten again or are not used in all following control-flow branches.
    This logic incorrectly removes such assignments to variables declared inside a for loop if they can be removed in a control-flow branch that ends with ``break`` or ``continue`` even though they cannot be removed in other control-flow branches.
    Variables declared outside of the respective for loop are not affected.
  introduced: 0.5.8
  fixed: 0.5.16
  severity: low
  conditions:
    yulOptimizer: true

- uid: SOL-2019-10
  name: ABIEncoderV2LoopYulOptimizer
  summary: >-
    If both the experimental ABIEncoderV2 and the experimental Yul optimizer are activated, one component of the Yul optimizer may reuse data in memory that has been changed in the meantime.
  description: >-
    The Yul optimizer incorrectly replaces ``mload`` and ``sload`` calls with values that have been previously written to the load location (and potentially changed in the meantime) if all of the following conditions are met: (1) there is a matching ``mstore`` or ``sstore`` call before; (2) the contents of memory or storage is only changed in a function that is called (directly or indirectly) in between the first store and the load call; (3) called function contains a for loop where the same memory location is changed in the condition or the post or body block.
    When used in Solidity mode, this can only happen if the experimental ABIEncoderV2 is activated and the experimental Yul optimizer has been activated manually in addition to the regular optimizer in the compiler settings.
  introduced: 0.5.14
  fixed: 0.5.15
  severity: low
  conditions:
    ABIEncoderV2: true
    optimizer: true
    yulOptimizer: true

- uid: SOL-2019-9
  name: ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers
  summary: >-
    Reading from calldata structs that contain dynamically encoded, but statically-sized members can result in incorrect values.
  description: >-
    When a calldata struct contains a dynamically encoded, but statically-sized member, the offsets for all subsequent struct members are calculated incorrectly.
    All reads from such members will result in invalid values.
    Only calldata structs are affected, i.e. this occurs in external functions with such structs as argument.
    Using affected structs in storage or memory or as arguments to public functions on the other hand works correctly.
  introduced: 0.5.6
  fixed: 0.5.11
  severity: low
  conditions:
    ABIEncoderV2: true

- uid: SOL-2019-8
  name: SignedArrayStorageCopy
  summary: >-
    Assigning an array of signed integers to a storage array of different type can lead to data corruption in that array.
  description: >-
    In two's complement, negative integers have their higher order bits set.
    In order to fit into a shared storage slot, these have to be set to zero.
    When a conversion is done at the same time, the bits to set to zero were incorrectly determined from the source and not the target type.
    This means that such copy operations can lead to incorrect values being stored.
  link: https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/
  introduced: 0.4.7
  fixed: 0.5.10
  severity: low/medium

- uid: SOL-2019-7
  name: ABIEncoderV2StorageArrayWithMultiSlotElement
  summary: >-
    Storage arrays containing structs or other statically-sized arrays are not read properly when directly encoded in external function calls or in abi.encode*.
  description: >-
    When storage arrays whose elements occupy more than a single storage slot are directly encoded in external function calls or using abi.encode*, their elements are read in an overlapping manner, i.e. the element pointer is not properly advanced between reads.
    This is not a problem when the storage data is first copied to a memory variable or if the storage array only contains value types or dynamically-sized arrays.
  link: https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/
  introduced: 0.4.16
  fixed: 0.5.10
  severity: low
  conditions:
    ABIEncoderV2: true

- uid: SOL-2019-6
  name: DynamicConstructorArgumentsClippedABIV2
  summary: >-
    A contract's constructor that takes structs or arrays that contain dynamically-sized arrays reverts or decodes to invalid data.
  description: >-
    During construction of a contract, constructor parameters are copied from the code section to memory for decoding.
    The amount of bytes to copy was calculated incorrectly in case all parameters are statically-sized but contain dynamically-sized arrays as struct members or inner arrays.
    Such types are only available if ABIEncoderV2 is activated.
  introduced: 0.4.16
  fixed: 0.5.9
  severity: very low
  conditions:
    ABIEncoderV2: true

- uid: SOL-2019-5
  name: UninitializedFunctionPointerInConstructor
  summary: >-
    Calling uninitialized internal function pointers created in the constructor does not always revert and can cause unexpected behaviour.
  description: >-
    Uninitialized internal function pointers point to a special piece of code that causes a revert when called.
    Jump target positions are different during construction and after deployment, but the code for setting this special jump target only considered the situation after deployment.
  introduced: 0.5.0
  fixed: 0.5.8
  severity: very low

- uid: SOL-2019-5
  name: UninitializedFunctionPointerInConstructor_0.4.x
  summary: >-
    Calling uninitialized internal function pointers created in the constructor does not always revert and can cause unexpected behaviour.
  description: >-
    Uninitialized internal function pointers point to a special piece of code that causes a revert when called.
    Jump target positions are different during construction and after deployment, but the code for setting this special jump target only considered the situation after deployment.
  introduced: 0.4.5
  fixed: 0.4.26
  severity: very low

- uid: SOL-2019-4
  name: IncorrectEventSignatureInLibraries
  summary: >-
    Contract types used in events in libraries cause an incorrect event signature hash
  description: >-
    Instead of using the type `address` in the hashed signature, the actual contract name was used, leading to a wrong hash in the logs.
  introduced: 0.5.0
  fixed: 0.5.8
  severity: very low

- uid: SOL-2019-4
  name: IncorrectEventSignatureInLibraries_0.4.x
  summary: >-
    Contract types used in events in libraries cause an incorrect event signature hash
  description: >-
    Instead of using the type `address` in the hashed signature, the actual contract name was used, leading to a wrong hash in the logs.
  introduced: 0.3.0
  fixed: 0.4.26
  severity: very low

- uid: SOL-2019-3
  name: ABIEncoderV2PackedStorage
  summary: >-
    Storage structs and arrays with types shorter than 32 bytes can cause data corruption if encoded directly from storage using the experimental ABIEncoderV2.
  description: >-
    Elements of structs and arrays that are shorter than 32 bytes are not properly decoded from storage when encoded directly (i.e. not via a memory type) using ABIEncoderV2.
    This can cause corruption in the values themselves but can also overwrite other parts of the encoded data.
  link: https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/
  introduced: 0.5.0
  fixed: 0.5.7
  severity: low
  conditions:
    ABIEncoderV2: true

- uid: SOL-2019-3
  name: ABIEncoderV2PackedStorage_0.4.x
  summary: >-
    Storage structs and arrays with types shorter than 32 bytes can cause data corruption if encoded directly from storage using the experimental ABIEncoderV2.
  description: >-
    Elements of structs and arrays that are shorter than 32 bytes are not properly decoded from storage when encoded directly (i.e. not via a memory type) using ABIEncoderV2.
    This can cause corruption in the values themselves but can also overwrite other parts of the encoded data.
  link: https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/
  introduced: 0.4.19
  fixed: 0.4.26
  severity: low
  conditions:
    ABIEncoderV2: true

- uid: SOL-2019-2
  name: IncorrectByteInstructionOptimization
  summary: >-
    The optimizer incorrectly handles byte opcodes whose second argument is 31 or a constant expression that evaluates to 31.
    This can result in unexpected values.
  description: >-
    The optimizer incorrectly handles byte opcodes that use the constant 31 as second argument.
    This can happen when performing index access on bytesNN types with a compile-time constant value (not index) of 31 or when using the byte opcode in inline assembly.
  link: https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/
  introduced: 0.5.5
  fixed: 0.5.7
  severity: very low
  conditions:
    optimizer: true

- uid: SOL-2019-1
  name: DoubleShiftSizeOverflow
  summary: >-
    Double bitwise shifts by large constants whose sum overflows 256 bits can result in unexpected values.
  description: >-
    Nested logical shift operations whose total shift size is 2**256 or more are incorrectly optimized.
    This only applies to shifts by numbers of bits that are compile-time constant expressions.
  link: https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/
  introduced: 0.5.5
  fixed: 0.5.6
  severity: low
  conditions:
    optimizer: true
    evmVersion: '>=constantinople'

- uid: SOL-2018-4
  name: ExpExponentCleanup
  summary: >-
    Using the ** operator with an exponent of type shorter than 256 bits can result in unexpected values.
  description: >-
    Higher order bits in the exponent are not properly cleaned before the EXP opcode is applied if the type of the exponent expression is smaller than 256 bits and not smaller than the type of the base.
    In that case, the result might be larger than expected if the exponent is assumed to lie within the value range of the type.
    Literal numbers as exponents are unaffected as are exponents or bases of type uint256.
  link: https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/
  fixed: 0.4.25
  severity: medium/high
  check:
    regex-source: '[^/]\*\* *[^/0-9 ]'

- uid: SOL-2018-3
  name: EventStructWrongData
  summary: >-
    Using structs in events logged wrong data.
  description: >-
    If a struct is used in an event, the address of the struct is logged instead of the actual data.
  link: https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/
  introduced: 0.4.17
  fixed: 0.4.25
  severity: very low
  check:
    ast-compact-json-path: $..[?(@.nodeType === 'EventDefinition')]..[?(@.nodeType === 'UserDefinedTypeName'
      && @.typeDescriptions.typeString.startsWith('struct'))]

- uid: SOL-2018-2
  name: NestedArrayFunctionCallDecoder
  summary: >-
    Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.
  description: >-
    If Solidity code calls a function that returns a multi-dimensional fixed-size array, array elements are incorrectly interpreted as memory pointers and thus can cause memory corruption if the return values are accessed.
    Calling functions with multi-dimensional fixed-size arrays is unaffected as is returning fixed-size arrays from function calls.
    The regular expression only checks if such functions are present, not if they are called, which is required for the contract to be affected.
  link: https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/
  introduced: 0.1.4
  fixed: 0.4.22
  severity: medium
  check:
    regex-source: returns[^;{]*\[\s*[^\] \t\r\n\v\f][^\]]*\]\s*\[\s*[^\] \t\r\n\v\f][^\]]*\][^{;]*[;{]

- uid: SOL-2018-1
  name: OneOfTwoConstructorsSkipped
  summary: >-
    If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.
  description: >-
    If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.
    There will be a compiler warning about the old-style constructor, so contracts only using new-style constructors are fine.
  introduced: 0.4.22
  fixed: 0.4.23
  severity: very low

- uid: SOL-2017-5
  name: ZeroFunctionSelector
  summary: >-
    It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.
  description: >-
    If a function has a selector consisting only of zeros, is payable and part of a contract that does not have a fallback function and at most five external functions in total, this function is called instead of the fallback function if Ether is sent to the contract without data.
  fixed: 0.4.18
  severity: very low

- uid: SOL-2017-4
  name: DelegateCallReturnValue
  summary: >-
    The low-level .delegatecall() does not return the execution outcome, but converts the value returned by the functioned called to a boolean instead.
  description: >-
    The return value of the low-level .delegatecall() function is taken from a position in memory, where the call data or the return data resides.
    This value is interpreted as a boolean and put onto the stack.
    This means if the called function returns at least 32 zero bytes, .delegatecall() returns false even if the call was successful.
  introduced: 0.3.0
  fixed: 0.4.15
  severity: low

- uid: SOL-2017-3
  name: ECRecoverMalformedInput
  summary: >-
    The ecrecover() builtin can return garbage for malformed input.
  description: >-
    The ecrecover precompile does not properly signal failure for malformed input (especially in the 'v' argument) and thus the Solidity function can return data that was previously present in the return area in memory.
  fixed: 0.4.14
  severity: medium

- uid: SOL-2017-2
  name: SkipEmptyStringLiteral
  summary: >-
    If "" is used in a function call, the following function arguments will not be correctly passed to the function.
  description: >-
    If the empty string literal "" is used as an argument in a function call, it is skipped by the encoder.
    This has the effect that the encoding of all arguments following this is shifted left by 32 bytes and thus the function call data is corrupted.
  fixed: 0.4.12
  severity: low

- uid: SOL-2017-1
  name: ConstantOptimizerSubtraction
  summary: >-
    In some situations, the optimizer replaces certain numbers in the code with routines that compute different numbers.
  description: >-
    The optimizer tries to represent any number in the bytecode by routines that compute them with less gas.
    For some special numbers, an incorrect routine is generated.
    This could allow an attacker to e.g. trick victims about a specific amount of ether, or function calls to call different functions (or none at all).
  link: https://blog.soliditylang.org/2017/05/03/solidity-optimizer-bug/
  fixed: 0.4.11
  severity: low
  conditions:
    optimizer: true

- uid: SOL-2016-11
  name: IdentityPrecompileReturnIgnored
  summary: >-
    Failure of the identity precompile was ignored.
  description: >-
    Calls to the identity contract, which is used for copying memory, ignored its return value.
    On the public chain, calls to the identity precompile can be made in a way that they never fail, but this might be different on private chains.
  severity: low
  fixed: 0.4.7

- uid: SOL-2016-10
  name: OptimizerStateKnowledgeNotResetForJumpdest
  summary: >-
    The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.
  description: >-
    The optimizer performs symbolic execution at certain stages.
    At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges.
    Computing this common state was simplified to just use the empty state, but this implementation was not done properly.
    This bug can cause data corruption.
  severity: medium
  introduced: 0.4.5
  fixed: 0.4.6
  conditions:
    optimizer: true

- uid: SOL-2016-9
  name: HighOrderByteCleanStorage
  summary: >-
    For short types, the high order bytes were not cleaned properly and could overwrite existing data.
  description: >-
    Types shorter than 32 bytes are packed together into the same 32 byte storage slot, but storage writes always write 32 bytes.
    For some types, the higher order bytes were not cleaned properly, which made it sometimes possible to overwrite a variable in storage when writing to another one.
  link: https://blog.soliditylang.org/2016/11/01/security-alert-solidity-variables-can-overwritten-storage/
  severity: high
  introduced: 0.1.6
  fixed: 0.4.4

- uid: SOL-2016-8
  name: OptimizerStaleKnowledgeAboutSHA3
  summary: >-
    The optimizer did not properly reset its knowledge about SHA3 operations resulting in some hashes (also used for storage variable positions) not being calculated correctly.
  description: >-
    The optimizer performs symbolic execution in order to save re-evaluating expressions whose value is already known.
    This knowledge was not properly reset across control flow paths and thus the optimizer sometimes thought that the result of a SHA3 operation is already present on the stack.
    This could result in data corruption by accessing the wrong storage slot.
  severity: medium
  fixed: 0.4.3
  conditions:
    optimizer: true

- uid: SOL-2016-7
  name: LibrariesNotCallableFromPayableFunctions
  summary: >-
    Library functions threw an exception when called from a call that received Ether.
  description: >-
    Library functions are protected against sending them Ether through a call.
    Since the DELEGATECALL opcode forwards the information about how much Ether was sent with a call, the library function incorrectly assumed that Ether was sent to the library and threw an exception.
  severity: low
  introduced: 0.4.0
  fixed: 0.4.2

- uid: SOL-2016-6
  name: SendFailsForZeroEther
  summary: >-
    The send function did not provide enough gas to the recipient if no Ether was sent with it.
  description: >-
    The recipient of an Ether transfer automatically receives a certain amount of gas from the EVM to handle the transfer.
    In the case of a zero-transfer, this gas is not provided which causes the recipient to throw an exception.
  severity: low
  fixed: 0.4.0

- uid: SOL-2016-5
  name: DynamicAllocationInfiniteLoop
  summary: >-
    Dynamic allocation of an empty memory array caused an infinite loop and thus an exception.
  description: >-
    Memory arrays can be created provided a length.
    If this length is zero, code was generated that did not terminate and thus consumed all gas.
  severity: low
  fixed: 0.3.6

- uid: SOL-2016-4
  name: OptimizerClearStateOnCodePathJoin
  summary: >-
    The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.
  description: >-
    The optimizer performs symbolic execution at certain stages.
    At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges.
    Computing this common state was not done correctly.
    This bug can cause data corruption, but it is probably quite hard to use for targeted attacks.
  severity: low
  fixed: 0.3.6
  conditions:
    optimizer: true

- uid: SOL-2016-3
  name: CleanBytesHigherOrderBits
  summary: >-
    The higher order bits of short bytesNN types were not cleaned before comparison.
  description: >-
    Two variables of type bytesNN were considered different if their higher order bits, which are not part of the actual value, were different.
    An attacker might use this to reach seemingly unreachable code paths by providing incorrectly formatted input data.
  severity: medium/high
  fixed: 0.3.3

- uid: SOL-2016-2
  name: ArrayAccessCleanHigherOrderBits
  summary: >-
    Access to array elements for arrays of types with less than 32 bytes did not correctly clean the higher order bits, causing corruption in other array elements.
  description: >-
    Multiple elements of an array of values that are shorter than 17 bytes are packed into the same storage slot.
    Writing to a single element of such an array did not properly clean the higher order bytes and thus could lead to data corruption.
  severity: medium/high
  fixed: 0.3.1

- uid: SOL-2016-1
  name: AncientCompiler
  summary: >-
    This compiler version is ancient and might contain several undocumented or undiscovered bugs.
  description: >-
    The list of bugs is only kept for compiler versions starting from 0.3.0, so older versions might contain undocumented bugs.
  severity: high
  fixed: 0.3.0

---

### Bugs By Version.Json (`docs/bugs_by_version.json`)

{
    "0.1.0": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ExpExponentCleanup",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-07-10"
    },
    "0.1.1": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ExpExponentCleanup",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-08-04"
    },
    "0.1.2": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ExpExponentCleanup",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-08-20"
    },
    "0.1.3": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ExpExponentCleanup",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-09-25"
    },
    "0.1.4": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-09-30"
    },
    "0.1.5": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-10-07"
    },
    "0.1.6": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-10-16"
    },
    "0.1.7": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-11-17"
    },
    "0.2.0": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2015-12-02"
    },
    "0.2.1": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2016-01-30"
    },
    "0.2.2": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits",
            "AncientCompiler"
        ],
        "released": "2016-02-17"
    },
    "0.3.0": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits",
            "ArrayAccessCleanHigherOrderBits"
        ],
        "released": "2016-03-11"
    },
    "0.3.1": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits"
        ],
        "released": "2016-03-31"
    },
    "0.3.2": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin",
            "CleanBytesHigherOrderBits"
        ],
        "released": "2016-04-18"
    },
    "0.3.3": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin"
        ],
        "released": "2016-05-27"
    },
    "0.3.4": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin"
        ],
        "released": "2016-05-31"
    },
    "0.3.5": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther",
            "DynamicAllocationInfiniteLoop",
            "OptimizerClearStateOnCodePathJoin"
        ],
        "released": "2016-06-10"
    },
    "0.3.6": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "SendFailsForZeroEther"
        ],
        "released": "2016-08-10"
    },
    "0.4.0": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "LibrariesNotCallableFromPayableFunctions"
        ],
        "released": "2016-09-08"
    },
    "0.4.1": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3",
            "LibrariesNotCallableFromPayableFunctions"
        ],
        "released": "2016-09-09"
    },
    "0.4.10": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction"
        ],
        "released": "2017-03-15"
    },
    "0.4.11": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral"
        ],
        "released": "2017-05-03"
    },
    "0.4.12": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput"
        ],
        "released": "2017-07-03"
    },
    "0.4.13": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput"
        ],
        "released": "2017-07-06"
    },
    "0.4.14": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue"
        ],
        "released": "2017-07-31"
    },
    "0.4.15": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector"
        ],
        "released": "2017-08-08"
    },
    "0.4.16": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector"
        ],
        "released": "2017-08-24"
    },
    "0.4.17": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "EventStructWrongData",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector"
        ],
        "released": "2017-09-21"
    },
    "0.4.18": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "EventStructWrongData",
            "NestedArrayFunctionCallDecoder"
        ],
        "released": "2017-10-18"
    },
    "0.4.19": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ABIEncoderV2PackedStorage_0.4.x",
            "ExpExponentCleanup",
            "EventStructWrongData",
            "NestedArrayFunctionCallDecoder"
        ],
        "released": "2017-11-30"
    },
    "0.4.2": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage",
            "OptimizerStaleKnowledgeAboutSHA3"
        ],
        "released": "2016-09-17"
    },
    "0.4.20": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ABIEncoderV2PackedStorage_0.4.x",
            "ExpExponentCleanup",
            "EventStructWrongData",
            "NestedArrayFunctionCallDecoder"
        ],
        "released": "2018-02-14"
    },
    "0.4.21": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ABIEncoderV2PackedStorage_0.4.x",
            "ExpExponentCleanup",
            "EventStructWrongData",
            "NestedArrayFunctionCallDecoder"
        ],
        "released": "2018-03-07"
    },
    "0.4.22": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ABIEncoderV2PackedStorage_0.4.x",
            "ExpExponentCleanup",
            "EventStructWrongData",
            "OneOfTwoConstructorsSkipped"
        ],
        "released": "2018-04-16"
    },
    "0.4.23": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ABIEncoderV2PackedStorage_0.4.x",
            "ExpExponentCleanup",
            "EventStructWrongData"
        ],
        "released": "2018-04-19"
    },
    "0.4.24": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ABIEncoderV2PackedStorage_0.4.x",
            "ExpExponentCleanup",
            "EventStructWrongData"
        ],
        "released": "2018-05-16"
    },
    "0.4.25": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ABIEncoderV2PackedStorage_0.4.x"
        ],
        "released": "2018-09-12"
    },
    "0.4.26": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2"
        ],
        "released": "2019-04-29"
    },
    "0.4.3": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "HighOrderByteCleanStorage"
        ],
        "released": "2016-10-25"
    },
    "0.4.4": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored"
        ],
        "released": "2016-10-31"
    },
    "0.4.5": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored",
            "OptimizerStateKnowledgeNotResetForJumpdest"
        ],
        "released": "2016-11-21"
    },
    "0.4.6": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction",
            "IdentityPrecompileReturnIgnored"
        ],
        "released": "2016-11-22"
    },
    "0.4.7": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction"
        ],
        "released": "2016-12-15"
    },
    "0.4.8": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction"
        ],
        "released": "2017-01-13"
    },
    "0.4.9": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "UninitializedFunctionPointerInConstructor_0.4.x",
            "IncorrectEventSignatureInLibraries_0.4.x",
            "ExpExponentCleanup",
            "NestedArrayFunctionCallDecoder",
            "ZeroFunctionSelector",
            "DelegateCallReturnValue",
            "ECRecoverMalformedInput",
            "SkipEmptyStringLiteral",
            "ConstantOptimizerSubtraction"
        ],
        "released": "2017-01-31"
    },
    "0.5.0": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor",
            "IncorrectEventSignatureInLibraries",
            "ABIEncoderV2PackedStorage"
        ],
        "released": "2018-11-13"
    },
    "0.5.1": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor",
            "IncorrectEventSignatureInLibraries",
            "ABIEncoderV2PackedStorage"
        ],
        "released": "2018-12-03"
    },
    "0.5.10": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "YulOptimizerRedundantAssignmentBreakContinue0.5",
            "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers"
        ],
        "released": "2019-06-25"
    },
    "0.5.11": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "YulOptimizerRedundantAssignmentBreakContinue0.5"
        ],
        "released": "2019-08-12"
    },
    "0.5.12": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "YulOptimizerRedundantAssignmentBreakContinue0.5"
        ],
        "released": "2019-10-01"
    },
    "0.5.13": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "YulOptimizerRedundantAssignmentBreakContinue0.5"
        ],
        "released": "2019-11-14"
    },
    "0.5.14": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "YulOptimizerRedundantAssignmentBreakContinue0.5",
            "ABIEncoderV2LoopYulOptimizer"
        ],
        "released": "2019-12-09"
    },
    "0.5.15": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "YulOptimizerRedundantAssignmentBreakContinue0.5"
        ],
        "released": "2019-12-17"
    },
    "0.5.16": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden"
        ],
        "released": "2020-01-02"
    },
    "0.5.17": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow"
        ],
        "released": "2020-03-17"
    },
    "0.5.2": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor",
            "IncorrectEventSignatureInLibraries",
            "ABIEncoderV2PackedStorage"
        ],
        "released": "2018-12-19"
    },
    "0.5.3": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor",
            "IncorrectEventSignatureInLibraries",
            "ABIEncoderV2PackedStorage"
        ],
        "released": "2019-01-22"
    },
    "0.5.4": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor",
            "IncorrectEventSignatureInLibraries",
            "ABIEncoderV2PackedStorage"
        ],
        "released": "2019-02-12"
    },
    "0.5.5": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor",
            "IncorrectEventSignatureInLibraries",
            "ABIEncoderV2PackedStorage",
            "IncorrectByteInstructionOptimization",
            "DoubleShiftSizeOverflow"
        ],
        "released": "2019-03-05"
    },
    "0.5.6": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor",
            "IncorrectEventSignatureInLibraries",
            "ABIEncoderV2PackedStorage",
            "IncorrectByteInstructionOptimization"
        ],
        "released": "2019-03-13"
    },
    "0.5.7": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "DirtyBytesArrayToStorage",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2",
            "UninitializedFunctionPointerInConstructor",
            "IncorrectEventSignatureInLibraries"
        ],
        "released": "2019-03-26"
    },
    "0.5.8": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "YulOptimizerRedundantAssignmentBreakContinue0.5",
            "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement",
            "DynamicConstructorArgumentsClippedABIV2"
        ],
        "released": "2019-04-30"
    },
    "0.5.9": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "privateCanBeOverridden",
            "YulOptimizerRedundantAssignmentBreakContinue0.5",
            "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
            "SignedArrayStorageCopy",
            "ABIEncoderV2StorageArrayWithMultiSlotElement"
        ],
        "released": "2019-05-28"
    },
    "0.6.0": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ArraySliceDynamicallyEncodedBaseType",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow",
            "YulOptimizerRedundantAssignmentBreakContinue"
        ],
        "released": "2019-12-17"
    },
    "0.6.1": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ArraySliceDynamicallyEncodedBaseType",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow"
        ],
        "released": "2020-01-02"
    },
    "0.6.10": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup"
        ],
        "released": "2020-06-11"
    },
    "0.6.11": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup"
        ],
        "released": "2020-07-07"
    },
    "0.6.12": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup"
        ],
        "released": "2020-07-22"
    },
    "0.6.2": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ArraySliceDynamicallyEncodedBaseType",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow"
        ],
        "released": "2020-01-27"
    },
    "0.6.3": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ArraySliceDynamicallyEncodedBaseType",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow"
        ],
        "released": "2020-02-18"
    },
    "0.6.4": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ArraySliceDynamicallyEncodedBaseType",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents",
            "MemoryArrayCreationOverflow"
        ],
        "released": "2020-03-10"
    },
    "0.6.5": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ArraySliceDynamicallyEncodedBaseType",
            "ImplicitConstructorCallvalueCheck",
            "TupleAssignmentMultiStackSlotComponents"
        ],
        "released": "2020-04-06"
    },
    "0.6.6": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ArraySliceDynamicallyEncodedBaseType",
            "ImplicitConstructorCallvalueCheck"
        ],
        "released": "2020-04-09"
    },
    "0.6.7": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "MissingEscapingInFormatting",
            "ArraySliceDynamicallyEncodedBaseType",
            "ImplicitConstructorCallvalueCheck"
        ],
        "released": "2020-05-04"
    },
    "0.6.8": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup"
        ],
        "released": "2020-05-14"
    },
    "0.6.9": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "UsingForCalldata"
        ],
        "released": "2020-06-04"
    },
    "0.7.0": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup"
        ],
        "released": "2020-07-28"
    },
    "0.7.1": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup",
            "FreeFunctionRedefinition"
        ],
        "released": "2020-09-02"
    },
    "0.7.2": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy",
            "DynamicArrayCleanup"
        ],
        "released": "2020-09-28"
    },
    "0.7.3": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching",
            "EmptyByteArrayCopy"
        ],
        "released": "2020-10-07"
    },
    "0.7.4": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching"
        ],
        "released": "2020-10-19"
    },
    "0.7.5": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching"
        ],
        "released": "2020-11-18"
    },
    "0.7.6": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching"
        ],
        "released": "2020-12-16"
    },
    "0.8.0": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching"
        ],
        "released": "2020-12-16"
    },
    "0.8.1": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching"
        ],
        "released": "2021-01-27"
    },
    "0.8.10": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation"
        ],
        "released": "2021-11-09"
    },
    "0.8.11": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "AbiEncodeCallLiteralAsFixedBytesBug"
        ],
        "released": "2021-12-20"
    },
    "0.8.12": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "AbiEncodeCallLiteralAsFixedBytesBug"
        ],
        "released": "2022-02-16"
    },
    "0.8.13": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "StorageWriteRemovalBeforeConditionalTermination",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "InlineAssemblyMemorySideEffects",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation"
        ],
        "released": "2022-03-16"
    },
    "0.8.14": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "StorageWriteRemovalBeforeConditionalTermination",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "InlineAssemblyMemorySideEffects"
        ],
        "released": "2022-05-17"
    },
    "0.8.15": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "StorageWriteRemovalBeforeConditionalTermination",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup"
        ],
        "released": "2022-06-15"
    },
    "0.8.16": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "StorageWriteRemovalBeforeConditionalTermination"
        ],
        "released": "2022-08-08"
    },
    "0.8.17": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess"
        ],
        "released": "2022-09-08"
    },
    "0.8.18": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess"
        ],
        "released": "2023-02-01"
    },
    "0.8.19": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess"
        ],
        "released": "2023-02-22"
    },
    "0.8.2": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory",
            "KeccakCaching"
        ],
        "released": "2021-03-02"
    },
    "0.8.20": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess"
        ],
        "released": "2023-05-10"
    },
    "0.8.21": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication"
        ],
        "released": "2023-07-19"
    },
    "0.8.22": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication"
        ],
        "released": "2023-10-25"
    },
    "0.8.23": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2023-11-08"
    },
    "0.8.24": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2024-01-25"
    },
    "0.8.25": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2024-03-14"
    },
    "0.8.26": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2024-05-21"
    },
    "0.8.27": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2024-09-04"
    },
    "0.8.28": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "TransientStorageClearingHelperCollision",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2024-10-09"
    },
    "0.8.29": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "InheritanceOrderReversalOnStorageEndWarning",
            "UnsoundSpillInMutualRecursion",
            "TransientStorageClearingHelperCollision",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2025-03-12"
    },
    "0.8.3": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables",
            "ABIDecodeTwoDimensionalArrayMemory"
        ],
        "released": "2021-03-23"
    },
    "0.8.30": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "InheritanceOrderReversalOnStorageEndWarning",
            "UnsoundSpillInMutualRecursion",
            "TransientStorageClearingHelperCollision",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2025-05-07"
    },
    "0.8.31": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "InheritanceOrderReversalOnStorageEndWarning",
            "UnsoundSpillInMutualRecursion",
            "TransientStorageClearingHelperCollision",
            "LostStorageArrayWriteOnSlotOverflow"
        ],
        "released": "2025-12-03"
    },
    "0.8.32": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "InheritanceOrderReversalOnStorageEndWarning",
            "UnsoundSpillInMutualRecursion",
            "TransientStorageClearingHelperCollision"
        ],
        "released": "2025-12-18"
    },
    "0.8.33": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "InheritanceOrderReversalOnStorageEndWarning",
            "UnsoundSpillInMutualRecursion",
            "TransientStorageClearingHelperCollision"
        ],
        "released": "2025-12-18"
    },
    "0.8.34": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "InheritanceOrderReversalOnStorageEndWarning",
            "UnsoundSpillInMutualRecursion"
        ],
        "released": "2026-02-18"
    },
    "0.8.35": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "InheritanceOrderReversalOnStorageEndWarning",
            "UnsoundSpillInMutualRecursion"
        ],
        "released": "2026-04-29"
    },
    "0.8.36": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping",
            "MisorderedNamedParametersInRequireWithCustomErrors",
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion"
        ],
        "released": "2026-07-09"
    },
    "0.8.37": {
        "bugs": [
            "YulOptimizerKnowledgeBaseStaleBookkeeping"
        ],
        "released": "2026-09-10"
    },
    "0.8.4": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables"
        ],
        "released": "2021-04-21"
    },
    "0.8.5": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables"
        ],
        "released": "2021-06-10"
    },
    "0.8.6": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables"
        ],
        "released": "2021-06-22"
    },
    "0.8.7": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "SignedImmutables"
        ],
        "released": "2021-08-11"
    },
    "0.8.8": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation",
            "UserDefinedValueTypesBug",
            "SignedImmutables"
        ],
        "released": "2021-09-27"
    },
    "0.8.9": {
        "bugs": [
            "MemoryByteArrayElementDeleteClearsWholeWord",
            "SpillSlotCollisionAcrossMutualRecursion",
            "UnsoundSpillInMutualRecursion",
            "LostStorageArrayWriteOnSlotOverflow",
            "VerbatimInvalidDeduplication",
            "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
            "MissingSideEffectsOnSelectorAccess",
            "AbiReencodingHeadOverflowWithStaticArrayCleanup",
            "DirtyBytesArrayToStorage",
            "DataLocationChangeInInternalOverride",
            "NestedCalldataArrayAbiReencodingSizeValidation"
        ],
        "released": "2021-09-29"
    }
}

---

### Cheatsheet (`docs/cheatsheet.rst`)

**********
Cheatsheet
**********

.. index:: operator;precedence

Order of Precedence of Operators
================================

.. include:: types/operator-precedence-table.rst

.. index:: abi;decode, abi;encode, abi;encodePacked, abi;encodeWithSelector, abi;encodeCall, abi;encodeWithSignature

ABI Encoding and Decoding Functions
===================================

- ``abi.decode(bytes memory encodedData, (...)) returns (...)``: :ref:`ABI <ABI>`-decodes
  the provided data. The types are given in parentheses as second argument.
  Example: ``(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))``
- ``abi.encode(...) returns (bytes memory)``: :ref:`ABI <ABI>`-encodes the given arguments
- ``abi.encodePacked(...) returns (bytes memory)``: Performs :ref:`packed encoding <abi_packed_mode>` of
  the given arguments. Note that this encoding can be ambiguous!
- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: :ref:`ABI <ABI>`-encodes
  the given arguments starting from the second and prepends the given four-byte selector
- ``abi.encodeCall(function functionPointer, (...)) returns (bytes memory)``: ABI-encodes a call to ``functionPointer`` with the arguments found in the
  tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, ...)``
- ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent
  to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)``

.. index:: bytes;concat, string;concat

Members of ``bytes`` and  ``string``
====================================

- ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of
  arguments to one byte array<bytes-concat>`

- ``string.concat(...) returns (string memory)``: :ref:`Concatenates variable number of
  arguments to one string array<string-concat>`

.. index:: address;balance, address;codehash, address;send, address;code, address;transfer

Members of ``address``
======================

- ``<address>.balance`` (``uint256``): balance of the :ref:`address` in Wei
- ``<address>.code`` (``bytes memory``): code at the :ref:`address` (can be empty)
- ``<address>.codehash`` (``bytes32``): the codehash of the :ref:`address`
- ``<address>.call(bytes memory) returns (bool, bytes memory)``: issue low-level ``CALL`` with the given payload,
  returns success condition and return data
- ``<address>.delegatecall(bytes memory) returns (bool, bytes memory)``: issue low-level ``DELEGATECALL`` with the given payload,
  returns success condition and return data
- ``<address>.staticcall(bytes memory) returns (bool, bytes memory)``: issue low-level ``STATICCALL`` with the given payload,
  returns success condition and return data
- ``<address payable>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`,
  returns ``false`` on failure (deprecated)
- ``<address payable>.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure (deprecated)

.. index:: blockhash, blobhash, block, block;basefee, block;blobbasefee, block;chainid, block;coinbase, block;difficulty, block;gaslimit, block;number, block;prevrandao, block;slotnum, block;timestamp
.. index:: gasleft, msg;data, msg;sender, msg;sig, msg;value, tx;gasprice, tx;origin

Block and Transaction Properties
================================

- ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent blocks
- ``blobhash(uint index) returns (bytes32)``: versioned hash of the ``index``-th blob associated with the current transaction.
  A versioned hash consists of a single byte representing the version (currently ``0x01``), followed by the last 31 bytes
  of the SHA256 hash of the KZG commitment (`EIP-4844 <https://eips.ethereum.org/EIPS/eip-4844>`_).
  Returns zero if no blob with the given index exists.
- ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/eip-1559>`_)
- ``block.blobbasefee`` (``uint``): current block's blob base fee (`EIP-7516 <https://eips.ethereum.org/EIPS/eip-7516>`_ and `EIP-4844 <https://eips.ethereum.org/EIPS/eip-4844>`_)
- ``block.chainid`` (``uint``): current chain id
- ``block.coinbase`` (``address payable``): current block miner's address
- ``block.difficulty`` (``uint``): current block difficulty (``EVM < Paris``). For other EVM versions it behaves as a deprecated alias for ``block.prevrandao`` that will be removed in the next breaking release
- ``block.gaslimit`` (``uint``): current block gaslimit
- ``block.number`` (``uint``): current block number
- ``block.prevrandao`` (``uint``): random number provided by the beacon chain (``EVM >= Paris``) (see `EIP-4399 <https://eips.ethereum.org/EIPS/eip-4399>`_ )
- ``block.slotnum`` (``uint64``): current beacon chain slot number (``EVM >= Amsterdam``) (see `EIP-7843 <https://eips.ethereum.org/EIPS/eip-7843>`_ )
- ``block.timestamp`` (``uint``): current block timestamp in seconds since Unix epoch
- ``gasleft() returns (uint256)``: remaining gas
- ``msg.data`` (``bytes``): complete calldata
- ``msg.sender`` (``address``): sender of the message (current call)
- ``msg.sig`` (``bytes4``): first four bytes of the calldata (i.e. function identifier)
- ``msg.value`` (``uint``): number of wei sent with the message
- ``tx.gasprice`` (``uint``): gas price of the transaction
- ``tx.origin`` (``address``): sender of the transaction (full call chain)

.. index:: assert, require, revert

Validations and Assertions
==========================

- ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error)
- ``require(bool condition)``: abort execution and revert state changes if condition is ``false`` (use
  for malformed input or error in external component)
- ``require(bool condition, string memory message)``: abort execution and revert state changes if
  condition is ``false`` (use for malformed input or error in external component). Also provide error message.
- ``revert()``: abort execution and revert state changes
- ``revert(string memory message)``: abort execution and revert state changes providing an explanatory string

.. index:: cryptography, keccak256, sha256, ripemd160, ecrecover, addmod, mulmod, erc7201

Mathematical and Cryptographic Functions
========================================

- ``keccak256(bytes memory) returns (bytes32)``: compute the Keccak-256 hash of the input
- ``sha256(bytes memory) returns (bytes32)``: compute the SHA-256 hash of the input
- ``ripemd160(bytes memory) returns (bytes20)``: compute the RIPEMD-160 hash of the input
- ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with
  the public key from elliptic curve signature, return zero on error
- ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with
  arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0.
- ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed
  with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0.
- ``erc7201(string memory id) returns (uint)``: compute the base slot of an ``erc7201`` storage namespace.
  Can be used in compile time context.

.. index:: this, super, selfdestruct

Contract-related
================

- ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` or ``address payable``
- ``super``: a contract one level higher in the inheritance hierarchy
- ``selfdestruct(address payable recipient)``: send all funds to the given address and (only on EVMs before Cancun or when invoked within the transaction creating the contract) destroy the contract.

.. index:: type;name, type;creationCode, type;runtimeCode, type;interfaceId, type;min, type;max

Type Information
================

- ``type(C).name`` (``string``): the name of the contract
- ``type(C).creationCode`` (``bytes memory``): creation bytecode of the given contract, see :ref:`Type Information<meta-type>`.
- ``type(C).runtimeCode`` (``bytes memory``): runtime bytecode of the given contract, see :ref:`Type Information<meta-type>`.
- ``type(I).interfaceId`` (``bytes4``): value containing the EIP-165 interface identifier of the given interface, see :ref:`Type Information<meta-type>`.
- ``type(T).min`` (``T``): the minimum value representable by the integer type ``T``, see :ref:`Type Information<meta-type>`.
- ``type(T).max`` (``T``): the maximum value representable by the integer type ``T``, see :ref:`Type Information<meta-type>`.


.. index:: visibility, public, private, external, internal

Function Visibility Specifiers
==============================

.. code-block:: solidity
    :force:

    function myFunction() <visibility specifier> returns (bool) {
        return true;
    }

- ``public``: visible externally and internally (creates a :ref:`getter function<getter-functions>` for storage/state variables)
- ``private``: only visible in the current contract
- ``external``: only visible externally (only for functions) - i.e. can only be message-called (via ``this.func``)
- ``internal``: only visible internally


.. index:: modifiers, pure, view, payable, constant, anonymous, indexed

Modifiers
=========

- ``pure`` for functions: Disallows modification or access of state.
- ``view`` for functions: Disallows modification of state.
- ``payable`` for functions: Allows them to receive Ether together with a call.
- ``constant`` for state variables: Disallows assignment (except initialization), does not occupy storage slot.
- ``immutable`` for state variables: Allows assignment at construction time and is constant when deployed. Is stored in code.
- ``anonymous`` for events: Does not store event signature as topic.
- ``indexed`` for event parameters: Stores the parameter as topic.
- ``virtual`` for functions and modifiers: Allows the function's or modifier's
  behavior to be changed in derived contracts.
- ``override``: States that this function, modifier or public state variable changes
  the behavior of a function or modifier in a base contract.

---

### Common Patterns (`docs/common-patterns.rst`)

###############
Common Patterns
###############

.. index:: withdrawal

.. _withdrawal_pattern:

*************************
Withdrawal from Contracts
*************************

The recommended method of sending funds after an effect
is using the withdrawal pattern. Although the most intuitive
method of sending Ether, as a result of an effect, is a
direct ``transfer`` call, this is not recommended as it
introduces a potential security risk. You may read
more about this on the :ref:`security_considerations` page.

The following is an example of the withdrawal pattern in practice in
a contract where the goal is to send the most of some compensation, e.g. Ether, to the
contract in order to become the "richest", inspired by
`King of the Ether <https://www.kingoftheether.com/>`_.

In the following contract, if you are no longer the richest,
you receive the funds of the person who is now the richest.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;

    contract WithdrawalContract {
        address public richest;
        uint public mostSent;

        mapping(address => uint) pendingWithdrawals;

        /// The amount of Ether sent was not higher than
        /// the currently highest amount.
        error NotEnoughEther();

        constructor() payable {
            richest = msg.sender;
            mostSent = msg.value;
        }

        function becomeRichest() public payable {
            if (msg.value <= mostSent) revert NotEnoughEther();
            pendingWithdrawals[richest] += msg.value;
            richest = msg.sender;
            mostSent = msg.value;
        }

        function withdraw() public {
            uint amount = pendingWithdrawals[msg.sender];
            // Remember to zero the pending refund before
            // sending to prevent reentrancy attacks
            pendingWithdrawals[msg.sender] = 0;
            (bool success, ) = payable(msg.sender).call{value: amount}("");
            require(success);
        }
    }

This is as opposed to the more intuitive sending pattern:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;

    contract SendContract {
        address payable public richest;
        uint public mostSent;

        /// The amount of Ether sent was not higher than
        /// the currently highest amount.
        error NotEnoughEther();

        constructor() payable {
            richest = payable(msg.sender);
            mostSent = msg.value;
        }

        function becomeRichest() public payable {
            if (msg.value <= mostSent) revert NotEnoughEther();
            // This line can cause problems (explained below).
            (bool success, ) = richest.call{value: msg.value}("");
            require(success);
            richest = payable(msg.sender);
            mostSent = msg.value;
        }
    }

Notice that, in this example, an attacker could trap the
contract into an unusable state by causing ``richest`` to be
the address of a contract that has a receive or fallback function
which fails (e.g. by using ``revert()`` or by just
consuming more than the 2300 gas stipend transferred to them). That way,
whenever ``transfer`` is called to deliver funds to the
"poisoned" contract, it will fail and thus also ``becomeRichest``
will fail, with the contract being stuck forever.

In contrast, if you use the "withdraw" pattern from the first example,
the attacker can only cause his or her own withdraw to fail and not the
rest of the contract's workings.

.. index:: access;restricting

******************
Restricting Access
******************

Restricting access is a common pattern for contracts.
Note that you can never restrict any human or computer
from reading the content of your transactions or
your contract's state. You can make it a bit harder
by using encryption, but if your contract is supposed
to read the data, so will everyone else.

You can restrict read access to your contract's state
by **other contracts**. That is actually the default
unless you declare your state variables ``public``.

Furthermore, you can restrict who can make modifications
to your contract's state or call your contract's
functions and this is what this section is about.

.. index:: function;modifier

The use of **function modifiers** makes these
restrictions highly readable.

.. code-block:: solidity
    :force:

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;

    contract AccessRestriction {
        // These will be assigned at the construction
        // phase, where `msg.sender` is the account
        // creating this contract.
        address public owner = msg.sender;
        uint public creationTime = block.timestamp;

        // Now follows a list of errors that
        // this contract can generate together
        // with a textual explanation in special
        // comments.

        /// Sender not authorized for this
        /// operation.
        error Unauthorized();

        /// Function called too early.
        error TooEarly();

        /// Not enough Ether sent with function call.
        error NotEnoughEther();

        // Modifiers can be used to change
        // the body of a function.
        // If this modifier is used, it will
        // prepend a check that only passes
        // if the function is called from
        // a certain address.
        modifier onlyBy(address account)
        {
            if (msg.sender != account)
                revert Unauthorized();
            // Do not forget the "_;"! It will
            // be replaced by the actual function
            // body when the modifier is used.
            _;
        }

        /// Make `newOwner` the new owner of this
        /// contract.
        function changeOwner(address newOwner)
            public
            onlyBy(owner)
        {
            owner = newOwner;
        }

        modifier onlyAfter(uint time) {
            if (block.timestamp < time)
                revert TooEarly();
            _;
        }

        /// Erase ownership information.
        /// May only be called 6 weeks after
        /// the contract has been created.
        function disown()
            public
            onlyBy(owner)
            onlyAfter(creationTime + 6 weeks)
        {
            delete owner;
        }

        // This modifier requires a certain
        // fee being associated with a function call.
        // If the caller sent too much, he or she is
        // refunded, but only after the function body.
        // This was dangerous before Solidity version 0.4.0,
        // where it was possible to skip the part after `_;`.
        modifier costs(uint amount) {
            if (msg.value < amount)
                revert NotEnoughEther();

            _;
            if (msg.value > amount) {
                (bool success, ) = payable(msg.sender).call{value: msg.value - amount}("");
                require(success);
            }
        }

        function forceOwnerChange(address newOwner)
            public
            payable
            costs(200 ether)
        {
            owner = newOwner;
            // just some example condition
            if (uint160(owner) & 0 == 1)
                // This did not refund for Solidity
                // before version 0.4.0.
                return;
            // refund overpaid fees
        }
    }

A more specialised way in which access to function
calls can be restricted will be discussed
in the next example.

.. index:: state machine

*************
State Machine
*************

Contracts often act as a state machine, which means
that they have certain **stages** in which they behave
differently or in which different functions can
be called. A function call often ends a stage
and transitions the contract into the next stage
(especially if the contract models **interaction**).
It is also common that some stages are automatically
reached at a certain point in **time**.

An example for this is a blind auction contract which
starts in the stage "accepting blinded bids", then
transitions to "revealing bids" which is ended by
"determine auction outcome".

.. index:: function;modifier

Function modifiers can be used in this situation
to model the states and guard against
incorrect usage of the contract.

Example
=======

In the following example,
the modifier ``atStage`` ensures that the function can
only be called at a certain stage.

Automatic timed transitions
are handled by the modifier ``timedTransitions``, which
should be used for all functions.

.. note::
    **Modifier Order Matters**.
    If atStage is combined
    with timedTransitions, make sure that you mention
    it after the latter, so that the new stage is
    taken into account.

Finally, the modifier ``transitionNext`` can be used
to automatically go to the next stage when the
function finishes.

.. note::
    **Modifier May be Skipped**.
    This only applies to Solidity before version 0.4.0:
    Since modifiers are applied by simply replacing
    code and not by using a function call,
    the code in the transitionNext modifier
    can be skipped if the function itself uses
    return. If you want to do that, make sure
    to call nextStage manually from those functions.
    Starting with version 0.4.0, modifier code
    will run even if the function explicitly returns.

.. code-block:: solidity
    :force:

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;

    contract StateMachine {
        enum Stages {
            AcceptingBlindedBids,
            RevealBids,
            AnotherStage,
            AreWeDoneYet,
            Finished
        }
        /// Function cannot be called at this time.
        error FunctionInvalidAtThisStage();

        // This is the current stage.
        Stages public stage = Stages.AcceptingBlindedBids;

        uint public creationTime = block.timestamp;

        modifier atStage(Stages stage_) {
            if (stage != stage_)
                revert FunctionInvalidAtThisStage();
            _;
        }

        function nextStage() internal {
            stage = Stages(uint(stage) + 1);
        }

        // Perform timed transitions. Be sure to mention
        // this modifier first, otherwise the guards
        // will not take the new stage into account.
        modifier timedTransitions() {
            if (stage == Stages.AcceptingBlindedBids &&
                        block.timestamp >= creationTime + 10 days)
                nextStage();
            if (stage == Stages.RevealBids &&
                    block.timestamp >= creationTime + 12 days)
                nextStage();
            // The other stages transition by transaction
            _;
        }

        // Order of the modifiers matters here!
        function bid()
            public
            payable
            timedTransitions
            atStage(Stages.AcceptingBlindedBids)
        {
            // We will not implement that here
        }

        function reveal()
            public
            timedTransitions
            atStage(Stages.RevealBids)
        {
        }

        // This modifier goes to the next stage
        // after the function is done.
        modifier transitionNext()
        {
            _;
            nextStage();
        }

        function g()
            public
            timedTransitions
            atStage(Stages.AnotherStage)
            transitionNext
        {
        }

        function h()
            public
            timedTransitions
            atStage(Stages.AreWeDoneYet)
            transitionNext
        {
        }

        function i()
            public
            timedTransitions
            atStage(Stages.Finished)
        {
        }
    }

---

### Contracts (`docs/contracts.rst`)

.. index:: ! contract

.. _contracts:

##########
Contracts
##########

Contracts in Solidity are similar to classes in object-oriented languages. They
contain persistent data in state variables, and functions that can modify these
variables. Calling a function on a different contract (instance) will perform
an EVM function call and thus switch the context such that state variables
in the calling contract are
inaccessible. A contract and its functions need to be called for anything to happen.
There is no "cron" concept in Ethereum to call a function at a particular event automatically.

.. include:: contracts/creating-contracts.rst

.. include:: contracts/visibility-and-getters.rst

.. include:: contracts/function-modifiers.rst

.. include:: contracts/transient-storage.rst

.. include:: contracts/constant-state-variables.rst
.. include:: contracts/custom-storage-layout.rst
.. include:: contracts/functions.rst

.. include:: contracts/events.rst
.. include:: contracts/errors.rst

.. include:: contracts/inheritance.rst

.. include:: contracts/abstract-contracts.rst
.. include:: contracts/interfaces.rst

.. include:: contracts/libraries.rst

.. include:: contracts/using-for.rst

---

### Contributing (`docs/contributing.rst`)

############
Contributing
############

Help is always welcome and there are plenty of options to contribute to Solidity.

In particular, we appreciate support in the following areas:

* Reporting issues.
* Fixing and responding to `Solidity's GitHub issues
  <https://github.com/argotorg/solidity/issues>`_, especially those tagged as
  `"good first issue" <https://github.com/argotorg/solidity/labels/good%20first%20issue>`_ which are
  meant as introductory issues for external contributors.
* Improving the documentation.
* `Translating <https://github.com/solidity-docs>`_ the documentation into more languages.
* Responding to questions from other users on `StackExchange
  <https://ethereum.stackexchange.com>`_ and the `Solidity Matrix Chat
  <https://matrix.to/#/#ethereum\_solidity:gitter.im>`_.
* Getting involved in the language design process by proposing language changes or new features in the `Solidity forum <https://forum.soliditylang.org/>`_ and providing feedback.

To get started, you can try :ref:`building-from-source` in order to familiarize
yourself with the components of Solidity and the build process. Also, it may be
useful to become well-versed at writing smart-contracts in Solidity.

Please note that this project is released with a `Contributor Code of Conduct <https://raw.githubusercontent.com/ethereum/solidity/develop/CODE_OF_CONDUCT.md>`_. By participating in this project — in the issues, pull requests, or Matrix channels — you agree to abide by its terms.

Team Calls
==========

If you have issues or pull requests to discuss, or are interested in hearing what
the team and contributors are working on, you can join our public team call:

- Wednesdays at 3PM CET/CEST.

The call takes place on `Jitsi <https://meet.solidity.org>`_.

New topics can be freely added to the `agenda <https://notes.argot.org/@solidity-design-call-agenda>`_
and will be scheduled for discussion on the nearest call.

How to Report Issues
====================

To report an issue, please use the
`GitHub issues tracker <https://github.com/argotorg/solidity/issues>`_. When
reporting issues, please mention the following details:

* Solidity version.
* Source code (if applicable).
* Operating system.
* Steps to reproduce the issue.
* Actual vs. expected behavior.

Reducing the source code that caused the issue to a bare minimum is always
very helpful, and sometimes even clarifies a misunderstanding.

For technical discussions about language design, a post in the
`Solidity forum <https://forum.soliditylang.org/>`_ is the correct place (see :ref:`solidity_language_design`).

Workflow for Pull Requests
==========================

In order to contribute, please fork off of the ``develop`` branch and make your
changes there. Your commit messages should detail *why* you made your change
in addition to *what* you did (unless it is a tiny change).

If you need to pull in any changes from ``develop`` after making your fork (for
example, to resolve potential merge conflicts), please avoid using ``git merge``
and instead, ``git rebase`` your branch. This will help us review your change
more easily.

Additionally, if you are writing a new feature, please ensure you add appropriate
test cases under ``test/`` (see below).

However, if you are making a larger change, please consult with the `Solidity Development Matrix channel
<https://matrix.to/#/#ethereum\_solidity-dev:gitter.im>`_ (different from the one mentioned above — this one is
focused on compiler and language development instead of language usage) first.

New features and bugfixes should be added to the ``Changelog.md`` file: please
follow the style of previous entries, when applicable.

Finally, please make sure you respect the `coding style
<https://github.com/argotorg/solidity/blob/develop/CODING_STYLE.md>`_
for this project. Also, even though we do CI testing, please test your code and
ensure that it builds locally before submitting a pull request.

We highly recommend going through our `review checklist <https://github.com/argotorg/solidity/blob/develop/ReviewChecklist.md>`_ before submitting the pull request.
We thoroughly review every PR and will help you get it right, but there are many common problems that can be easily avoided, making the review much smoother.

Thank you for your help!

AI-Assisted Contributions
=========================

We do not ban the use of AI tools, but we hold all contributions to the same high standard
regardless of how they are produced, and we require full transparency about their use.

Submitting AI-generated code means you have reviewed it, understand it, can explain it, and have
tested it as thoroughly as if you had written it by hand.

If you used AI tools to generate code, tests, or documentation in any part of your contribution,
disclosure in the pull request is mandatory.
If we determine that a PR contains undisclosed AI-generated content, we may close it.


Running the Compiler Tests
==========================

Prerequisites
-------------

For running all compiler tests you may want to optionally install a few
dependencies (`evmone <https://github.com/ipsilon/evmone/releases>`_,
`z3 <https://github.com/Z3Prover/z3>`_, `Eldarica <https://github.com/uuverifiers/eldarica/>`_,
`cvc5 <https://github.com/cvc5/cvc5>`_).

On macOS systems, some of the testing scripts expect GNU coreutils to be installed.
This can be easiest accomplished using Homebrew: ``brew install coreutils``.

On Windows systems, make sure that you have a privilege to create symlinks,
otherwise several tests may fail.
Administrators should have that privilege, but you may also
`grant it to other users <https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links#policy-management>`_
or
`enable Developer Mode <https://learn.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development>`_.

Running the Tests
-----------------

Solidity includes different types of tests, most of them bundled into the
`Boost C++ Test Framework <https://www.boost.org/doc/libs/release/libs/test/doc/html/index.html>`_ application ``soltest``.
Running ``build/test/soltest`` or its wrapper ``scripts/soltest.sh`` is sufficient for most changes.

The ``./scripts/tests.sh`` script executes most Solidity tests automatically,
including those bundled into the `Boost C++ Test Framework <https://www.boost.org/doc/libs/release/libs/test/doc/html/index.html>`_
application ``soltest`` (or its wrapper ``scripts/soltest.sh``), as well as command-line tests and
compilation tests.

The test system automatically tries to discover the location of
the `evmone <https://github.com/ipsilon/evmone/releases>`_ for running the semantic tests.

The ``evmone`` library must be located in the ``deps`` or ``deps/lib`` directory relative to the
current working directory, to its parent or its parent's parent. Alternatively, an explicit location
for the ``evmone`` shared object can be specified via the ``ETH_EVMONE`` environment variable.

``evmone`` is needed mainly for running semantic and gas tests.
If you do not have it installed, you can skip these tests by passing the ``--no-semantic-tests``
flag to ``scripts/soltest.sh``.

The ``evmone`` library should end with the file name
extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS.

For running SMT tests, the ``z3`` executable must be present in ``PATH``.
A few SMT tests use ``Eldarica`` instead of ``z3``.
These require its executable (``eld``) to be present in ``PATH`` for the tests to pass.
However, if ``Eldarica`` is not found, these tests will be automatically skipped.

If ``z3`` is not present on your system, you should disable the
SMT tests by exporting ``SMT_FLAGS=--no-smt`` before running ``./scripts/tests.sh`` or
running ``./scripts/soltest.sh --no-smt``.
These tests are ``libsolidity/smtCheckerTests``.

.. note::

    To get a list of all unit tests run by Soltest, run ``./build/test/soltest --list_content=HRF``.

For quicker results you can run a subset of, or specific tests.

To run a subset of tests, you can use filters:
``./scripts/soltest.sh -t TestSuite/TestName``,
where ``TestName`` can be a wildcard ``*``.

Or, for example, to run all the tests for the yul disambiguator:
``./scripts/soltest.sh -t "yulOptimizerTests/disambiguator/*" --no-smt``.

``./build/test/soltest --help`` has extensive help on all of the options available.

See especially:

- `show_progress (-p) <https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/utf_reference/rt_param_reference/show_progress.html>`_ to show test completion,
- `run_test (-t) <https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/utf_reference/rt_param_reference/run_test.html>`_ to run specific tests cases, and
- `report-level (-r) <https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/utf_reference/rt_param_reference/report_level.html>`_ give a more detailed report.

.. note::

    Those working in a Windows environment wanting to run the above basic sets
    without z3. Using Git Bash, you use: ``./build/test/Release/soltest.exe -- --no-smt``.
    If you are running this in plain Command Prompt, use ``.\build\test\Release\soltest.exe -- --no-smt``.

If you want to debug using GDB, make sure you build differently than the "usual".
For example, you could run the following command in your ``build`` folder:

.. code-block:: bash

   cmake -DCMAKE_BUILD_TYPE=Debug ..
   make

This creates symbols so that when you debug a test using the ``--debug`` flag,
you have access to functions and variables in which you can break or print with.

The CI runs additional tests (including ``solc-js`` and testing third party Solidity
frameworks) that require compiling the Emscripten target.

Writing and Running Syntax Tests
--------------------------------

Syntax tests check that the compiler generates the correct error messages for invalid code
and properly accepts valid code.
They are stored in individual files inside the ``tests/libsolidity/syntaxTests`` folder.
These files must contain annotations, stating the expected result(s) of the respective test.
The test suite compiles and checks them against the given expectations.

For example: ``./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol``

.. code-block:: solidity

    contract test {
        uint256 variable;
        uint128 variable;
    }
    // ----
    // DeclarationError: (36-52): Identifier already declared.

A syntax test must contain at least the contract under test itself, followed by the separator ``// ----``. The comments that follow the separator are used to describe the
expected compiler errors or warnings. The number range denotes the location in the source where the error occurred.
If you want the contract to compile without any errors or warning you can leave
out the separator and the comments that follow it.

In the above example, the state variable ``variable`` was declared twice, which is not allowed. This results in a ``DeclarationError`` stating that the identifier was already declared.

The ``isoltest`` tool is used for these tests and you can find it under ``./build/test/tools/``. It is an interactive tool which allows
editing of failing contracts using your preferred text editor. Let's try to break this test by removing the second declaration of ``variable``:

.. code-block:: solidity

    contract test {
        uint256 variable;
    }
    // ----
    // DeclarationError: (36-52): Identifier already declared.

Running ``./build/test/tools/isoltest`` again results in a test failure:

.. code-block:: text

    syntaxTests/double_stateVariable_declaration.sol: FAIL
        Contract:
            contract test {
                uint256 variable;
            }

        Expected result:
            DeclarationError: (36-52): Identifier already declared.
        Obtained result:
            Success


``isoltest`` prints the expected result next to the obtained result, and also
provides a way to edit, update or skip the current contract file, or quit the application.

It offers several options for failing tests:

- ``edit``: ``isoltest`` tries to open the contract in an editor so you can adjust it. It either uses the editor given on the command-line (as ``isoltest --editor /path/to/editor``), in the environment variable ``EDITOR`` or just ``/usr/bin/editor`` (in that order).
- ``update``: Updates the expectations for contract under test. This updates the annotations by removing unmet expectations and adding missing expectations. The test is then run again.
- ``skip``: Skips the execution of this particular test.
- ``quit``: Quits ``isoltest``.

All of these options apply to the current contract, except ``quit`` which stops the entire testing process.

Automatically updating the test above changes it to

.. code-block:: solidity

    contract test {
        uint256 variable;
    }
    // ----

and re-run the test. It now passes again:

.. code-block:: text

    Re-running test case...
    syntaxTests/double_stateVariable_declaration.sol: OK


.. note::

    Choose a name for the contract file that explains what it tests, e.g. ``double_variable_declaration.sol``.
    Do not put more than one contract into a single file, unless you are testing inheritance or cross-contract calls.
    Each file should test one aspect of your new feature.

Command-line Tests
------------------

Our suite of end-to-end command-line tests checks the behaviour of the compiler binary as a whole
in various scenarios.
These tests are located in `test/cmdlineTests/ <https://github.com/argotorg/solidity/tree/develop/test/cmdlineTests>`_,
one per subdirectory, and can be executed using the ``cmdlineTests.sh`` script.

By default the script runs all available tests.
You can also provide one or more `file name patterns <https://www.gnu.org/software/bash/manual/bash.html#Filename-Expansion>`_,
in which case only the tests matching at least one pattern will be executed.
It is also possible to exclude files matching a specific pattern by prefixing it with ``--exclude``.

By default the script assumes that a ``solc`` binary is available inside the ``build/`` subdirectory
inside the working copy.
If you build the compiler outside of the source tree, you can use the ``SOLIDITY_BUILD_DIR`` environment
variable to specify a different location for the build directory.

Example:

.. code-block:: bash

    export SOLIDITY_BUILD_DIR=~/solidity/build/
    test/cmdlineTests.sh "standard_*" "*_yul_*" --exclude "standard_yul_*"

The commands above will run tests from directories starting with ``test/cmdlineTests/standard_`` and
subdirectories of ``test/cmdlineTests/`` that have ``_yul_`` somewhere in the name,
but no test whose name starts with ``standard_yul_`` will be executed.
It will also assume that the file ``solidity/build/solc/solc`` inside your home directory is the
compiler binary (unless you are on Windows -- then ``solidity/build/solc/Release/solc.exe``).

There are several kinds of command-line tests:

- *Standard JSON test*: contains at least an ``input.json`` file.
  In general may contain:

    - ``input.json``: input file to be passed to the ``--standard-json`` option on the command line.
    - ``output.json``: expected Standard JSON output.
    - ``args``: extra command-line arguments passed to ``solc``.

- *CLI test*: contains at least an ``input.*`` file (other than ``input.json``).
  In general may contain:

    - ``input.*``: a single input file, whose name will be supplied to ``solc`` on the command line.
      Usually ``input.sol`` or ``input.yul``.
    - ``args``: extra command-line arguments passed to ``solc``.
    - ``stdin``: content to be passed to ``solc`` via standard input.
    - ``output``: expected content of the standard output.
    - ``err``: expected content of the standard error output.
    - ``exit``: expected exit code. If not provided, zero is expected.

- *Script test*: contains a ``test.*`` file.
  In general may contain:

    - ``test.*``: a single script to run, usually ``test.sh`` or ``test.py``.
      The script must be executable.

Running the Fuzzer via AFL
==========================

Fuzzing is a technique that runs programs on more or less random inputs to find exceptional execution
states (segmentation faults, exceptions, etc). Modern fuzzers are clever and run a directed search
inside the input. We have a specialized binary called ``solfuzzer`` which takes source code as input
and fails whenever it encounters an internal compiler error, segmentation fault or similar, but
does not fail if e.g., the code contains an error. This way, fuzzing tools can find internal problems in the compiler.

We mainly use `AFL <https://lcamtuf.coredump.cx/afl/>`_ for fuzzing. You need to download and
install the AFL packages from your repositories (afl, afl-clang) or build them manually.
Next, build Solidity (or just the ``solfuzzer`` binary) with AFL as your compiler:

.. code-block:: bash

    cd build
    # if needed
    make clean
    cmake .. -DCMAKE_C_COMPILER=path/to/afl-gcc -DCMAKE_CXX_COMPILER=path/to/afl-g++
    make solfuzzer

At this stage, you should be able to see a message similar to the following:

.. code-block:: text

    Scanning dependencies of target solfuzzer
    [ 98%] Building CXX object test/tools/CMakeFiles/solfuzzer.dir/fuzzer.cpp.o
    afl-cc 2.52b by <lcamtuf@google.com>
    afl-as 2.52b by <lcamtuf@google.com>
    [+] Instrumented 1949 locations (64-bit, non-hardened mode, ratio 100%).
    [100%] Linking CXX executable solfuzzer

If the instrumentation messages did not appear, try switching the cmake flags pointing to AFL's clang binaries:

.. code-block:: bash

    # if previously failed
    make clean
    cmake .. -DCMAKE_C_COMPILER=path/to/afl-clang -DCMAKE_CXX_COMPILER=path/to/afl-clang++
    make solfuzzer

Otherwise, upon execution the fuzzer halts with an error saying binary is not instrumented:

.. code-block:: text

    afl-fuzz 2.52b by <lcamtuf@google.com>
    ... (truncated messages)
    [*] Validating target binary...

    [-] Looks like the target binary is not instrumented! The fuzzer depends on
        compile-time instrumentation to isolate interesting test cases while
        mutating the input data. For more information, and for tips on how to
        instrument binaries, please see /usr/share/doc/afl-doc/docs/README.

        When source code is not available, you may be able to leverage QEMU
        mode support. Consult the README for tips on how to enable this.
        (It is also possible to use afl-fuzz as a traditional, "dumb" fuzzer.
        For that, you can use the -n option - but expect much worse results.)

    [-] PROGRAM ABORT : No instrumentation detected
             Location : check_binary(), afl-fuzz.c:6920


Next, you need some example source files. This makes it much easier for the fuzzer
to find errors. You can either copy some files from the syntax tests or extract test files
from the documentation or the other tests:

.. code-block:: bash

    mkdir /tmp/test_cases
    cd /tmp/test_cases
    # extract from tests:
    path/to/solidity/scripts/isolate_tests.py path/to/solidity/test/libsolidity/SolidityEndToEndTest.cpp
    # extract from documentation:
    path/to/solidity/scripts/isolate_tests.py path/to/solidity/docs

The AFL documentation states that the corpus (the initial input files) should not be
too large. The files themselves should not be larger than 1 kB and there should be
at most one input file per functionality, so better start with a small number of.
There is also a tool called ``afl-cmin`` that can trim input files
that result in similar behavior of the binary.

Now run the fuzzer (the ``-m`` extends the size of memory to 60 MB):

.. code-block:: bash

    afl-fuzz -m 60 -i /tmp/test_cases -o /tmp/fuzzer_reports -- /path/to/solfuzzer

The fuzzer creates source files that lead to failures in ``/tmp/fuzzer_reports``.
Often it finds many similar source files that produce the same error. You can
use the tool ``scripts/uniqueErrors.sh`` to filter out the unique errors.

Whiskers
========

*Whiskers* is a string templating system similar to `Mustache <https://mustache.github.io>`_. It is used by the
compiler in various places to aid readability, and thus maintainability and verifiability, of the code.

The syntax comes with a substantial difference to Mustache. The template markers ``{{`` and ``}}`` are
replaced by ``<`` and ``>`` in order to aid parsing and avoid conflicts with :ref:`yul`
(The symbols ``<`` and ``>`` are invalid in inline assembly, while ``{`` and ``}`` are used to delimit blocks).
Another limitation is that lists are only resolved one depth and they do not recurse. This may change in the future.

A rough specification is the following:

Any occurrence of ``<name>`` is replaced by the string-value of the supplied variable ``name`` without any
escaping and without iterated replacements. An area can be delimited by ``<#name>...</name>``. It is replaced
by as many concatenations of its contents as there were sets of variables supplied to the template system,
each time replacing any ``<inner>`` items by their respective value. Top-level variables can also be used
inside such areas.

There are also conditionals of the form ``<?name>...<!name>...</name>``, where template replacements
continue recursively either in the first or the second segment depending on the value of the boolean
parameter ``name``. If ``<?+name>...<!+name>...</+name>`` is used, then the check is whether
the string parameter ``name`` is non-empty.

.. _documentation-style:

Documentation Style Guide
=========================

In the following section you find style recommendations specifically focusing on documentation
contributions to Solidity.

English Language
----------------

Use International English, unless using project or brand names. Try to reduce the usage of
local slang and references, making your language as clear to all readers as possible.
Below are some references to help:

* `Simplified technical English <https://en.wikipedia.org/wiki/Simplified_Technical_English>`_
* `International English <https://en.wikipedia.org/wiki/International_English>`_

.. note::

    While the official Solidity documentation is written in English, there are community contributed :ref:`translations`
    in other languages available. Please refer to the `translation guide <https://github.com/solidity-docs#solidity-documentation-translation-guide>`_
    for information on how to contribute to the community translations.

Title Case for Headings
-----------------------

Use `title case <https://titlecase.com>`_ for headings. This means capitalise all principal words in
titles, but not articles, conjunctions, and prepositions unless they start the
title.

For example, the following are all correct:

* Title Case for Headings.
* For Headings Use Title Case.
* Local and State Variable Names.
* Order of Layout.

Expand Contractions
-------------------

Use expanded contractions for words, for example:

* "Do not" instead of "Don't".
* "Can not" instead of "Can't".

Active and Passive Voice
------------------------

Active voice is typically recommended for tutorial style documentation as it
helps the reader understand who or what is performing a task. However, as the
Solidity documentation is a mixture of tutorials and reference content, passive
voice is sometimes more applicable.

As a summary:

* Use passive voice for technical reference, for example language definition and internals of the Ethereum VM.
* Use active voice when describing recommendations on how to apply an aspect of Solidity.

For example, the below is in passive voice as it specifies an aspect of Solidity:

  Functions can be declared ``pure`` in which case they promise not to read
  from or modify the state.

For example, the below is in active voice as it discusses an application of Solidity:

  When invoking the compiler, you can specify how to discover the first element
  of a path, and also path prefix remappings.

Common Terms
------------

* "Function parameters" and "return variables", not input and output parameters.

Code Examples
-------------

A CI process tests all code block formatted code examples that begin with ``pragma solidity``, ``contract``, ``library``
or ``interface`` using the ``./test/cmdlineTests.sh`` script when you create a PR. If you are adding new code examples,
ensure they work and pass tests before creating the PR.

Ensure that all code examples begin with a ``pragma`` version that spans the largest where the contract code is valid.
For example ``pragma solidity >=0.4.0 <0.9.0;``.

Running Documentation Tests
---------------------------

Make sure your contributions pass our documentation tests by running ``./docs/docs.sh`` that installs dependencies
needed for documentation and checks for any problems such as broken links or syntax issues.

.. _solidity_language_design:

Solidity Language Design
========================

To actively get involved in the language design process and to share your ideas concerning the future of Solidity,
please join the `Solidity forum <https://forum.soliditylang.org/>`_.

The Solidity forum serves as the place to propose and discuss new language features and their implementation in
the early stages of ideation or modifications of existing features.

As soon as proposals get more tangible, their
implementation will also be discussed in the `Solidity GitHub repository <https://github.com/argotorg/solidity>`_
in the form of issues.

In addition to the forum and issue discussions, we regularly host language design discussion calls in which selected
topics, issues or feature implementations are debated in detail. The invitation to those calls is shared via the forum.

We are also sharing feedback surveys and other content that is relevant to language design in the forum.

If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project <https://github.com/orgs/argotorg/projects/38>`_.
Issues in the design backlog need further specification and will either be discussed in a language design call or in a regular team call. You can
see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch <https://github.com/argotorg/solidity/tree/breaking>`_.

For ad-hoc cases and questions, you can reach out to us via the `Solidity-dev Gitter channel <https://gitter.im/ethereum/solidity-dev>`_ — a
dedicated chatroom for conversations around the Solidity compiler and language development.

We are happy to hear your thoughts on how we can improve the language design process to be even more collaborative and transparent.

---

### Control Structures (`docs/control-structures.rst`)

##################################
Expressions and Control Structures
##################################

.. index:: ! parameter, parameter;input, parameter;output, function parameter, parameter;function, return variable, variable;return, return


.. index:: if, else, while, do/while, for, break, continue, return, switch, goto

Control Structures
===================

Most of the control structures known from curly-braces languages are available in Solidity:

There is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, with
the usual semantics known from C or JavaScript.

Solidity also supports exception handling in the form of ``try``/``catch``-statements,
but only for :ref:`external function calls <external-function-calls>` and
contract creation calls. Errors can be created using the :ref:`revert statement <revert-statement>`.

Parentheses can *not* be omitted for conditionals, but curly braces can be omitted
around single-statement bodies.

Note that there is no type conversion from non-boolean to boolean types as
there is in C and JavaScript, so ``if (1) { ... }`` is *not* valid
Solidity.

.. index:: ! function;call, function;internal, function;external

.. _function-calls:

Function Calls
==============

.. _internal-function-calls:

Internal Function Calls
-----------------------

Functions of the current contract can be called directly ("internally"), also recursively, as seen in
this nonsensical example:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.4.22 <0.9.0;

    // This will report a warning
    contract C {
        function g(uint a) public pure returns (uint ret) { return a + f(); }
        function f() internal pure returns (uint ret) { return g(7) + f(); }
    }

These function calls are translated into simple jumps inside the EVM. This has
the effect that the current memory is not cleared, i.e. passing memory references
to internally-called functions is very efficient. Only functions of the same
contract instance can be called internally.

You should still avoid excessive recursion, as every internal function call
uses up at least one stack slot and there are only 1024 slots available.

.. _external-function-calls:

External Function Calls
-----------------------

Functions can also be called using the ``this.g(8);`` and ``c.g(2);`` notation, where
``c`` is a contract instance and ``g`` is a function belonging to ``c``.
Calling the function ``g`` via either way results in it being called "externally", using a
message call and not directly via jumps.
Please note that function calls on ``this`` cannot be used in the constructor,
as the actual contract has not been created yet.

Functions of other contracts have to be called externally. For an external call,
all function arguments have to be copied to memory.

.. note::
    A function call from one contract to another does not create its own transaction,
    it is a message call as part of the overall transaction.

When calling functions of other contracts, you can specify the amount of Wei or
gas sent with the call with the special options ``{value: 10, gas: 10000}``.
Note that it is discouraged to specify gas values explicitly, since the gas costs
of opcodes can change in the future. Any Wei you send to the contract is added
to the total balance of that contract:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.6.2 <0.9.0;

    contract InfoFeed {
        function info() public payable returns (uint ret) { return 42; }
    }

    contract Consumer {
        InfoFeed feed;
        function setFeed(InfoFeed addr) public { feed = addr; }
        function callFeed() public { feed.info{value: 10, gas: 800}(); }
    }

You need to use the modifier ``payable`` with the ``info`` function because
otherwise, the ``value`` option would not be available.

.. warning::
  Be careful that ``feed.info{value: 10, gas: 800}`` only locally sets the
  ``value`` and amount of ``gas`` sent with the function call, and the
  parentheses at the end perform the actual call. So
  ``feed.info{value: 10, gas: 800}`` does not call the function and
  the ``value`` and ``gas`` settings are lost, only
  ``feed.info{value: 10, gas: 800}()`` performs the function call.

.. warning::
    Due to the fact that the EVM considers a call to a non-existing contract to
    always succeed, Solidity uses the ``extcodesize`` opcode to check that
    the contract that is about to be called actually exists (it contains code)
    and causes an exception if it does not. This check is skipped if the return
    data will be decoded after the call and thus the ABI decoder will catch the
    case of a non-existing contract.

    This check is not performed in case of :ref:`low-level calls <address_related>` which
    operate on addresses rather than contract instances.

.. warning::
    Be careful when using high-level calls to
    :ref:`precompiled contracts <precompiledContracts>`,
    since the compiler considers them non-existing according to the
    above logic even though they execute code and can return data.

.. note::
    Since the version 0.8.10, the compiler does not check ``extcodesize`` on
    high-level external calls if return data is expected, because an empty code
    will be unable to return data, and the ABI decoder will revert.
    As a consequence, this allows high-level external calls to precompiled
    contracts, since they can return data despite having no code
    associated with their addresses.

    Read about :ref:`precompiled contracts <precompiledContracts>` and
    :ref:`low-level calls <address_related>`
    for more information.

Function calls also cause exceptions if the called contract itself
throws an exception or goes out of gas.

.. warning::
    Any interaction with another contract imposes a potential danger, especially
    if the source code of the contract is not known in advance. The
    current contract hands over control to the called contract and that may potentially
    do just about anything. Even if the called contract inherits from a known parent contract,
    the inheriting contract is only required to have a correct interface. The
    implementation of the contract, however, can be completely arbitrary and thus,
    pose a danger. In addition, be prepared in case it calls into other contracts of
    your system or even back into the calling contract before the first
    call returns. This means
    that the called contract can change state variables of the calling contract
    via its functions. Write your functions in a way that, for example, calls to
    external functions happen after any changes to state variables in your contract
    so your contract is not vulnerable to a reentrancy exploit.

.. note::
    Before Solidity 0.6.2, the recommended way to specify the value and gas was to
    use ``f.value(x).gas(g)()``. This was deprecated in Solidity 0.6.2 and is no
    longer possible since Solidity 0.7.0.

Function Calls with Named Parameters
------------------------------------

Function call arguments can be given by name, in any order,
if they are enclosed in ``{ }`` as can be seen in the following
example. The argument list has to coincide by name with the list of
parameters from the function declaration, but can be in arbitrary order.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.4.0 <0.9.0;

    contract C {
        mapping(uint => uint) data;

        function f() public {
            set({value: 2, key: 3});
        }

        function set(uint key, uint value) public {
            data[key] = value;
        }
    }

Omitted Names in Function Definitions
-------------------------------------

The names of parameters and return values in the function declaration can be omitted.
Those items with omitted names will still be present on the stack, but they are
inaccessible by name. An omitted return value name
can still return a value to the caller by use of the ``return`` statement.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.4.22 <0.9.0;

    contract C {
        // omitted name for parameter
        function func(uint k, uint) public pure returns(uint) {
            return k;
        }
    }


.. index:: ! new, contracts;creating

.. _creating-contracts:

Creating Contracts via ``new``
==============================

A contract can create other contracts using the ``new`` keyword. The full
code of the contract being created has to be known when the creating contract
is compiled so recursive creation-dependencies are not possible.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.7.0 <0.9.0;
    contract D {
        uint public x;
        constructor(uint a) payable {
            x = a;
        }
    }

    contract C {
        D d = new D(4); // will be executed as part of C's constructor

        function createD(uint arg) public {
            D newD = new D(arg);
            newD.x();
        }

        function createAndEndowD(uint arg, uint amount) public payable {
            // Send ether along with the creation
            D newD = new D{value: amount}(arg);
            newD.x();
        }
    }

As seen in the example, it is possible to send Ether while creating
an instance of ``D`` using the ``value`` option, but it is not possible
to limit the amount of gas.
If the creation fails (due to out-of-stack, not enough balance or other problems),
an exception is thrown.

.. _salted-contract-creations:

Salted contract creations / create2
-----------------------------------

When creating a contract, the address of the contract is computed from
the address of the creating contract and a counter that is increased with
each contract creation.

If you specify the option ``salt`` (a bytes32 value), then contract creation will
use a different mechanism to come up with the address of the new contract:

It will compute the address from the address of the creating contract,
the given salt value, the (creation) bytecode of the created contract and the constructor
arguments.

In particular, the counter ("nonce") is not used. This allows for more flexibility
in creating contracts: You are able to derive the address of the
new contract before it is created. Furthermore, you can rely on this address
also in case the creating
contracts creates other contracts in the meantime.

The main use-case here is contracts that act as judges for off-chain interactions,
which only need to be created if there is a dispute.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.7.0 <0.9.0;
    contract D {
        uint public x;
        constructor(uint a) {
            x = a;
        }
    }

    contract C {
        function createDSalted(bytes32 salt, uint arg) public {
            // This complicated expression just tells you how the address
            // can be pre-computed. It is just there for illustration.
            // You actually only need ``new D{salt: salt}(arg)``.
            address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
                bytes1(0xff),
                address(this),
                salt,
                keccak256(abi.encodePacked(
                    type(D).creationCode,
                    abi.encode(arg)
                ))
            )))));

            D d = new D{salt: salt}(arg);
            require(address(d) == predictedAddress);
        }
    }

.. warning::
    There are some peculiarities in relation to salted creation. A contract can be
    re-created at the same address after having been destroyed. Yet, it is possible
    for that newly created contract to have a different deployed bytecode even
    though the creation bytecode has been the same (which is a requirement because
    otherwise the address would change). This is due to the fact that the constructor
    can query external state that might have changed between the two creations
    and incorporate that into the deployed bytecode before it is stored.


.. _order-of-evaluation:

Order of Evaluation of Expressions
==================================

The evaluation order of expressions is not specified (more formally, the order
in which the children of one node in the expression tree are evaluated is not
specified, but they are of course evaluated before the node itself). It is only
guaranteed that statements are executed in order and short-circuiting for
boolean expressions is done.

.. index:: ! assignment

Assignment
==========

.. index:: ! assignment;destructuring

.. _destructuring-assignments:

Destructuring Assignments and Returning Multiple Values
-------------------------------------------------------

Solidity internally allows tuple types, i.e. a list of objects
of potentially different types whose number is a constant at
compile-time. Those tuples can be used to return multiple values at the same time.
These can then either be assigned to newly declared variables
or to pre-existing variables (or LValues in general).

Tuples are not proper types in Solidity, they can only be used to form syntactic
groupings of expressions.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.5.0 <0.9.0;

    contract C {
        uint index;

        function f() public pure returns (uint, bool, uint) {
            return (7, true, 2);
        }

        function g() public {
            // Variables declared with type and assigned from the returned tuple,
            // not all elements have to be specified (but the number must match).
            (uint x, , uint y) = f();
            // Common trick to swap values -- does not work for non-value storage types.
            (x, y) = (y, x);
            // Components can be left out (also for variable declarations).
            (index, , ) = f(); // Sets the index to 7
        }
    }

It is not possible to mix variable declarations and non-declaration assignments,
i.e. the following is not valid: ``(x, uint y) = (1, 2);``

.. note::
    Prior to version 0.5.0 it was possible to assign to tuples of smaller size, either
    filling up on the left or on the right side (which ever was empty). This is
    now disallowed, so both sides have to have the same number of components.

.. warning::
    Be careful when assigning to multiple variables at the same time when
    reference types are involved, because it could lead to unexpected
    copying behavior.

Complications for Arrays and Structs
------------------------------------

The semantics of assignments are more complicated for non-value types like arrays and structs,
including ``bytes`` and ``string``, see :ref:`Data location and assignment behavior <data-location-assignment>` for details.

In the example below the call to ``g(x)`` has no effect on ``x`` because it creates
an independent copy of the storage value in memory. However, ``h(x)`` successfully modifies ``x``
because only a reference and not a copy is passed.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.4.22 <0.9.0;

    contract C {
        uint[20] x;

        function f() public {
            g(x);
            h(x);
        }

        function g(uint[20] memory y) internal pure {
            y[2] = 3;
        }

        function h(uint[20] storage y) internal {
            y[3] = 4;
        }
    }

.. index:: ! scoping, declarations, default value

.. _default-value:

Scoping and Declarations
========================

A variable which is declared will have an initial default
value whose byte-representation is all zeros.
The "default values" of variables are the typical "zero-state"
of whatever the type is. For example, the default value for a ``bool``
is ``false``. The default value for the ``uint`` or ``int``
types is ``0``. For statically-sized arrays and ``bytes1`` to
``bytes32``, each individual
element will be initialized to the default value corresponding
to its type. For dynamically-sized arrays, ``bytes``
and ``string``, the default value is an empty array or string.
For the ``enum`` type, the default value is its first member.

Scoping in Solidity follows the widespread scoping rules of C99
(and many other languages): Variables are visible from the point right after their declaration
until the end of the smallest ``{ }``-block that contains the declaration.
As an exception to this rule, variables declared in the
initialization part of a for-loop are only visible until the end of the for-loop.

Variables that are parameter-like (function parameters, modifier parameters,
catch parameters, ...) are visible inside the code block that follows -
the body of the function/modifier for a function and modifier parameter and the catch block
for a catch parameter.

Variables and other items declared outside of a code block, for example functions, contracts,
user-defined types, etc., are visible even before they were declared. This means you can
use state variables before they are declared and call functions recursively.

As a consequence, the following examples will compile without warnings, since
the two variables have the same name but disjoint scopes.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.5.0 <0.9.0;
    contract C {
        function minimalScoping() pure public {
            {
                uint same;
                same = 1;
            }

            {
                uint same;
                same = 3;
            }
        }
    }

As a special example of the C99 scoping rules, note that in the following,
the first assignment to ``x`` will actually assign the outer and not the inner variable.
In any case, you will get a warning about the outer variable being shadowed.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.5.0 <0.9.0;
    // This will report a warning
    contract C {
        function f() pure public returns (uint) {
            uint x = 1;
            {
                x = 2; // this will assign to the outer variable
                uint x;
            }
            return x; // x has value 2
        }
    }

.. warning::
    Before version 0.5.0 Solidity followed the same scoping rules as
    JavaScript, that is, a variable declared anywhere within a function would be in scope
    for the entire function, regardless where it was declared. The following example shows a code snippet that used
    to compile but leads to an error starting from version 0.5.0.

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.5.0 <0.9.0;
    // This will not compile
    contract C {
        function f() pure public returns (uint) {
            x = 2;
            uint x;
            return x;
        }
    }


.. index:: ! safe math, safemath, checked, unchecked
.. _unchecked:

Checked or Unchecked Arithmetic
===============================

An overflow or underflow is the situation where the resulting value of an arithmetic operation,
when executed on an unrestricted integer, falls outside the range of the result type.

Prior to Solidity 0.8.0, arithmetic operations would always wrap in case of
under- or overflow leading to widespread use of libraries that introduce
additional checks.

Since Solidity 0.8.0, all arithmetic operations revert on over- and underflow by default,
thus making the use of these libraries unnecessary.

To obtain the previous behavior, an ``unchecked`` block can be used:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.0;
    contract C {
        function f(uint a, uint b) pure public returns (uint) {
            // This subtraction will wrap on underflow.
            unchecked { return a - b; }
        }
        function g(uint a, uint b) pure public returns (uint) {
            // This subtraction will revert on underflow.
            return a - b;
        }
    }

The call to ``f(2, 3)`` will return ``2**256-1``, while ``g(2, 3)`` will cause
a failing assertion.

The ``unchecked`` block can be used everywhere inside a block, but not as a replacement
for a block. It also cannot be nested.

The setting only affects the statements that are syntactically inside the block.
Functions called from within an ``unchecked`` block do not inherit the property.

.. note::
    To avoid ambiguity, you cannot use ``_;`` inside an ``unchecked`` block.

The following operators will cause a failing assertion on overflow or underflow
and will wrap without an error if used inside an unchecked block:

``++``, ``--``, ``+``, binary ``-``, unary ``-``, ``*``, ``/``, ``%``, ``**``

``+=``, ``-=``, ``*=``, ``/=``, ``%=``

.. warning::
    It is not possible to disable the check for division by zero
    or modulo by zero using the ``unchecked`` block.

.. note::
   Bitwise operators do not perform overflow or underflow checks.
   This is particularly visible when using bitwise shifts (``<<``, ``>>``, ``<<=``, ``>>=``) in
   place of integer division and multiplication by a power of 2.
   For example ``type(uint256).max << 3`` does not revert even though ``type(uint256).max * 8`` would.

.. note::
    The second statement in ``int x = type(int).min; -x;`` will result in an overflow
    because the negative range can hold one more value than the positive range.

Explicit type conversions will always truncate and never cause a failing assertion
with the exception of a conversion from an integer to an enum type.

.. index:: ! exception, ! throw, ! assert, ! require, ! revert, ! errors

.. _assert-and-require:

Error handling: Assert, Require, Revert and Exceptions
======================================================

Solidity uses state-reverting exceptions to handle errors.
Such an exception undoes all changes made to the
state in the current call (and all its sub-calls) and
flags an error to the caller.

When exceptions happen in a sub-call, they "bubble up" (i.e.,
exceptions are rethrown) automatically unless they are caught in
a ``try/catch`` statement. Exceptions to this rule are ``send``
and the low-level functions ``call``, ``delegatecall`` and
``staticcall``: they return ``false`` as their first return value in case
of an exception instead of "bubbling up".

.. warning::
    The low-level functions ``call``, ``delegatecall`` and
    ``staticcall`` return ``true`` as their first return value
    if the account called is non-existent, as part of the design
    of the EVM. Account existence must be checked prior to calling if needed.

Exceptions can contain error data that is passed back to the caller
in the form of :ref:`error instances <errors>`.
The built-in errors ``Error(string)`` and ``Panic(uint256)`` are
used by special functions, as explained below. ``Error`` is used for "regular" error conditions
while ``Panic`` is used for errors that should not be present in bug-free code.

.. _assert-and-require-statements:

Panic via ``assert`` and Error via ``require``
----------------------------------------------

The convenience functions ``assert`` and ``require`` can be used to check for conditions and throw an exception
if the condition is not met.

The ``assert`` function creates an error of type ``Panic(uint256)``.
The same error is created by the compiler in certain situations as listed below.

Assert should only be used to test for internal
errors, and to check invariants. Properly functioning code should
never create a Panic, not even on invalid external input.
If this happens, then there
is a bug in your contract which you should fix. Language analysis
tools can evaluate your contract to identify the conditions and
function calls which will cause a Panic.

A Panic exception is generated in the following situations.
The error code supplied with the error data indicates the kind of panic.

#. 0x00: Used for generic compiler inserted panics.
#. 0x01: If you call ``assert`` with an argument that evaluates to false.
#. 0x11: If an arithmetic operation results in underflow or overflow outside of an ``unchecked { ... }`` block.
#. 0x12; If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
#. 0x21: If you convert a value that is too big or negative into an enum type.
#. 0x22: If you access a storage byte array that is incorrectly encoded.
#. 0x31: If you call ``.pop()`` on an empty array.
#. 0x32: If you access an array, ``bytesN`` or an array slice at an out-of-bounds or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``).
#. 0x41: If you allocate too much memory or create an array that is too large.
#. 0x51: If you call a zero-initialized variable of internal function type.

The ``require`` function provides three overloads:

1. ``require(bool)`` which will revert without any data (not even an error selector).
2. ``require(bool, string)`` which will revert with an ``Error(string)``.
3. ``require(bool, error)`` which will revert with the custom, user supplied error provided as the second argument.

.. note::
    ``require`` arguments are evaluated unconditionally, so take special care to make sure that
    they are not expressions with unexpected side-effects.
    For example, in ``require(condition, CustomError(f()));`` and ``require(condition, f());``,
    function ``f()`` will be called regardless of whether the supplied condition is ``true`` or ``false``.

An ``Error(string)`` exception (or an exception without data) is generated
by the compiler in the following situations:

#. Calling ``require(x)`` where ``x`` evaluates to ``false``.
#. If you use ``revert()`` or ``revert("description")``.
#. If you perform an external function call targeting a contract that contains no code.
#. If your contract receives Ether via a public function without
   ``payable`` modifier (including the constructor and the fallback function).
#. If your contract receives Ether via a public getter function.

For the following cases, the error data from the external call
(if provided) is forwarded. This means that it can either cause
an ``Error`` or a ``Panic`` (or whatever else was given):

#. If a ``.transfer()`` fails.
#. If you call a function via a message call but it does not finish
   properly (i.e., it runs out of gas, has no matching function, or
   throws an exception itself), except when a low level operation
   ``call``, ``send``, ``delegatecall``, ``callcode`` or ``staticcall``
   is used. The low level operations never throw exceptions but
   indicate failures by returning ``false``.
#. If you create a contract using the ``new`` keyword but the contract
   creation :ref:`does not finish properly<creating-contracts>`.

You can optionally provide a message string or a custom error to ``require``, but not to ``assert``.

.. note::
    If you do not provide a string or custom error argument to ``require``, it will revert
    with empty error data, not even including the error selector.


The following example shows how you can use ``require`` to check conditions on inputs
and ``assert`` for internal error checking.

.. code-block:: solidity
    :force:

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.6.2 <0.9.0;

    contract Sharer {
        function sendHalf(address payable addr) public payable returns (uint balance) {
            require(msg.value % 2 == 0, "Even value required.");
            uint balanceBeforeTransfer = address(this).balance;
            (bool success, ) = addr.call{value: msg.value / 2}("");
            require(success);
            // Since require will stop execution and revert if success is false,
            // there should be no way for us to still have half of the Ether.
            assert(address(this).balance == balanceBeforeTransfer - msg.value / 2);
            return address(this).balance;
        }
    }

Internally, Solidity performs a revert operation (instruction
``0xfd``). This causes
the EVM to revert all changes made to the state. The reason for reverting
is that there is no safe way to continue execution, because an expected effect
did not occur. Because we want to keep the atomicity of transactions, the
safest action is to revert all changes and make the whole transaction
(or at least call) without effect.

In both cases, the caller can react on such failures using ``try``/``catch``, but
the changes in the callee will always be reverted.

.. note::

    Panic exceptions used to use the ``invalid`` opcode before Solidity 0.8.0,
    which consumed all gas available to the call.
    Exceptions that use ``require`` used to consume all gas until before the Metropolis release.

.. _revert-statement:

``revert``
----------

A direct revert can be triggered using the ``revert`` statement and the ``revert`` function.

The ``revert`` statement takes a custom error as direct argument without parentheses:

    revert CustomError(arg1, arg2);

For backward-compatibility reasons, there is also the ``revert()`` function, which uses parentheses
and accepts a string:

    revert();
    revert("description");

The error data will be passed back to the caller and can be caught there.
Using ``revert()`` causes a revert without any error data while ``revert("description")``
will create an ``Error(string)`` error.

Using a custom error instance will usually be much cheaper than a string description,
because you can use the name of the error to describe it, which is encoded in only
four bytes. A longer description can be supplied via NatSpec which does not incur
any costs.

The following example shows how to use an error string and a custom error instance
together with ``revert`` and the equivalent ``require``:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;

    contract VendingMachine {
        address owner;
        error Unauthorized();
        function buy(uint amount) public payable {
            if (amount > msg.value / 2 ether)
                revert("Not enough Ether provided.");
            // Alternative way to do it:
            require(
                amount <= msg.value / 2 ether,
                "Not enough Ether provided."
            );
            // Perform the purchase.
        }
        function withdraw() public {
            if (msg.sender != owner)
                revert Unauthorized();

            (bool success, ) = payable(msg.sender).call{value: address(this).balance}("");
            require(success);
        }
    }

The two ways ``if (!condition) revert(...);`` and ``require(condition, ...);`` are
equivalent as long as the arguments to ``revert`` and ``require`` do not have side-effects,
for example if they are just strings.

.. note::
    The ``require`` function is evaluated just as any other function.
    This means that all arguments are evaluated before the function itself is executed.
    In particular, in ``require(condition, f())`` the function ``f`` is executed even if
    ``condition`` is true.

The provided string is :ref:`abi-encoded <ABI>` as if it were a call to a function ``Error(string)``.
In the above example, ``revert("Not enough Ether provided.");`` returns the following hexadecimal as error return data:

.. code::

    0x08c379a0                                                         // Function selector for Error(string)
    0x0000000000000000000000000000000000000000000000000000000000000020 // Data offset
    0x000000000000000000000000000000000000000000000000000000000000001a // String length
    0x4e6f7420656e6f7567682045746865722070726f76696465642e000000000000 // String data

The provided message can be retrieved by the caller using ``try``/``catch`` as shown below.

.. note::
    There used to be a keyword called ``throw`` with the same semantics as ``revert()`` which
    was deprecated in version 0.4.13 and removed in version 0.5.0.


.. _try-catch:

``try``/``catch``
-----------------

A failure in an external call can be caught using a try/catch statement, as follows:

.. code-block:: solidity

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.8.1;

    interface DataFeed { function getData(address token) external returns (uint value); }

    contract FeedConsumer {
        DataFeed feed;
        uint errorCount;
        function rate(address token) public returns (uint value, bool success) {
            // Permanently disable the mechanism if there are
            // more than 10 errors.
            require(errorCount < 10);
            try feed.getData(token) returns (uint v) {
                return (v, true);
            } catch Error(string memory /*reason*/) {
                // This is executed in case
                // revert was called inside getData
                // and a reason string was provided.
                errorCount++;
                return (0, false);
            } catch Panic(uint /*errorCode*/) {
                // This is executed in case of a panic,
                // i.e. a serious error like division by zero
                // or overflow. The error code can be used
                // to determine the kind of error.
                errorCount++;
                return (0, false);
            } catch (bytes memory /*lowLevelData*/) {
                // This is executed in case revert() was used.
                errorCount++;
                return (0, false);
            }
        }
    }

The ``try`` keyword has to be followed by an expression representing an external function call
or a contract creation (``new ContractName()``).
Errors inside the expression are not caught (for example if it is a complex expression
that also involves internal function calls), only a revert happening inside the external
call itself. The ``returns`` part (which is optional) that follows declares return variables
matching the types returned by the external call. In case there was no error,
these variables are assigned and the contract's execution continues inside the
first success block. If the end of the success block is reached, execution continues after the ``catch`` blocks.

Solidity supports different kinds of catch blocks depending on the
type of error:

- ``catch Error(string memory reason) { ... }``: This catch clause is executed if the error was caused by ``revert("reasonString")`` or
  ``require(false, "reasonString")`` (or an internal error that causes such an
  exception).

- ``catch Panic(uint errorCode) { ... }``: If the error was caused by a panic, i.e. by a failing ``assert``, division by zero,
  invalid array access, arithmetic overflow and others, this catch clause will be run.

- ``catch (bytes memory lowLevelData) { ... }``: This clause is executed if the error signature
  does not match any other clause, if there was an error while decoding the error
  message, or
  if no error data was provided with the exception.
  The declared variable provides access to the low-level error data in that case.

- ``catch { ... }``: If you are not interested in the error data, you can just use
  ``catch { ... }`` (even as the only catch clause) instead of the previous clause.


It is planned to support other types of error data in the future.
The strings ``Error`` and ``Panic`` are currently parsed as is and are not treated as identifiers.

In order to catch all error cases, you have to have at least the clause
``catch { ...}`` or the clause ``catch (bytes memory lowLevelData) { ... }``.

The variables declared in the ``returns`` and the ``catch`` clause are only
in scope in the block that follows.

.. note::

    If an error happens during the decoding of the return data
    inside a try/catch-statement, this causes an exception in the currently
    executing contract and because of that, it is not caught in the catch clause.
    If there is an error during decoding of ``catch Error(string memory reason)``
    and there is a low-level catch clause, this error is caught there.

.. note::

    If execution reaches a catch-block, then the state-changing effects of
    the external call have been reverted. If execution reaches
    the success block, the effects were not reverted.
    If the effects have been reverted, then execution either continues
    in a catch block or the execution of the try/catch statement itself
    reverts (for example due to decoding failures as noted above or
    due to not providing a low-level catch clause).

.. note::
    The reason behind a failed call can be manifold. Do not assume that
    the error message is coming directly from the called contract:
    The error might have happened deeper down in the call chain and the
    called contract just forwarded it. Also, it could be due to an
    out-of-gas situation and not a deliberate error condition:
    The caller always retains at least 1/64th of the gas in a call and thus
    even if the called contract goes out of gas, the caller still
    has some gas left.

---

### Credits And Attribution (`docs/credits-and-attribution.rst`)

.. This page is meant to be linked to from the footer.

:orphan:

#######################
Credits and Attribution
#######################

Website icons
=============

.. |icon-share-solid| image:: _static/img/solid-share-arrow.svg
.. _share icon: https://fontawesome.com/v5.15/icons/share?style=solid
.. _Font Awesome Free License: https://fontawesome.com/license/free

+-------------------------+-----------------------------------------------------------------------+
| Icon                    | Attribution                                                           |
+=========================+=======================================================================+
| |icon-share-solid|      | - Source: `share icon`_ from Font Awesome 5.15.0.                     |
|                         | - License: `Font Awesome Free License`_ (CC BY 4.0).                  |
+-------------------------+-----------------------------------------------------------------------+

---

### Frequently Reported Non Bugs (`docs/frequently-reported-non-bugs.rst`)

.. _frequently-reported-non-bugs:

############################
Frequently Reported Non-Bugs
############################

The behaviors listed below are reported as compiler bugs on a regular basis,
but are either intentional, documented, or explicitly not guaranteed by the language.

The list of actual bugs is tracked in the :ref:`list of known bugs<known_bugs>`.

Non-canonical ABI-encoded calldata is accepted
==============================================

Offsets that point backwards, overlap, or leave gaps are not necessarily rejected,
and trailing data past the encoded arguments is ignored.
The Solidity decoder does not enforce :ref:`strict encoding mode<abi_packed_mode>`;
the invariant we uphold is that decoding must not read beyond ``calldatasize()``.

Different results between the evmasm and the IR pipeline
========================================================

The two pipelines have some semantic differences.
Known and intentional divergences are listed in :ref:`Solidity IR-based Codegen Changes<ir-breaking-changes>`,
in particular :ref:`cleanup behavior<ir-cleanup>` differs.

Order of evaluation
===================

The :ref:`evaluation order of expressions is unspecified<order-of-evaluation>` and this includes the components
of tuple assignments and returns (see also :ref:`Tuples are not proper types<destructuring-assignments>`).
Only statement order and short-circuiting of boolean operators are guaranteed.
Note that :ref:`assignments involving reference types<data-location-assignment>` copy or alias depending on
data location, which is documented behavior and not an aliasing bug by itself.

Stale references into storage
=============================

A reference to a storage array element can be left dangling by anything that resizes or relocates the
containing array, for example a ``.pop()``, a ``.push()`` that switches a ``bytes`` array
:ref:`from short to long layout<bytes-and-string>`, or an assignment to the array itself as in ``(s[0], s) = (x, y)``.
Writing through such a reference is not rejected and may write outside the data area of the array.

This is :ref:`documented behavior<dangling-storage-references>`, and code containing dangling
references is explicitly considered to have *undefined behavior*.

---

### Grammar (`docs/grammar.rst`)

****************
Language Grammar
****************

.. syntax:autogrammar:: SolidityParser.g4
   :root-rule: SolidityParser.sourceUnit
   :undocumented:
   :cc-to-dash:

.. syntax:autogrammar:: SolidityLexer.g4
   :root-rule: SolidityParser.sourceUnit
   :fragments:
   :cc-to-dash:

---

### Index (`docs/index.rst`)

Solidity
========

Solidity is an object-oriented, high-level language for implementing smart contracts.
Smart contracts are programs that govern the behavior of accounts within the Ethereum state.

Solidity is a `curly-bracket language <https://en.wikipedia.org/wiki/List_of_programming_languages_by_type#Curly_bracket_languages>`_ designed to target the Ethereum Virtual Machine (EVM).
It is influenced by C++, Python, and JavaScript.
You can find more details about which languages Solidity has been inspired by in the :doc:`language influences <language-influences>` section.

Solidity is statically typed, supports inheritance, libraries, and complex user-defined types, among other features.

With Solidity, you can create contracts for uses such as voting, crowdfunding, blind auctions, and multi-signature wallets.

When deploying contracts, you should use the latest released version of Solidity.
Apart from exceptional cases, only the latest version receives
`security fixes <https://github.com/argotorg/solidity/security/policy#supported-versions>`_.
Furthermore, breaking changes, as well as new features, are introduced regularly.
We currently use a 0.y.z version number `to indicate this fast pace of change <https://semver.org/#spec-item-4>`_.

.. warning::

  The Solidity 0.8.x release introduced a lot of breaking changes.
  Make sure you read :doc:`the full list <080-breaking-changes>`.

Ideas for improving Solidity or this documentation are always welcome,
read our :doc:`contributors guide <contributing>` for more details.

.. Hint::

  You can download this documentation as PDF, HTML or Epub
  by clicking on the versions flyout menu in the bottom-right corner and selecting the preferred download format.


Getting Started
---------------

**1. Understand the Smart Contract Basics**

If you are new to the concept of smart contracts, we recommend you to get started by digging into the "Introduction to Smart Contracts" section, which covers the following:

* :ref:`A simple example smart contract <simple-smart-contract>` written in Solidity.
* :ref:`Blockchain Basics <blockchain-basics>`.
* :ref:`The Ethereum Virtual Machine <the-ethereum-virtual-machine>`.

**2. Get to Know Solidity**

Once you are accustomed to the basics, we recommend you read the :doc:`"Solidity by Example" <solidity-by-example>`
and “Language Description” sections to understand the core concepts of the language.

**3. Install the Solidity Compiler**

There are various ways to install the Solidity compiler,
simply choose your preferred option and follow the steps outlined on the :ref:`installation page <installing-solidity>`.

.. hint::
  You can try out code examples directly in your browser with the
  `Remix IDE <https://remix.ethereum.org>`_.
  Remix is a web browser-based IDE that allows you to write, deploy and administer Solidity smart contracts,
  without the need to install Solidity locally.

.. warning::
    As humans write software, it can have bugs.
    Therefore, you should follow established software development best practices when writing your smart contracts.
    This includes code review, testing, audits, and correctness proofs.
    Smart contract users are sometimes more confident with code than their authors,
    and blockchains and smart contracts have their own unique issues to watch out for,
    so before working on production code, make sure you read the :ref:`security_considerations` section.

**4. Learn More**

If you want to learn more about building decentralized applications on Ethereum,
the `Ethereum Developer Resources <https://ethereum.org/en/developers/>`_ can help you with further general documentation around Ethereum,
and a wide selection of tutorials, tools, and development frameworks.

If you have any questions, you can try searching for answers or asking on the
`Ethereum StackExchange <https://ethereum.stackexchange.com/>`_,
or our `Matrix channel <https://matrix.to/#/#ethereum\_solidity:gitter.im>`_.

.. _translations:

Translations
------------

Community contributors help translate this documentation into several languages.
Note that they have varying degrees of completeness and up-to-dateness.
The English version stands as a reference.

You can switch between languages by clicking on the flyout menu in the bottom-right corner
and selecting the preferred language.

* `Chinese <https://docs.soliditylang.org/zh-cn/latest/>`_
* `French <https://docs.soliditylang.org/fr/latest/>`_
* `Indonesian <https://github.com/solidity-docs/id-indonesian>`_
* `Japanese <https://github.com/solidity-docs/ja-japanese>`_
* `Korean <https://github.com/solidity-docs/ko-korean>`_
* `Persian <https://github.com/solidity-docs/fa-persian>`_
* `Russian <https://github.com/solidity-docs/ru-russian>`_
* `Spanish <https://github.com/solidity-docs/es-spanish>`_
* `Turkish <https://docs.soliditylang.org/tr/latest/>`_

.. note::

   We set up a GitHub organization and translation workflow to help streamline the community efforts.
   Please refer to the translation guide in the `solidity-docs org <https://github.com/solidity-docs>`_
   for information on how to start a new language or contribute to the community translations.

Contents
========

:ref:`Keyword Index <genindex>`, :ref:`Search Page <search>`

.. toctree::
   :maxdepth: 2
   :caption: Basics

   introduction-to-smart-contracts.rst
   solidity-by-example.rst
   installing-solidity.rst

.. toctree::
   :maxdepth: 2
   :caption: Language Description

   layout-of-source-files.rst
   structure-of-a-contract.rst
   types.rst
   units-and-global-variables.rst
   control-structures.rst
   contracts.rst
   assembly.rst
   cheatsheet.rst
   grammar.rst

.. toctree::
   :maxdepth: 2
   :caption: Compiler

   using-the-compiler.rst
   analysing-compilation-output.rst
   ir-breaking-changes.rst

.. toctree::
   :maxdepth: 2
   :caption: Internals

   internals/layout_in_storage.rst
   internals/layout_in_memory.rst
   internals/layout_in_calldata.rst
   internals/variable_cleanup.rst
   internals/source_mappings.rst
   internals/optimizer.rst
   metadata.rst
   abi-spec.rst

.. toctree::
   :maxdepth: 2
   :caption: Advisory content

   security-considerations.rst
   bugs.rst
   frequently-reported-non-bugs.rst
   050-breaking-changes.rst
   060-breaking-changes.rst
   070-breaking-changes.rst
   080-breaking-changes.rst

.. toctree::
   :maxdepth: 2
   :caption: Additional Material

   natspec-format.rst
   smtchecker.rst
   yul.rst
   path-resolution.rst

.. toctree::
   :maxdepth: 2
   :caption: Resources

   style-guide.rst
   common-patterns.rst
   resources.rst
   contributing.rst
   language-influences.rst
   brand-guide.rst

---

### Installing Solidity (`docs/installing-solidity.rst`)

.. index:: ! installing

.. _installing-solidity:

################################
Installing the Solidity Compiler
################################

Versioning
==========

Solidity versions follow `Semantic Versioning <https://semver.org>`_. In
addition, patch-level releases with major release 0 (i.e. 0.x.y) will not
contain breaking changes. That means code that compiles with version 0.x.y
can be expected to compile with 0.x.z where z > y.

In addition to releases, we provide **prereleases** and **nightly development builds** to make it
easy for developers to try out upcoming features and provide early feedback.
Note that such builds contain bleeding-edge code from the development branch and are not guaranteed
to be of the same quality as full releases.
Despite our best efforts, they might contain undocumented and/or broken changes that will not
become a part of an actual release. They are not meant for production use.

When deploying contracts, you should use the latest released version of Solidity. This
is because breaking changes, as well as new features and bug fixes are introduced regularly.
We currently use a 0.x version number `to indicate this fast pace of change <https://semver.org/#spec-item-4>`_.

Remix
=====

*We recommend Remix for small contracts and for quickly learning Solidity.*

`Access Remix online <https://remix.ethereum.org/>`_, you do not need to install anything.
If you want to use it without connection to the Internet, download Remix Desktop from `the releases page <https://github.com/remix-project-org/remix-desktop/releases/>`_.
Remix is also a convenient option for testing nightly builds
without installing multiple Solidity versions.

Further options on this page detail installing command-line Solidity compiler software
on your computer. Choose a command-line compiler if you are working on a larger contract
or if you require more compilation options.

.. _solcjs:

npm / Node.js
=============

Use ``npm`` for a convenient and portable way to install ``solcjs``, a Solidity compiler. The
``solcjs`` program has fewer features than the ways to access the compiler described
further down this page. The
:ref:`commandline-compiler` documentation assumes you are using
the full-featured compiler, ``solc``. The usage of ``solcjs`` is documented inside its own
`repository <https://github.com/argotorg/solc-js>`_.

Note: The solc-js project is derived from the C++
``solc`` by using Emscripten, which means that both use the same compiler source code.
``solc-js`` can be used in JavaScript projects directly (such as Remix).
Please refer to the solc-js repository for instructions.

.. code-block:: bash

    npm install solc

.. note::

    The command-line executable is named ``solcjs``.

    The command-line options of ``solcjs`` are not compatible with ``solc`` and tools (such as ``geth``)
    expecting the behavior of ``solc`` will not work with ``solcjs``.

Docker
======

Docker images of Solidity builds are available using the `solc <https://github.com/argotorg/solidity/pkgs/container/solc>`_ image from the argotorg organization on ghcr.io.
Use the ``stable`` tag for the latest released version, and ``nightly`` for potentially unstable changes in the ``develop`` branch.

The Docker image runs the compiler executable so that you can pass all compiler arguments to it.
For example, the command below pulls the stable version of the ``solc`` image (if you do not have it already),
and runs it in a new container, passing the ``--help`` argument.

.. code-block:: bash

    docker run ghcr.io/argotorg/solc:stable --help

.. note::

    Specific compiler versions are supported as the Docker image tag such as ``ghcr.io/argotorg/solc:0.8.23``.
    We will be passing the ``stable`` tag here instead of specific version tag to ensure that users get
    the latest version by default and avoid the issue of an out-of-date version.

To use the Docker image to compile Solidity files on the host machine, mount a
local folder for input and output, and specify the contract to compile. For example:

.. code-block:: bash

    docker run \
        --volume "/tmp/some/local/path/:/sources/" \
        ghcr.io/argotorg/solc:stable \
            /sources/Contract.sol \
            --abi \
            --bin \
            --output-dir /sources/output/

You can also use the standard JSON interface (which is recommended when using the compiler with tooling).
When using this interface, it is not necessary to mount any directories as long as the JSON input is
self-contained (i.e. it does not refer to any external files that would have to be
:ref:`loaded by the import callback <initial-vfs-content-standard-json-with-import-callback>`).

.. code-block:: bash

    docker run ghcr.io/argotorg/solc:stable --standard-json < input.json > output.json

Linux Packages
==============

We provide :ref:`standalone binaries <static-binaries>` of the compiler that should run on most
distributions without any additional installation steps.

Ubuntu packages for versions up to 0.8.30 are available in the
`ethereum/ethereum PPA <https://launchpad.net/~ethereum/+archive/ubuntu/ethereum>`_.
However, we have discontinued this distribution method and future versions will not be added there.

Some Linux distributions provide their own packages.
These packages are not directly maintained by us but usually kept up-to-date by the respective
package maintainers.

Unofficial, community-maintained scripts for building and installing the compiler are also
available for some distributions:

- Arch Linux / (AUR):

    - `solidity <https://aur.archlinux.org/packages/solidity>`_ (builds from source),
    - `solidity-bin <https://aur.archlinux.org/packages/solidity-bin>`_ (uses our standalone binaries).

- Nix:

    - `solc.nix <https://github.com/hellwolf/solc.nix>`_ (builds from source).

.. note::

    Please be aware that these scripts are produced and maintained by users and not vetted in any
    way by the distro maintainers.
    Exercise caution when using them.

There is also a `snap package <https://snapcraft.io/solc>`_, however, it is **currently unmaintained**.
It is installable in all the `supported Linux distros <https://snapcraft.io/docs/reference/administration/distribution-support/>`_. To
install the latest stable version of solc:

.. code-block:: bash

    sudo snap install solc

If you want to help testing the latest development version of Solidity
with the most recent changes, please use the following:

.. code-block:: bash

    sudo snap install solc --edge

.. note::

    The ``solc`` snap uses strict confinement. This is the most secure mode for snap packages
    but it comes with limitations, like accessing only the files in your ``/home`` and ``/media`` directories.
    For more information, go to `Demystifying Snap Confinement <https://snapcraft.io/blog/demystifying-snap-confinement>`_.


macOS Packages
==============

We distribute the Solidity compiler through Homebrew
as a build-from-source version. Pre-built bottles are
currently not supported.

.. code-block:: bash

    brew update
    brew upgrade
    brew tap ethereum/ethereum
    brew install solidity

To install the most recent 0.4.x / 0.5.x version of Solidity you can also use ``brew install solidity@4``
and ``brew install solidity@5``, respectively.

If you need a specific version of Solidity you can install a
Homebrew formula directly from Github.

View
`solidity.rb commits on GitHub <https://github.com/ethereum/homebrew-ethereum/commits/master/solidity.rb>`_.

Copy the commit hash of the version you want and check it out on your machine.

.. code-block:: bash

    git clone https://github.com/ethereum/homebrew-ethereum.git
    cd homebrew-ethereum
    git checkout <your-hash-goes-here>

Install it using ``brew``:

.. code-block:: bash

    brew unlink solidity
    # eg. Install 0.4.8
    brew install solidity.rb

.. _static-binaries:

Static Binaries
===============

We maintain a repository containing static builds of past and current compiler versions for all
supported platforms at `solc-bin`_. This is also the location where you can find the nightly builds.

The repository is not only a quick and easy way for end users to get binaries ready to be used
out-of-the-box but it is also meant to be friendly to third-party tools:

- The content is mirrored to https://binaries.soliditylang.org where it can be easily downloaded over
  HTTPS without any authentication, rate limiting or the need to use git.
- Content is served with correct ``Content-Type`` headers and lenient CORS configuration so that it
  can be directly loaded by tools running in the browser.
- Binaries do not require installation or unpacking (exception for older Windows builds
  bundled with necessary DLLs).
- We strive for a high level of backward-compatibility. Files, once added, are not removed or moved
  without providing a symlink/redirect at the old location. They are also never modified
  in place and should always match the original checksum. The only exception would be broken or
  unusable files with the potential to cause more harm than good if left as is.
- Files are served over both HTTP and HTTPS. As long as you obtain the file list in a secure way
  (via git, HTTPS, IPFS or just have it cached locally) and verify hashes of the binaries
  after downloading them, you do not have to use HTTPS for the binaries themselves.

The same binaries are in most cases available on the `Solidity release page on GitHub`_. The
difference is that we do not generally update old releases on the GitHub release page. This means
that we do not rename them if the naming convention changes and we do not add builds for platforms
that were not supported at the time of release. This only happens in ``solc-bin``.

The ``solc-bin`` repository contains several top-level directories, each representing a single platform.
Each one includes a ``list.json`` file listing the available binaries. For example in
``emscripten-wasm32/list.json`` you will find the following information about version 0.7.4:

.. code-block:: json

    {
      "path": "solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js",
      "version": "0.7.4",
      "build": "commit.3f05b770",
      "longVersion": "0.7.4+commit.3f05b770",
      "keccak256": "0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3",
      "sha256": "0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2",
      "urls": [
        "dweb:/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS"
      ]
    }

This means that:

- You can find the binary in the same directory under the name
  `solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js <https://github.com/argotorg/solc-bin/blob/gh-pages/emscripten-wasm32/solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js>`_.
  Note that the file might be a symlink, and you will need to resolve it yourself if you are not using
  git to download it or your file system does not support symlinks.
- The binary is also mirrored at https://binaries.soliditylang.org/emscripten-wasm32/solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js.
  In this case git is not necessary and symlinks are resolved transparently, either by serving a copy
  of the file or returning a HTTP redirect.
- The file is also available on IPFS at `QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS`_.
  Please, be aware that the order of items in the ``urls`` array is not predetermined or guaranteed and users should not rely on it.
- You can verify the integrity of the binary by comparing its keccak256 hash to
  ``0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3``.  The hash can be computed
  on the command-line using ``keccak256sum`` utility provided by `sha3sum`_ or `keccak256() function
  from ethereumjs-util`_ in JavaScript.
- You can also verify the integrity of the binary by comparing its sha256 hash to
  ``0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2``.

.. warning::

   Due to the strong backwards compatibility requirement the repository contains some legacy elements
   but you should avoid using them when writing new tools:

   - Use ``emscripten-wasm32/`` (with a fallback to ``emscripten-asmjs/``) instead of ``bin/`` if
     you want the best performance. Until version 0.6.1 we only provided asm.js binaries.
     Starting with 0.6.2 we switched to `WebAssembly builds`_ with much better performance. We have
     rebuilt the older versions for wasm but the original asm.js files remain in ``bin/``.
     The new ones had to be placed in a separate directory to avoid name clashes.
   - Use ``emscripten-asmjs/`` and ``emscripten-wasm32/`` instead of ``bin/`` and ``wasm/`` directories
     if you want to be sure whether you are downloading a wasm or an asm.js binary.
   - Use ``list.json`` instead of ``list.js`` and ``list.txt``. The JSON list format contains all
     the information from the old ones and more.

.. warning::
   - The solc-bin.ethereum.org domain is no longer supported. Going forward,
     we recommend any tools which are still using it as the source of Solidity binaries
     to switch to binaries.soliditylang.org.

.. warning::

    The binaries are also available at https://argotorg.github.io/solc-bin/ but this page
    stopped being updated just after the release of version 0.7.2, will not receive any new releases
    or nightly builds for any platform and does not serve the new directory structure, including
    non-emscripten builds.

    If you are using it, please switch to https://binaries.soliditylang.org, which is a drop-in
    replacement. This allows us to make changes to the underlying hosting in a transparent way and
    minimize disruption. Unlike the ``argotorg.github.io`` domain, which we do not have any control
    over, ``binaries.soliditylang.org`` is guaranteed to work and maintain the same URL structure
    in the long-term.

.. _IPFS: https://ipfs.io
.. _solc-bin: https://github.com/argotorg/solc-bin/
.. _Solidity release page on GitHub: https://github.com/argotorg/solidity/releases
.. _sha3sum: https://github.com/maandree/sha3sum
.. _keccak256() function from ethereumjs-util: https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/modules/_hash_.md#const-keccak256
.. _WebAssembly builds: https://emscripten.org/docs/compiling/WebAssembly.html
.. _QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS: https://gateway.ipfs.io/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS

.. _building-from-source:

Building from Source
====================
Prerequisites - All Operating Systems
-------------------------------------

The following are dependencies for all builds of Solidity:

.. Note: This has to be kept in sync with `scripts/ci/install_and_check_minimum_requirements.sh`.

+-----------------------------------+-------------------------------------------------------+
| Software                          | Notes                                                 |
+===================================+=======================================================+
| `CMake`_ (version 3.21.3+)        | Cross-platform build file generator.                  |
+-----------------------------------+-------------------------------------------------------+
| `Boost`_ (version 1.83+)          | C++ libraries.                                        |
+-----------------------------------+-------------------------------------------------------+
| `Git`_                            | Command-line tool for retrieving source code.         |
+-----------------------------------+-------------------------------------------------------+
| `z3`_ (version 4.8.16+, Optional) | For use with SMT checker.                             |
+-----------------------------------+-------------------------------------------------------+

.. _Git: https://git-scm.com/download
.. _Boost: https://www.boost.org
.. _CMake: https://cmake.org/download/
.. _z3: https://github.com/Z3Prover/z3

.. note::
    Solidity versions prior to 0.5.10 can fail to correctly link against Boost versions 1.70+.
    A possible workaround is to temporarily rename ``<Boost install path>/lib/cmake/Boost-1.70.0``
    prior to running the cmake command to configure Solidity.

    Starting from 0.5.10 linking against Boost 1.70+ should work without manual intervention.

.. note::
    The default build configuration requires a specific Z3 version (the latest one at the time the
    code was last updated). Changes introduced between Z3 releases often result in slightly different
    (but still valid) results being returned. Our SMT tests do not account for these differences and
    will likely fail with a different version than the one they were written for. This does not mean
    that a build using a different version is faulty. If you pass ``-DSTRICT_Z3_VERSION=OFF`` option
    to CMake, you can build with any version that satisfies the requirement given in the table above.
    If you do this, however, please remember to pass the ``--no-smt`` option to ``scripts/tests.sh``
    to skip the SMT tests.

.. note::
    By default the build is performed in *pedantic mode*, which enables extra warnings and tells the
    compiler to treat all warnings as errors.
    This forces developers to fix warnings as they arise, so they do not accumulate "to be fixed later".
    If you are only interested in creating a release build and do not intend to modify the source code
    to deal with such warnings, you can pass ``-DPEDANTIC=OFF`` option to CMake to disable this mode.
    Doing this is not recommended for general use but may be necessary when using a toolchain we are
    not testing with or trying to build an older version with newer tools.
    If you encounter such warnings, please consider
    `reporting them <https://github.com/argotorg/solidity/issues/new>`_.

Minimum Compiler Versions
^^^^^^^^^^^^^^^^^^^^^^^^^

The following C++ compilers and their minimum versions can build the Solidity codebase:

.. Note: Minimum versions for GCC and Clang are based on availability in Ubuntu 24.04.

- `GCC <https://gcc.gnu.org>`_, version 13.3+
- `Clang <https://clang.llvm.org/>`_, version 19.1.1+
- `MSVC <https://visualstudio.microsoft.com/vs/>`_, version 2022+

Prerequisites - macOS
---------------------

For macOS builds, ensure that you have the latest version of
`Xcode installed <https://developer.apple.com/xcode/resources/>`_.
This contains the `Clang C++ compiler <https://en.wikipedia.org/wiki/Clang>`_, the
`Xcode IDE <https://en.wikipedia.org/wiki/Xcode>`_ and other Apple development
tools that are required for building C++ applications on OS X.
If you are installing Xcode for the first time, or have just installed a new
version then you will need to agree to the license before you can do
command-line builds:

.. code-block:: bash

    sudo xcodebuild -license accept

Our OS X build script uses `the Homebrew <https://brew.sh>`_
package manager for installing external dependencies.
Here's how to `uninstall Homebrew
<https://docs.brew.sh/FAQ#how-do-i-uninstall-homebrew>`_,
if you ever want to start again from scratch.

Prerequisites - Windows
-----------------------

You need to install the following dependencies for Windows builds of Solidity:

+-----------------------------------+-------------------------------------------------------+
| Software                          | Notes                                                 |
+===================================+=======================================================+
| `Visual Studio 2022 Build Tools`_ | C++ compiler                                          |
+-----------------------------------+-------------------------------------------------------+
| `Visual Studio 2022`_  (Optional) | C++ compiler and dev environment.                     |
+-----------------------------------+-------------------------------------------------------+
| `Boost`_ (version 1.77+)          | C++ libraries.                                        |
+-----------------------------------+-------------------------------------------------------+

If you already have one IDE and only need the compiler and libraries,
you could install Visual Studio 2022 Build Tools.

Visual Studio 2022 provides both IDE and necessary compiler and libraries.
So if you have not got an IDE and prefer to develop Solidity, Visual Studio 2022
may be a choice for you to get everything setup easily.

Here is the list of components that should be installed
in Visual Studio 2022 Build Tools or Visual Studio 2022:

* Visual Studio C++ core features
* VC++ 2022 v143 toolset (x86,x64)
* Windows Universal CRT SDK
* Windows 10 or 11 SDK
* C++/CLI support

.. _Visual Studio 2022: https://visualstudio.microsoft.com/vs/older-downloads/#visual-studio-2022-and-other-products
.. _Visual Studio 2022 Build Tools: https://visualstudio.microsoft.com/vs/older-downloads/#visual-studio-2022-and-other-products

We have a helper script which you can use to install all required external dependencies:

.. code-block:: bat

    scripts\install_deps.ps1

This will install ``boost`` and ``cmake`` to the ``deps`` subdirectory.

Clone the Repository
--------------------

To clone the source code, execute the following command:

.. code-block:: bash

    git clone --recursive https://github.com/argotorg/solidity.git
    cd solidity

If you want to help develop Solidity,
you should fork Solidity and add your personal fork as a second remote:

.. code-block:: bash

    git remote add personal git@github.com:[username]/solidity.git

.. note::
    This method will result in a pre-release build leading to e.g. a flag
    being set in each bytecode produced by such a compiler.
    If you want to re-build a released Solidity compiler, then
    please use the source tarball on the GitHub release page:

    https://github.com/argotorg/solidity/releases/download/v0.X.Y/solidity_0.X.Y.tar.gz

    (not the "Source code" provided by GitHub).

Command-Line Build
------------------

**Be sure to install External Dependencies (see above) before build.**

Solidity project uses CMake to configure the build.
You might want to install `ccache`_ to speed up repeated builds.
CMake will pick it up automatically.
Building Solidity is quite similar on Linux, macOS and other Unices:

.. _ccache: https://ccache.dev/

.. code-block:: bash

    mkdir build
    cd build
    cmake .. && make

or even easier on Linux and macOS, you can run:

.. code-block:: bash

    #note: this will install binaries solc and soltest at usr/local/bin
    ./scripts/build.sh

.. warning::

    BSD builds should work, but are untested by the Solidity team.

And for Windows:

.. code-block:: bash

    mkdir build
    cd build
    cmake -G "Visual Studio 17 2022" ..

In case you want to use the version of boost installed by ``scripts\install_deps.ps1``, you will
additionally need to pass ``-DBoost_ROOT="deps/boost" -DBoost_INCLUDE_DIR="deps/boost/include"`` and ``-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded``
as arguments to the call to ``cmake``.

This should result in the creation of **solidity.sln** in that build directory.
Double-clicking on that file should result in Visual Studio firing up.  We suggest building
**Release** configuration, but all others work.

Alternatively, you can build for Windows on the command-line, like so:

.. code-block:: bash

    cmake --build . --config Release

CMake Options
=============

If you are interested what CMake options are available run ``cmake .. -LH``.

.. _smt_solvers_build:

SMT Solvers
-----------
Solidity can optionally use SMT solvers, namely ``z3``, ``cvc5`` and ``Eldarica``,
but their presence is checked only at runtime, they are not needed for the build to succeed.

.. note::

    The emscripten builds require Z3 and will statically link against it instead.

The Version String in Detail
============================

The Solidity version string contains four parts:

- the version number
- pre-release tag, usually set to ``develop.YYYY.MM.DD``, ``pre.N`` or ``nightly.YYYY.MM.DD``
- commit in the format of ``commit.GITHASH``
- platform, which has an arbitrary number of items, containing details about the platform and compiler

If there are local modifications, the commit will be postfixed with ``.mod``.

These parts are combined as required by SemVer, where the Solidity pre-release tag equals to the SemVer pre-release
and the Solidity commit and platform combined make up the SemVer build metadata.

Examples:

- release: ``0.4.8+commit.60cc1668.Emscripten.clang``
- pre-release: ``0.4.9-pre.3+commit.fb60450bc.Emscripten.clang``
- nightly build: ``0.4.9-nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang``

Important Information About Versioning
======================================

After a release is made, the patch version level is bumped, because we assume that only
patch level changes follow. When changes are merged, the version should be bumped according
to SemVer and the severity of the change. Finally, a release is always made with the version
of the current build, but without the ``prerelease`` specifier.

Example:

1. The 0.4.0 release is made.
2. Nightly builds and preerelases have a version of 0.4.1 from now on.
3. Non-breaking changes are introduced --> no change in version.
4. A breaking change is introduced --> version is bumped to 0.5.0.
5. The 0.5.0 release is made.

This behavior works well with the :ref:`version pragma <version_pragma>`.

---

--- METRICS ---
- Files Extracted: 42
- Estimated Token Budget: ~126239 tokens
- Canonical Reference: https://codewiki.google/github.com/argotorg/solidity
