This document defines the requirements for EEA EthTrust Security Certification, a set of certifications that a smart contract has been reviewed and found not to have a defined set of security vulnerabilities.
This specification is licensed by the Enterprise Ethereum Alliance, Inc. (EEA) under the terms of the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) [[License]] Unless otherwise explicitly authorised in writing by the EEA, you can only use this specification in accordance with those terms. Unless required by applicable law or agreed to in writing, this specification is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the [[License]] for the specific language governing permissions and limitations. This is an editors' draft for the EEA EthTrust Security Levels Specification. Content has been reviewed by the EEA EthTrust Security Levels Working Group, but not the EEA Board. The Working Group expects at time of writing that version 1 of this Specification will be published as an EEA Specification around August 2022. Please send any comments to the EEA at [https://entethalliance.org/contact/](https://entethalliance.org/contact/).

Introduction

This document, the EEA EthTrust Security Levels Specification, defines the requirements for granting EEA EthTrust Certification to a smart contract. No audit can guarantee that a smart contract is secure against **all possible** vulnerabilities, as explained in the . However it can provide a level of assurance, backed not only by the reputation of the auditor issuing the certification, but by the collective reputations of the multiple experts in security from different and in many cases competing organizations, who collaborated within the EEA to ensure this specification defines protections against a real and significant set of known vulnerabilities.

How to read this specification

This section describes how to understand this specification, including the conventions used for examples and requirements, core concepts, references, informative sections, etc.

Typographic Conventions

How to read a requirement

The core of this document is the requirements, that collectively define EEA EthTrust Certification. Requirements have - a Level, - a name, - a URL, and - a statement of what MUST be achieved to meet the requirement. Some requirements at the same level are grouped in a subsection, because they are related to a particular theme or area of potential attacks. Most requirements or groups of requirements are followed by some explanation that can include why the requirement is important, how to test for it, links to Related Requirements, test cases, and links to other useful information.
The following requirement:

[1] No Exact Balance Check:
Tested code MUST NOT make tests that ether balance is equal to (i.e. `==`) a specified amount or the value of a variable.

is a Level 1 requirement, as noted by the "[1]" before its name. Its name is No Unsafe Balance Check. Its URL (for the Editor's draft version of the specification) is https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-1-exact-balance-check. The statement of requirement is that
Tested code MUST NOT make tests that ether balance is equal to (i.e. `==`) a specified amount or the value of a variable.
Following [the requirement](#req-1-exact-balance-check) in the document is some explanation of why this is important, a link to further discussion (which includes test cases) in the "Smart Contract Weakness Classification Registry" [[swcregistry]], and to the description of a general vulnerability in the "Common Weakness Enumeration" [[CWE]] maintained by MITRE.
Overriding Requirements
For some requirements, the statement will include an alternative condition, introduced with the keyword unless, that identifies one or more Overriding Requirements. These are requirements at a higher level, that can be satisfied to achieve conformance if the Tested Code does not meet the lower-level requirement as stated. Where there are more than one Overriding Requirements it is generally necessary to meet all of them to pass the requirement they override. The purpose is to simplify testing for simple cases that do not use features that need to be handled with extra care to avoid introducing vulnerabilities, while ensuring that more complex Tested Code is appropriately checked. In the typical case, of Overriding Requirements for a Level 1 requirement, they apply in relatively unusual cases or where automated systems are generally unable to verify that Tested Code meets the requirement. Further manual verification of the applicable Overriding Requirement(s) can determine that the Tested Code is using a feature appropriately, and therefore passes the Level 1 requirement.
In the following requirement, the Level is "1", the name is "**[1] No Unicode BDO**", the overriding requirement is "**[2] No Misleading Unicode BDO**", and the related requirement "**[3] No Unnecessary Unicode BDO**" is also mentioned.

[1] No Unicode BDO
Tested Code MUST not contain the Unicode direction control characters U+2066, U+2067, U+2068, U+2029, U+202A, U+202B, U+202C, U+202D, or U+202E
unless it meets the overriding requirement [2] No Unnecessary Unicode BDO.

The Level 1 requirement [1] No Unicode BDO is automatically verifiable. Most contracts have no use for Unicode BDO control characters, and will not include them. They will therefore trivially meet the Level 1 requirement.

Tested Code that does use those characters, and meets the Level 2 overriding requirement [**[2] No Unnecessary Unicode BDO**](#req-2-unicode-bdo) conforms to the Level 1 requirement:

[2] No Unnecessary Unicode BDO
At EthTrust level 2 Tested Code MUST not use Unicode direction control characters to produce misleading information.
This is an Overriding requirement for [1] No Unicode BDO.

Why Certify Contracts?

The smart contracts that power decentralized applications on Ethereum have been fraught with security issues, and today there is still no good way to see how secure an address or contract is before initiating a transaction. The Defi space in particular has exploded with a flurry of activity, with individuals and organizations approving transactions in token contracts, swapping tokens, and adding liquidity to pools in quick succession without stopping to think about checking security. For Ethereum to be trusted as a transaction layer by enterprises storing critical data, or financial institutions sending or receiving large amounts of capital, there needs to be a way to easily and quickly signal that a contract has gone through appropriate security audits. Performing this review process early, and particularly before production deployment, is especially important in the context of blockchain development because the costs (in time, effort, funds, and/or credibility) of attempting to update or patch a smart contract after deployment are generally much higher than in other software development contexts. This smart contract security standard is designed to raise the level of confidence in the quality of security audits for smart contracts, and thus to raise trust in the Ethereum ecosystem as a global settlement layer for all types of transactions across all types of industry sectors, for the benefit of Ethereum as a whole. Certification also provides value to the actual or potential users of a smart contract, and others who may be affected by use or abuse of a particular smart contract even if they are not themselves direct users. By requiring that developers go through the certification process, these stakeholders receive a degree of protection through reduced risk and increased confidence of the security of assets held in or supported by the Tested Code, by limiting exposure to certain known weaknesses. This assurance is not complete; for example it relies on the competence and integrity of the auditor issuing the certification. That may be itself incompletely knowable and/or reflected in a professional reputation stemming from later-revealed information about the performance of Tested Code they have audited, especially if it becomes sufficiently high-profile to motivate exploitation of any known weaknesses remaining after the auditor's certification. Finally, smart contract developers and ecosystem stakeholders receive value when others in the ecosystem (including direct competitors) complete the certification process because it means those other contracts are less likely to generate exploitation-related headlines which lead the general public, including business leaders, prospective customers/users, regulators, investors, and others, to perceive use of this technology as a broad category to be insecure and high risk. In some ways, the value of smart contract security certification is analogous to the certification processes applicable to aircraft parts. Most directly, this process helps reduce risks for the part manufacturers and for the integrators who seek to use those parts as components of a larger and more capable complex structure, by providing some assurance of a minimum level of quality. Less directly, these processes significantly reduce (even without entirely eliminating) aviation accidents and crashes, saving lives and earning the trust of both regulators and customers attending to the safety and risk levels of the industry and technology as a whole category. Many of these safety certification processes began as purely voluntary procedures elected internally by a manufacturer and/or specified and required by a consortium of customers representing a motivatingly-large segment of the total market. Having proven their value, some of these certification processes are now required by law for certain applications in order to protect the public (including ground-based bystanders). This is the first version of the specification. The Working Group expects that experience with implementing it will lead to expansion and revisions in a subsequent version. This document does not create an affirmative duty of compliance on any party, though requirements to comply with it may be created by contract negotiations or other processes with prospective customers or investors. We hope the value of completing the certification process, as summarized above, motivates frequent participation and completion of the process, and continued development of the automated tools that can make the evaluation process easier and cheaper. As issues in the specification and challenges in the implementation are discovered, we hope such discoveries will lead to change requests and increased participation in the Enterprise Ethereum Alliance Working Group responsible for developing and maintaining this specification.

Developing Secure Smart Contracts

Security issues that this specification calls for checking are not necessarily obvious to smart contract developers, especially relative newcomers in a quickly growing field. By walking their own code through the certification process, even if no prospective customer requires it, a smart contract developer can discover ways their code is vulnerable to known weaknesses and fix that code prior to deployment. Developers should always try to make their code as secure as possible. Instead of aiming to reach some particular conformance level, a developer should try to ensure that their code implements all the requirements of this specification. This helps ensure they have considered the possible vulnerabilities the specfication addresses, Aside from the obvious reputational benefit, developers will learn from this process, improving their understanding of potential weaknesses and thus their ability to avoid them completely in their own work. For an organization developing and deploying smart contracts, this process reduces the risks to both their credibility, and assets or other capital.
This specification defines a number of requirements. As described in , each requirement has a Level (one, two or three), and a statement of the requirement that Tested Code must meet. In order to achieve EEA EthTrust Certification at a specific Level, the Tested Code MUST meet all the requirements for that level, including all the requirements for lower levels. Some requirements can either be met directly, or by instead meeting one or more Overriding requirements at a higher level, meaning that meeting the higher-level Overriding Requirements defined for that requirement means the requirement is considered to be met. There is also a section on , which contains further recommendations. There is no requirement to test for these; however careful implementation and testing is RECOMMENDED. Note that good implementation of the Recommended Good Practices can enhance security, but in some cases incomplete or low-quality implementation could **reduce** security.

Conformance Claims

For Tested Code to be granted EEA EthTrust Certification means an auditor has provided a valid Conformance Claim, that the Tested Code meets the requirements of the Security Level for which it is certified. A valid Conformance Claim MUST include: - The date on which the certification was issued, in 'YYYY-MM-DD' format - The EVM version(s) (of those listed at [[!EVM-version]]) for which the certification is valid - The version of the EEA EthTrust Security Levels specification for which the contract is certified (this specification is version 1) - A name and a URL for the organisation or software issuing the certification - The Security Level of certification ("1", "2", or "3") - A SHA3-256 hash of the compiled bytecode for each contract in the Tested Code certified, sorted ascending by the hash value interpreted as a number - A SHA3-256 hash of the Solidity source code for each contract in the Tested Code certified, sorted ascending by the hash value interpreted as a number - The compiler options applied for each compilation - The contract metadata generated by the compiler - A list of the requirements which were tested and a statement for each one, noting whether the Tested Code meets the requirement. This MAY include further information. - For conformance claims where certification is granted because the Tested Code met one or more overriding requirement(s) at a higher Level, the conformance claim MUST include the results for the higher Level Overriding Requirement(s), and MAY omit the results for the lower level requirement(s) whose results were thus unnecessary to determine conformance. A valid conformance claim for Level 3 MUST contain a SHA3-256 hash of the documentation provided to meet [**[3] Document Contract Logic**](#req-3-documented) A valid Conformance Claim SHOULD include - a contact address for questions about or challenges to the certification. - descriptions of conformance to the "Recommended Good Practices". A valid Conformance Claim MAY include: - An address where a SHA3-256 hash of the conformance claim has been recorded on an identified network, e.g. Ethereum Mainnet. - An address of the contract deployed on an identified network, e.g. Ethereum Mainnet. Valid values of EVM versions are those listed in the Solidity documentation [[!EVM-version]]. As of June 2022 the two most recent are `london` and `berlin`.

Who can offer EEA EthTrust Certification?

This "Version One" of the specification does not make any restrictions on who can perform an audit and provide EEA EthTrust Certification. There is no certification process defined for auditors or tools. This means that Auditors' claims of performing accurate tests are made by themselves. There is always a possibility of fraud, misrepresentation, or incompetence on the part of any auditor who offers "EEA EthTrust version 1" certification. The Working Group expects its own members, who wrote the specification, to behave to a high standard of integrity and to know the specification well, and notes that there are many others who also do so. The Working Group or EEA MAY seek to develop an auditor certification program for subsequent versions of the EEA EthTrust Security Levels Specification.

Identifying what is certified

An EEA EthTrust evaluation is performed on Tested Code, which means the Solidity source code for a smart contract or several related smart contracts, along with the bytecode generated by compiling the code with specified parameters. If the Tested Code is divided into more than one smart contract, each deployable at a single address, it is referred to as a Set Of Contracts. Where a proxy contract is used to enable upgrading a contract, the proxy contract is generally not eligible for certification. Audits and certification will usually apply to a specific contract (or Set Of Contracts) that are called by the proxy contract, so when they are upgraded it is important to certify the new contract(s).

Security Considerations

Security of information systems is a major field of work. This specification describes testing for security problems in smart contracts. However there is no such thing as perfect security. EEA EthTrust certification states that at least a defined minimum set of checks has been performed on a smart contract. This does not mean there are no security vulnerabilities. From time to time new security vulnerabilities are identified, and many manual auditing prcedures require skill and judgement, meaning there is a possibility that a vulnerability is not noticed. There are also risks inherent in any system of even moderate complexity. Ethereum is based on a model of account holders authorising transactions between accounts. It is very difficult to stop a malicious actor with a privileged key from using that to cause undesirable or otherwise bad outcomes.

Proxy Contracts

Using a Proxy Contract is a common and useful pattern, where a contract is deployed at a fixed address, but merely acts as a proxy, referring all calls to another contract (called the execution contract in this document), that carries out the processing, whose address can be dynamically re-assigned by the proxy contract. This enables upgrading the code, by replacing the execution contract with a new one, for example to fix a security bug. However, this means that the Proxy Contract itself can maliciously redirect a call. In general, EEA EthTrust certification will apply to Execution Contracts, because Proxy Contracts cannot meet the requirements for safe external calls in this specification, and therefore cannot be certified as meeting the requirements of this specification. Nevertheless, it is very important that proxy contracts are well-constructed, and it is a good practice to audit their security properties even if they cannot be certified, as per [**[GP] Meet as many requirements as possible**](#req-R-meet-all-possible).

Oracles

A common feature of Ethereum networks is the use of Oracles; functions that can be called to provide information from outside a blockchain, from weather forecasts to random number generation. This specification contains requirements to check that smart contracts are sufficiently robust to deal appropriately with whatever information is returned (including the possibility of mal-formed data, that can potentially be delibrately crafted as an attack). However, determining whether data produced by an Oracle is actually true is beyond the scope of this specification, and it is possible that an Oracle provides misinformation or even actively produces harmful disinformation.

Signature mechanisms

Some requirements in the document refer to Malleable Signatures. These are signatures created according to a scheme constructed so that, given a message and a signature, it is possible to efficiently compute the signature of a different message - usually one that has been transformed in specific ways. While there are very valuable use cases that such signature schemes allow [[chase]], if not used carefully they can lead to vulnerabilites, which is why this specfication seeks to constrain their use appropriately.

Gas and Gas Prices

Gas Griefing is the deliberate abuse of the Gas mechanism that is used in Ethereum to regulate the consumption of computing power, to cause an unexpected or adverse outcome much in the style of a Denial of Service attack. Because Ethereum is designed with the Gas mechanism as a regulating feature, it is insufficient to simply check that a transaction has enough Gas; it is a security feature that sufficient gas must be provided, so checking for Gas Griefing needs to take into account the goals and business logic that the contract embodies.

In addition, a common feature of Ethereum network upgrades is to change the Gas Price of specific operations. EEA EthTrust certification only applies for the EVM version(s) specified; it is not valid for other versions. Thus it is important to recheck code to ensure its security properties remain the same across network upgrades, or take remedial action.

Timing Attacks

Timing Attacks refer to attacks where an adversary can place their or a victim's transactions earlier or later in a block.

Front-Running is a type of timing attack based on the fact that transactions are visible to the participants in the network before they are added to a block. This can mean that a malicious participant can use the information to submit an alternative transaction, frustrating the aim of the original transaction. For example, in a system designed to attest original authorship, a malicious participant could use the information in a claim of authorship to create a rival claim, and add their claim to a block first.

Mitigation of this kind of attack requires careful consideration of the information that is included in a transaction, including the parameters required by a contract. Other strategies can include the use of Private Transactions [[EEA-clients]] or Layer 2 technology, to establish the ordering of transactions before releasing sensitive information to all nodes participating in a blockchain.

Back-Running is similar to Front-Running, except the attacker places their transactions toward the end of a block.

In Sandwich Attacks, an attacker places a victim's transaction undesirably between two other transactions. For example, an attacker creates a buy and sell transaction before and after a victim's buy transaction, artificially driving the price up for the victim and providing no-risk profit for the attacker.

Generally, any contracts which have their bytecode and transactions unencrypted, may be vulnerable to timing attacks attacks. Mitigation of this kind of attack requires careful consideration of the information that is included in a transaction, including the parameters required by a contract. Other strategies include hash commitment schemes, batch execution and the use of Private Transactions [[EEA-clients]] or Layer 2 technology, to establish the ordering of transactions before releasing sensitive information to all nodes participating in a blockchain.

MEV

Miner Extracted Value (or Maximum Extracted Value, or Extractable Value) refers to the potential for block producers to gain value that is not intentionally given to them, (i.e. steal it) by maliciously reordering or censoring transactions.

Attacks that modify the order of transactions, so that the order of transactions on the blockchain does not correspond with the time they were broadcasted, include Front-Running, Back-Running, and Sandwich Attacks.

As a simple example of an MEV attack, a Smart Contract may promise an award to the first transaction that answers an "easy" question, such as "what is 1+1?". A block producer that knows the answer can drop all transactions that contain the answer, except for their own in the block.

The risks and mitigations for MEV attacks are similar to those for Timing Attacks and depend on smart contract logic.

Source code, pragma, and compilers

The benefits of requiring the source in Solidity include - Having it simplifies a number of tests - Solidity is by a large measure the most common programming language for Ethereum smart contracts - There is substantial security research done that is based on Solidity source code. There are some drawbacks. The most obvious is that some code that is not written in Solidity. Perhaps more important, it means that a deployed contract, that may have been written in Solidity, cannot be tested directly without someone making the source code available. Solidity allows the source code to specify the compiler version used. This specification currently has no requirement for a specific pragma, but it is a good practice to ensure that the pragma refers to a bounded set of versions, where it is known that those versions of the compiler produce identical bytecode from the given source code. Another important limitation is that source code is subject to homoglyph attacks and related attacks, where Unicode Direction Control Characters or characters that look the same, but are different, (e.g. Latin "p" and Cyrillic "р") are used to deceive people reading the code, to disguise malicious behaviour.

Network Upgrades

From time to time the Ethereum community implements a Network Upgrade, sometimes also called a hard fork. This is a change to Ethereum that is backwards-incompatible. Because they typically change the EVM, Ethereum Mainnet Network Upgrades generally correspond to EVM versions. A Network Upgrade can affect more or less any aspect of Ethereum, including changing EVM opcodes or their Gas price, changing how blocks are added, or how rewards are paid, among many possibilities. Because Network Upgrades are not guaranteed to be backwards compatible, a newer EVM version can process bytecode in unanticipated ways. If a Network Upgrade changes the EVM to fix a security problem, it is important to consider that change, and it is a good practice to follow that upgrade. Enterprise Ethereum (as defined in [[EEA-clients]] and [[EEA-chains]]) follows Ethereum Network Upgrades. Because claims of conformance to this specification are only valid for specific EVM versions, a Network Upgrade can mean an updated audit is needed to maintain valid EEA EthTrust Certification for the current Ethereum network. Network Upgrades typically on impact a few features, which can help limit the effort need to audit code after an upgrade: in a reasonable proportion of cases there will be no changes that affect the Tested Code, or a review of the small proportion affected by a Network Upgrade will be sufficient to renew EEA EthTrust Certification.

EEA EthTrust Security Levels

EEA EthTrust Certification is available at three Security Levels. The Security Levels describe minimum requirements for certifications at each Level: 1, 2, 3. These Levels provide successively stronger assurance that a smart contract does not have specific security vulnerabilities.

- [Level 1](#sec-levels-one) is designed so that for most cases Tested Code can be certified by an automated "static analysis" tool. - [Level 2](#sec-levels-two) mandates stricter static analysis, including for requirements where a human auditor is expected to determine what is "sufficent". - [Level 3](#sec-levels-three) provides analysis of the business logic the Tested Code implements, and that the code not only does not exhibit known security vulnerabilities, but also correctly implements what it claims to do. - The optional [Recommended Good Practices](#sec-good-practice-recommendations), correctly implemented, further enhance the Security of smart contracts. It is not necessary to test them to conform to this specification.

This scheme has been compared to the conformance approach used in the "OWASP Application Security Verification Standard" specification family [[ASVS]]. There are some clear differences, largely resulting from the differences between the general applicability ASVS aims to achieve, and this specification's very precise focus on the security of Ethereum smart contracts written in Solidity.

The vulnerabilities addressed by this specification come from a number of sources, including Solidity Security Alerts [[solidity-alerts]], the Smart Contract Weakness Classification [[swcregistry]], TMIO Best practices [[tmio-bp]], Security Advisory Notices, and practical tests that auditors perform.

In principle anyone can submit a smart contract for verification. However submitters should be aware of any restrictions on usage arising from copyright conditions or the like. In addition, meeting certain requirements can be more difficult to demonstrate in a situation of limited control over the development of the smart contract.

Security Level 1

EEA EthTrust Certification at Level 1 is intended to allow an unguided automated tool to analyze most contracts' bytecode and source code, and determine whether they meet the requirements. For some situations that are difficut to verify automatically, but only likely to arise in a small minority of contracts, there are higher-level Overriding Requirements that can be fulfilled to meet a requirement for this level.

To be eligible for EEA EthTrust Level 1 Certification, Tested code MUST fulfil all Level 1 requirements, unless it meets the applicable Overriding Requirement(s) for any Level 1 requirement it does not meet. (Note that this does not imply that it is necessary to meet Related Requirements at a higher level). If there is not an overriding requirement for a Level 1 requirement that the Tested code does not meet, the Tested code is not eligible for EEA EthTrust Certification.

[1] No CREATE2
Tested code MUST NOT contain a CREATE2 instruction.

[1] No tx.origin
Tested code MUST NOT contain a tx.origin instruction
unless it meets the Overriding Requirement [3] Require safe tx.origin

[1] No Conflicting Inheritance
Tested code MUST NOT inherit or declare two functions or variables from multiple contracts with the same name
unless it meets the Overriding Requirement: [2] Document Name Conflicts.

See also the related requirement [2] Compiler Bug SOL-2020-2.

[1] No Hashing Consecutive Variable Length Arguments
Tested Code MUST NOT use abi.encodePacked() with consecutive variable length arguments.

The elements of each variable-length argument to abi.encodePacked() are packed in order prior to hashing. Hash collisions are possible by rearranging the elements between consecutive, variable length arguments while maintaining that their concatenated order is the same.

Text and homoglyphs

Techniques such as substituting characters from different alphabets (e.g. Latin "a" and Cyrillic "а" are not the same), or changing the apparent order of characters through the use of invisible Unicode direction control characters can help to mask malicious code, even in viewing source code, to deceive human auditors. Many of these attacks are broadly known as homoglyph attacks. Several approaches to successfully exploiting this issue are described in [[Ivanov]]. The requirements in this section are related to the security advisory [[CVE-2021-42574]] and [[CWE-94]], "Improper Control of Generation of Code", also called "Code Injection". More information on Unicode direction control characters is available in the W3C note [How to use Unicode controls for bidi text](https://www.w3.org/International/questions/qa-bidi-unicode-controls) [[unicode-bdo]].

[1] No Unicode BDO
Tested code MUST NOT contain the Unicode Direction Control Characters U+2066, U+2067, U+2068, U+2029, U+202A, U+202B, U+202C, U+202D, or U+202E
unless it meets the Overriding Requirement [2] No Unnecessary Unicode Controls.

[1] No Self-destruct
Tested code MUST NOT contain the selfdestruct() instruction or its now-deprecated alias suicide()
unless it meets the Overriding Requirements [2] Safe Self-destruct
and
[2] Document Special Code Use.

[1] No assembly
Tested Code MUST NOT contain the assembly() instruction
unless it meets all the Overriding Requirements: [2] Safe Use of assembly,
[2] Document Special Code Use
, [2] Compiler Bug SOL-2022-5 in `assembly`
, [2] Compiler Bug SOL-2022-4,
[2] Compiler Bug SOL-2021-3, and [2] Compiler Bug SOL-2019-2 in `assembly`.

External Calls

One of the most commonly cited vulnerabilities in Ethereum Smart Contracts is reentrancy attacks, where malicious contracts can call into a contract that called them, before the originating contract's function call has completed. Code that relies on other code introduces multiple possible attack vectors, whether through malicious manipulation of the external references themselves or of the code called, or simply due to failure to adequately manage the possible outcomes of an external call.

See also the Related Requirements: [2] Safe External Calls, [2] Handle External Call Returns, and [3] Safer External Calls.

[1] Check External Calls Return:
Tested Code that makes external calls using low-level functions such as call, delegatecall, or staticcall MUST check the returned value from each usage to determine whether the call failed.

Normally exceptions in subcalls "bubble up", unless they are handled in a try/catch. However low-level calls like call, delegatecall, or staticcall behave differently. They return a boolean indicating whether the call completed successfully. Not accounting for possible failures from these calls may lead to unexpected behavior in the caller contract. See also [SWC-104](https://swcregistry.io/docs/SWC-104) in [[swcregistry]], error handling documentation in [[error-handling]], unchecked return value as described in [[CWE-252]], and the Related Requirements: [1] Use Check-Effects-Interaction, [2] Handle External Call Returns, [3] Safer External Calls

[1] Use Check-Effects-Interaction
Tested code that makes external calls MUST follow the Checks-Effects-Interactions pattern [[!c-e-i]] to protect against reentrancy attacks unless it meets the Overriding Requirements [2] Safe external calls
and [2] Document Special Code Use
or it meets the Overriding Requirements [3] Safer External Calls AND [3] Document Contract Logic.

[1] No delegatecall
Tested Code MUST NOT contain the delegatecall instruction
unless it meets the Overriding Requirement: [2] Safe External Calls.
or it meets the Overriding Requirements [3] Safer External Calls AND [3] Document Contract Logic.

[1] No Exact Balance Check
Tested code MUST NOT test that the balance of an account is exactly equal to (i.e. `==`) a specified amount or the value of a variable.

Testing the balance of an account as a basis for some action has risks associated with unexpected receipt of ether or another token, including tokens deliberately transfered to cause such tests to fail as an attack. See also related requirement [3] Protect against Miner Extractable Value (MEV):, [SWC-132](https://swcregistry.io/docs/SWC-132) in [[swcregistry]], and improper locking as described in [[CWE-667]].

Improved Compilers

The requirements in this section can be met by using a sufficiently recent version of the Solidity compiler. Otherwise, there are Overriding Requirements to perform the same testing that the up-to-date compiler checks: - From 0.8.0 the compiler checks for arithmetic causing overflows and underflows. - From 0.5.0 storage must be declared explicitly as `storage` or `memory`. - From 0.4.22 code does not compile if it uses constructors that are not explicitly declared as `constructor`.

[1] No Overflow/Underflow Tested code MUST NOT use a version of Solidity older than 0.8.0
unless it meets the Overriding Requirements: [2] Safe Overflow/Underflow and [2] Document Special Code Use.

[1] Explicit Storage Tested code MUST NOT use a version of Solidity older than 0.5.0
unless it meets the Overriding Requirement: [2] Declare storage Explicitly.

[1] Explicit Constructors Tested code MUST NOT use a version of Solidity older than 0.4.22
unless it meets the Overriding Requirement: [2] Declare Constructors Explicitly.

Compiler Bugs

There are a number of known security bugs in previous versions of the Solidity compiler. The requirements in this subsection ensure that Tested Code does not trigger these bugs. The name of the requirement includes the `uid` first recorded for the bug in [[!solidity-bugs-json]], as a key that can be used to find more information about the bug. [[solidity-bugs]] describes the conventions used for the JSON-formatted list of bugs. The requirements in this subsection are ordered according to the latest compiler versions that are vulnerable, to slightly simplify assessment given the compiler version in use. Implementing the Good Practice of the related requirement [**[GP] Use Latest Compiler**](#req-R-use-latest-compiler) means that Tested Code passes all requirements in this subsection. Some compiler-related bugs are in the as level 2 requirements, either because they Overriding Requirements for requirements in this subsection, or because they are Overriding Requirements for other Level 1 requirements that already ensure that the bug cannot be triggered. Some bugs were introduced in known versions, while others are assumed to have existed in all versions before they were fixed.

[1] Compiler Bug SOL-2022-5 with .push()
Tested code that copies `bytes` arrays from calldata or memory whose size is not a multiple of 32 bytes, and has an empty `.push()` instruction that writes to the resulting array, MUST NOT use a version of Solidity older than 0.8.15.

Until 0.8.15 copying memory or calldata whose length is not a multiple of 32 bytes could expose data beyond the data copied, which could be observable using `assembly`. See also the [15 June 2022 security alert](https://blog.soliditylang.org/2022/06/15/dirty-bytes-array-to-storage-bug/) and the related requirement [2] Compiler Bug SOL-2022-5 in `assembly`.

[1] Compiler Bug SOL-2022-3
Tested code that uses `memory` and `calldata` pointers for the same function, and changes the data location of a function during inheritance, and performs an internal call at a location that is only aware of the original function signature from the base contract MUST NOT use a version of Solidity between 0.6.9 and 0.8.13 (inclusive).

Compilers from 0.6.9 until it was fixed in 0.8.13 had a bug that incorrectly allowed internal or public calls to use a simpification only valid for external calls, treating `memory` and `calldata` as equivalent pointers. See also the 17 May 2022 [security alert](https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/).

[1] Compiler Bug SOL-2022-2
Tested code that uses passes a nested array to an external function, or to abi.encode(), or uses it in an event MUST NOT use a version of Solidity between 0.6.9 and 0.8.13 (inclusive).

Compilers from 0.5.8 until it was fixed in 0.8.13 had a bug that meant a single-pass encoding and decoding of a nested array could read data beyond the `calldatasize()`. See also the 17 May 2022 [security alert](https://blog.soliditylang.org/2022/05/17/calldata-reencode-size-check-bug/).

[1] Compiler Bug SOL-2022-1
Tested code that uses Number literals for a fixed `bytes` type shorter than 32 bytes, or String literals for any fixed bytes type, and passes such literals to an abi.encodeCall() as the first parameter, MUST NOT use a versions 0.8.11 nor 0.8.12 of Solidity.

Compilers from 0.8.11 and 0.8.12 had a bug that meant literal parameters were incorrectly encoded by `abi.encodeCall()` in certain circumstances. See also the 17 May 2022 [security alert](https://blog.soliditylang.org/2022/03/16/encodecall-bug/).

[1] Compiler Bug SOL-2021-2
Tested code that uses abi.decode() on byte arrays as `memory`, MUST NOT use the ABIEncoderV2 with a version of Solidity between 0.4.16 and 0.8.3 (inclusive).

Compilers 0.4.16 introduced a bug, fixed in 0.8.4, that meant the ABIEncoderV2 incorrectly validated pointers when reading `memory` byte arrays, which could result in reading data beyond the array area due to an overflow error in calcuating pointers. See also the 21 April 2021 [security alert](https://blog.soliditylang.org/2021/04/21/decoding-from-memory-bug/).

[1] Compiler Bug SOL-2021-1
Tested code that has 2 or more occurrences of an instruction keccak(mem,length) where the values of mem are equal, and the values of length are unequal and are not multiples of 32, MUST NOT use the bytecode optimzier with a version of Solidity older than 0.8.3.

Compilers before 0.8.3 had an optimizer bug that meant keccak hashes, calculated for the same content but different lengths that were not multiples of 32 bytes incorrectly used the first value from cache instead of recalculating. See also the 23 March 2021 [security alert](https://blog.soliditylang.org/2021/03/23/keccak-optimizer-bug/).

[1] Compiler Bug SOL-2020-11-push
Tested code that copies an empty byte array to storage, and subsequently increases the size of the array using push() MUST NOT a use version of Solidity older than 0.7.4.

Compilers before 0.7.4 had a bug that meant data would be packed after an empty array, and if the length of the array were extended `push()` prior to 0.7.4, that data would be readable from the array. See also the 19 October 2020 [security alert](https://blog.soliditylang.org/2020/10/19/empty-byte-array-copy-bug/).

[1] Compiler Bug SOL-2020-10
Tested code that copies an array of types shorter than 16 bytes to a longer array MUST NOT a use version of Solidity older than 0.7.3.

Compilers before 0.7.3 had a bug that meant when array data for types shorter than 16 bytes are assigned to a longer array, the extra values in that longer array are not correctly reset to zero. See also the 7 October 2020 [security alert](https://blog.soliditylang.org/2020/10/07/solidity-dynamic-array-cleanup-bug).

[1] Compiler Bug SOL-2020-9
Tested code that defines free functions MUST NOT use version 0.7.1 of Solidity.

The 0.7.1 compiler did not correctly distinguish overlapping free function declarations, meaning that the wrong function could be called.

[1] Compiler Bug SOL-2020-8
Tested code that calls internal library functions with calldata parameters called via using for MUST NOT use version 0.6.9 of Solidity.

The 0.6.9 compiler incorrectly copied calldata parameters passed to internal library functions passed with `using for` as if they were calling to external library functions, leading to stack corruption and an incorrect jump destination.

[1] Compiler Bug SOL-2020-6
Tested code that accesses an array slice using an expression for the starting index that can evaluate to a value other than zero MUST NOT use the ABIEncoderV2 with a version of Solidity between 0.6.0 and 0.6.7 (inclusive).

Compiler version 0.6.0 introduced a bug fixed in 0.6.8 that incorrectly calculated index offsets for the start of array slices, used in dynamic `calldata` types, when using the ABIEncoderV2.

[1] Compiler Bug SOL-2020-7
Tested code that passes a string literal containing two consecutive backslash ("\") characters to an encoding function or an external call MUST NOT use the ABIEncoderV2 with a version of Solidity between 0.5.14 and 0.6.7 (inclusive).

Compiler version 0.5.14 introduced a bug fixed in 0.6.8 that incorrectly encoded consecutive backslash characters in string literals when passing them to an external function, or an enncoding function, when using the ABIEncoderV2.

[1] Compiler Bug SOL-2020-5
Tested code that defines a contract that does not include a constructor but has a base contract that defines a constructor not defined as `payable` MUST NOT use a version of Solidity between 0.4.5 and 0.6.7 (inclusive), unless it meets the Overriding Requirement [2] Check Constructor Payment.

Solidity 0.4.5 introduced a check intended to result in contract creation reverting if value is passed to a constructor that is not explicitly marked as `payable`. But where the constructor was not defined in a contract but inerited from a base, this check did not function properly until version 0.6.8 meaning the creation would not revert as expected.

[1] Compiler Bug SOL-2020-4
Tested code that makes assignments that involve nested tuples, or assignments to tuples that include a pointer to an external function or a reference to a dynamically sized `calldata` array MUST NOT use a version of Solidity older than 0.6.4.

Solidity 0.1.6 introduced a bug fixed in 0.6.5 that meant tuple assignments involving nested tuples, pointers to external functions, or references to dynamically sized `calldata` arrays were corrupted due to incorrectly calculating the number of stack slots.

[1] Compiler Bug SOL-2020-3
Tested code that declares arrays of size larger than 2^256-1 MUST NOT use a version of Solidity older than 0.6.5.

Version 0.2.0 of the compiler introduced a bug, fixed in version 0.6.5, that meant no overflow check was performed for the creation of very large arrays, meaning in some cases an overflow error would occur that would use result in consuming all gas in a transaction due to the memory handling error introduced in compiling the contract.

[1] Compiler Bug SOL-2020-1
Tested code that declares variables inside a `for` loop that contains a `break` or `continue` statement MUST NOT use the Yul Optimizer with version 0.6.0 nor a version of Solidity between 0.5.8 and 0.5.15 (inclusive).

A bug in the Yul Optimiser in versions from 0.5.8 to 0.5.15 and in version 0.6.0 meant assignments for variables declared inside a `for` loop that contained a `break` or `continue` statement could be removed.

[1] Compiler Bug SOL-2020-11-length
Tested code that copies an empty byte array to storage, and subsequently increases the size of the array by assigning the length attribute MUST NOT use a version of Solidity older than 0.6.0.

Compilers before 0.6.0 had a bug that meant data would be packed after an empty array, and if the length of the array were then extended by assigning the `length` attribute that data would be readable from the array. See also the 19 October 2020 [security alert](https://blog.soliditylang.org/2020/10/19/empty-byte-array-copy-bug/).

[1] Compiler Bug SOL-2019-10
Tested code MUST NOT use the combination of all of

  • the ABIEncoderV2
  • the Optimizer
  • the yulOptimizer
  • version 0.5.14 of Solidity.
A bug in version 0.5.14 that required multiple compiler options to trigger could result in data corruption in storage.

[1] Compiler Bugs SOL-2019-3,6,7,9
Tested code that uses `struct` or arrays MUST NOT use the ABIEncoderV2 option with a version of Solidity between 0.4.16 and 0.5.10 (inclusive).

Compiler 0.5.6 introduced bug SOL-2019-9 fixed in 0.5.11 that meant reading a `struct` through `calldata` which had dyamically encoded members that were statically sized resulted in corrupted data. Bugs SOL-2019-6 and SOL-2019-7 introduced in compiler 0.4.16 and fixed in compiler 0.5.9 and 0.5.10 respectively meant that data encoded in or read from a `struct` could be corrupted. Bug SOL-2019-3 from 0.4.19 to 0.4.25 and from 0.5.0 to 0.5.7 could corrupt data, both in the `struct` and other encoded data, when encoding a `struct`. All of these bugs were triggered by using the ABIEncoderV2. See also the 26 March 2019 [security alert](https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/), and the 25 June 2019 [security alert](https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/).

[1] Compiler Bug SOL-2019-8
Tested code that assigns an array of signed integers to an array of a different type MUST NOT use a version of Solidity between 0.4.7 and 0.5.9 (inclusive).

Compiler 0.4.7 introduced a bug fixed in 0.5.10 that meant assigning an array of signed integers to another array of different type corrupted negative values. See also the 25 June 2019 [security alert](https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/).

[1] Compiler Bug SOL-2019-5
Tested code that calls an uninitialized internal function pointer in the constructor MUST NOT use a version between 0.4.5 and 0.4.25 (inclusive) nor a version between 0.5.0 and 0.5.7 (inclusive) of Solidity.

A bug in versions 0.4.5 to 0.4.25 and one in versions 0.5.0 until fixed in 0.5.8 meant calls to unitialized function pointers in constructors did not revert as expected and as they do in deployed code.

[1] Compiler Bug SOL-2019-4
Tested code that uses events containing contract types, in libraries, MUST NOT use a version of Solitidy between 0.5.0 and 0.5.7.

Version 0.5.0 introduced a bug fixed in 0.5.8 that meant an incorrect hash is logged if library events contain contract types.

[1] Compiler Bug SOL-2019-2
Tested code that makes index access to bytesNN types with a second parameter (not the index) whose compile-time value evaluates to 31 MUST NOT use the Optimizer with versions 0.5.5 nor 0.5.6 of Solitidy.

Version 0.5.5 introduced an Optimizer bug fixed in 0.5.7 where a second parameter value of "31" for a `byte` opcode resulted in unexpected values. See also the related requirement [**[2] Compiler Bug SOL-2019-2 in `assembly`**](#req-2-compiler-SOL-2019-2-assembly).

[1] Compiler Bug SOL-2019-1
Tested code that nests bitwise shifts to produce a total shift of more than 256 bits AND compiles for the Constantinople or later EVM version MUST NOT use the Optimizer option with version 0.5.5 of Solidity.

Compiler 0.5.5 introduced a bug fixed in 0.5.6 that meant nested bitwise shifts could be incorrectly optimized. See also the 26 March 2019 [security security](https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/).

[1] Compiler Bug SOL-2018-4
Tested code that has a match for the regexp `[^/]\\*\\* *[^/0-9 ]` MUST NOT use a version of Solidity older than 0.4.25.

Compilers before 0.4.25 had a bug that meant exponents calculated using `**` with a type that is shorter than 256 bits, not shorter than the type of the base, and containing dirty higher order bits could produce an incorrect result. See also the 13 September 2018 [security alert](https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/).

[1] Compiler Bug SOL-2018-3
Tested code that uses a struct in events MUST NOT use a version of Solidity between 0.4.17 and 0.4.24 (inclusive).

Compilers from 0.4.17 until it was fixed in 0.4.25 had a bug that meant when events used `struct`s, the address of the `struct` was logged instead of the data. See also the 13 September 2018 [security alert](https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/).

[1] Compiler Bug SOL-2018-2
Tested code that calls a function matching the regexp `returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]` MUST NOT use a version of Solidity older than 0.4.22.

Compilers between 0.1.4 and 0.4.21 incorrectly interpreted array values as memory pointers when a function that returns a fixed-size multidimensional array is called. See also the 13 September 2018 [security alert](https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/).

[1] Compiler Bug SOL-2018-1
Tested code that both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract), which are not exactly the same MUST NOT use version 0.4.22 of Solidity.

Compilers 0.4.22 had a bug that means it is unclear which constructor function is used. It is unnecessary to use the old-style constructor in this case, and not using it avoids triggering the bug. See also the related requirements [**[1] Explicit Constructors **](#req-1-explicit-constructors) and [**[2] Declare Constructors Explicitly **](#req-2-explicit-constructors).

[1] Compiler Bug SOL-2017-5
Tested code that has a payable function whose name consists only of any number of zeros ("0"), and does not have a fallback function, MUST NOT use a version of Solidity older than 0.4.18.

Compilers before 0.4.18 had a bug that meant such a function would be called instead of a fallback function if Ether is sent without data.

[1] Compiler Bug SOL-2017-4
Tested code that uses the delegatecall() instruction MUST NOT use a version of Solidity older than 0.4.15.

Compilers from 0.3.0 to 0.4.14 had a bug that meant if `delegateCall()` returned a value that started with 32 bytes of zeros, it would be read as `false` instead of `true`.

[1] Compiler Bug SOL-2017-3
Tested code that uses the ecrecover() pre-compile MUST NOT use a version of Solidity older than 0.4.14
unless it meets the Overriding Requirement [2] Validate ecrecover() Input.

[1] Compiler Bug SOL-2017-2
Tested code with functions that accept 2 or more parameters MUST NOT use a version of Solidity older than 0.4.12.

Compilers before 0.4.12 had a bug that meant when the empty string `""` was passed as a parameter value, the encoder simply ignored it, assigning subsequent arguments to the wrong parameter and corrupting the function call.

[1] Compiler Bug SOL-2017-1
Tested code that contains any number that either begins with `0xff` and ends with `00`, or begins with `0x00` and ends with `ff`, twice, OR uses such a number in the constructor, MUST NOT use the Optimizer with a version of Solidity older than 0.4.11.

The Optimizer for Compilers before 0.4.11 had a bug that meant certain numbers were corrupted by an attempt to optimise gas or constructor size. See also the 3 May 2017 [security alert](https://blog.soliditylang.org/2017/05/03/solidity-optimizer-bug/).

[1] Compiler Bug SOL-2016-11
Tested code that uses a version older than 0.4.7 of Solidity MUST NOT call the Identity Contract UNLESS it meets the overriding requirement [2] Compiler Bug Check Identity Calls.

Versions before 0.4.7 of the compiler had a specific bug that caused data corruption at jump destinations.

[1] Compiler Bug SOL-2016-10
Tested code MUST NOT use the Optimizer option with version 0.4.5 of Solidity.

Version 0.4.5 of the compiler had an Optimizer bug that caused data corruption at jump destinations. See also the related requirement [**[1] Compiler Bug SOL-2016-4**](#req-1-compiler-SOL-2016-4).

[1] Compiler Bug SOL-2016-9
Tested code that use variables of a type shorter than 17 bytes MUST NOT use a version of Solidity older than 0.4.4.

Compilers between 0.1.6 and 0.4.4 packed shorter data types in a way that potentially allowed the overwriting of variables. See also SWC-124 [[swcregistry]].

[1] Compiler Bug SOL-2016-8
Tested code that uses the sha3() instruction MUST NOT use the Optimizer option with a version of Solidity older than 0.4.3.

Compilers before 0.4.3 had a bug in the Optimizer that incorrectly cached some `sha3()` hashes. Note that the `sha3()` instruction is disallowed since version 0.5.0, replaced by the `keccak256()` instruction.

[1] Compiler Bug SOL-2016-7
Tested code that uses delegatecall() from a function that can receive Ether to call a Library Function MUST NOT use versions 0.4.0 or 0.4.1 of Solidity.

Compilers 0.4.0 and 0.4.1 had a bug that incorrectly rejected Library Function calls made with `delegatecall()` from a function that had received Ether, interpreting it as an attempt to send Ether to the Library Function.

[1] Compiler Bug SOL-2016-6
Tested code that sends Ether MUST NOT use a version of Solidity older than 0.4.0 UNLESS it meets the overriding requirement [2] Compiler Bug No Zero Ether Send.

Versions before 0.4.0 of the compiler had a specific bug that meant transactions that send Ether but with a zero value fail to provide gas, causing an exception.

[1] Compiler Bug SOL-2016-5
Tested code that creates a dynamically sized array with a `length` that can be zero MUST NOT use a version of Solidity older than 0.3.6.

Compilers before 0.3.6 had a bug that meant dynamically created arrays with a zero length created code that did not terminate, and consumed all gas.

[1] Compiler Bug SOL-2016-4
Tested code that creates a `Jump Destination` opcode MUST NOT use the Optimizer with versions of Solidity older than 0.3.6.

For compilers before 0.3.6 the Optimizer had a bug that meant data corruption could occur due to incorrectly computing state at jump destinations.

[1] Compiler Bug SOL-2016-3
Tested code that compares the values of data of type BytesNN MUST NOT use a version of Solidity older than 0.3.3.

[1] Compiler Bug SOL-2016-2
Tested code that uses arrays, with data types whose size is less than 32 bytes MUST NOT use a version of Solidity older than 0.3.1.

[1] No Ancient Compilers
Tested code MUST NOT use a version of Solidity older than 0.3.

Compiler bugs are not tracked for compiler versions older than 0.3. There is therefore a risk that unknown bugs create unexpected problems. See also "SOL-2016-1" in [[!solidity-bugs-json]].

Security Level 2

EEA EthTrust Certification at Level 2 means that the Tested Code has been carefully reviewed by a human auditor or audit team, doing a "static analysis", and important security issues have been addressed to their satisfaction.

This level includes a number of Overriding Requirements for cases when Tested Code does not meet a Level 1 requirement directly, e.g. because it uses an uncommon feature that introduces higher risk. Passing the relevant Overriding Requirement tests that the feature has been implemented sufficiently well to satisfy the auditor that it does not expose the Tested Code to the known risks identified in this Security Level.

[2] Pass Level 1
To be eligible for EEA EthTrust Level 2 certification, Tested code MUST meet the requirements for .

Level 2 Compiler Bugs and Overriding Requirements

Some solidity compiler bugs have Overriding Requirements at Level 2.

[2] Compiler Bug SOL-2022-5 in `assembly`
Tested code that copies `bytes` arrays from calldata or memory whose size is not a multiple of 32 bytes, and has an `assembly` instruction that reads that data without explicitly matching the length that was copied, MUST NOT use a version of Solidity older than 0.8.15.

This is part of the set of Overriding Requirements for [1] No assembly.

Until 0.8.15 copying memory or calldata whose length is not a multiple of 32 bytes could expose data beyond the data copied, which could be observable using `assembly`. See also the [15 June 2022 security alert](https://blog.soliditylang.org/2022/06/15/dirty-bytes-array-to-storage-bug/) and related requirements [1] Compiler Bug SOL-2022-3 with `.push()`, [2] Safe Use of assembly, [2] Document Special Code Use, [2] Compiler Bug SOL-2022-4, [2] Compiler Bug SOL-2021-3, and [2] Compiler Bug SOL-2019-2 in `assembly`.

[2] Compiler Bug SOL-2022-4
Tested code that has at least two `assembly` instructions, such that one writes to memory e.g. by storing a value in a variable, but does not access that memory again, and code in a another `assembly` instruction refers to that memory, MUST NOT use the yulOptimizer with versions 0.8.13 or 0.8.14 of Solidity.

This is part of the set of Overriding Requirements for [1] No assembly.

Version 0.8.13 introduced a yulOptimizer bug fixed 0.8.15 in where memory created in an `assembly` instruction but only read in a different `assembly` instruction was discarded. See also the [17 June 2022 security alert](https://blog.soliditylang.org/2022/06/15/inline-assembly-memory-side-effects-bug/) and related requirements [2] Safe Use of assembly, [2] Document Special Code Use, [2] Compiler Bug SOL-2022-5 in `assembly`, [2] Compiler Bug SOL-2021-3, and [2] Compiler Bug SOL-2019-2 in `assembly`.

[2] Compiler Bug SOL-2021-3
Tested code that reads an `immutable` signed integer of a `type` shorter than 256 bits within an `assembly` instruction MUST NOT use a version of Solidity between 0.6.5 and 0.8.8 (inclusive).

This is part of the set of Overriding Requirements for [1] No assembly.

Compiler 0.6.8 introduced a bug, fixed in 0.8.9, that meant immutable signed integer types shorter than 256 bytes could be read incorrectly in inline `assembly` instructions. See also the [29 September 2021 security alert](https://blog.soliditylang.org/2021/09/29/signed-immutables-bug/), and the related requirements [2] Safe Use of assembly, [2] Document Special Code Use, [2] Compiler Bug SOL-2022-5 in `assembly`, [2] Compiler Bug SOL-2022-4, and [2] Compiler Bug SOL-2019-2 in `assembly`.

[2] Compiler Bug Check Constructor Payment
Tested code that enables a payment to a constructor function defined in a base contract but used by default in another contract without an explicit constructor, and that is not explicity marked `payable`, MUST NOT use a version of Solidity between 0.4.5 and 0.6.7 (inclusive).

This is an Overriding Requirement for [1] Compiler Bug SOL-2020-5.

[2] Compiler Bug SOL-2020-2
Tested code that declares multiple functions with the same name MUST NOT use a version of Solidity older than 0.5.17.

Compilers between 0.3.0 and 0.5.17 had a bug that allowed private method declarations to be overridden by declaring another function of the same name. See also the related requirements [1] No Conflicting Inheritance and [2] Document Name Conflicts.

[2] Compiler Bug SOL-2019-2 in `assembly`
Tested code that uses the Optimizer with a version 0.5.5 nor 0.5.6 of Solitidy MUST NOT contain inline `assembly` that uses the `byte` instruction with a second parameter whose compile-time value evaluates to 31.

This is part of the set of Overriding Requirements for [1] No assembly.

Version 0.5.5 intrduced a bug fixed in 0.5.7 where a second parameter value of "31" for a `byte` opcode resulted in unexpected values. See also the related requirements [**[1] Compiler Bug SOL-2019-2](#req-1-compiler-SOL-2019-2), [2] Safe Use of assembly, [2] Document Special Code Use, and [2] Compiler Bug SOL-2021-3.

[2] Compiler Bug Check Identity Calls
In Tested code that uses a version of Solidity older than 0.4.7, calls to the Identity Contract MUST explicitly check the return value.

This is an Overriding Requirement for [1] Compiler Bug SOL-2016-11.

[2] Validate ecrecover() input
Tested code that uses the ecrecover() pre-compile in a version of Solidity older than 0.4.14 MUST ensure that input is well-formed before making the call.

This is an Overriding Requirement for [1] Compiler Bug SOL-2017-3.

Prior to Solidity 0.4.14, bad input to `ecrecover()` could cause it to fail and produce corrupted data, while appearing to succeed.

[2] Compiler Bug No Zero Ether Send
Tested code that uses a version of Solidity older than 0.4.0, MUST NOT make Ether transfers that can send a value of zero.

This is an Overriding Requirement for [1] Compiler Bug SOL-2016-6.

Text and homoglyph attacks

Level 2 requirements permit the use of Unicode direction control characters in text strings, subject to analysis of whether they are necessary. Likewise, in the rare case there is a valid use of characters from multiple Unicode blocks (see [[unicode-blocks]]) in a variable name or label (most likely to be mixing two languages in a name), requirements at this level allow them to pass EEA EthTrust certification so long as they do not mislead or confuse. However, this level requires checking for homoglyph attacks including those within a single character set, such as the use of "í" in place of "i" or "ì", "ت" for "ث", or "1" for "l", and when a reviewer judges that the result is misleading or confusing, the relevant code does not meet the Level 2 requirements.

[2] No Unnecessary Unicode Controls
Tested code MUST NOT use Unicode direction control characters unless they are necessary to render text appropriately, and the resulting text does not mislead readers.
This is an Overriding Requirement for [1] No Unicode BDO.

[2] No Homoglyph-style Attack
Tested code MUST not use homoglyphs, Unicode control characters, combining characters, or characters from multiple Unicode blocks if the impact is misleading.

See also the Related Requirement: [1] No Unicode BDO.

[2] Document Special Code Use
Tested Code MUST document the need for any instances of:

  • selfdestruct() or its outdated alias suicide(),
  • assembly,
  • external calls,
  • use of block.number or block.timestamp,
  • Use of oracles and pseudo-randomness, and
  • code that can cause an overflow or underflow,

and MUST describe how the Tested Code protects against misuse or errors in these cases, and the documentation MUST be available to anyone who can call the Tested Code.

Related requirements: [3] Document Contract Logic, [3] Safer External Calls, [2] Safe Use of assembly, [2] Compiler Bug SOL-2022-5 in `assembly`, [2] Compiler Bug SOL-2022-4, [2] Compiler Bug SOL-2021-3, and [2] Compiler Bug SOL-2019-2 in `assembly`.

There are legitimate uses for all of these coding patterns, but they are also potential causes of security vulnerabilities. Requirements at level 2 therefore require testing that ensures the use of these patterns is explained and justified, and that they are used in a manner that does not introduce known vulnerabilities.

[2] Safe Self-destruct
Tested code that contains the selfdestruct() or suicide() MUST ensure that only authorised parties can call the method. The calls MUST be protected in a way that is fully compatible with the claims of the contract author.
This is an Overriding Requirement for [1] No Self-destruct.

[2] Safe External Calls
For Tested code that does not meet the requirement [1] Use Check-Effects-Interaction:

  • all contracts called MUST be within the Tested code, and
  • all contracts called MUST be controlled by the same entity, and
  • protections against reentrancy attacks must be fully compatible with the claims of the contract author

unless it meets the Overriding Requirements [3] Safer External Calls AND [3] Document Contract Logic.
This is an Overriding Requirement for [1] Use Check-Effects-Interaction.

[2] Safe Use of assembly
Tested Code MUST NOT use the assembly instruction to change a variable unless the code cannot:

  • create storage pointer collisions, nor
  • allow function type variable assignment,

as anticipated in SWC-124 or SWC-127 [[swcregistry]].

This is part of a set of Overriding Requirement for [1] No assembly.

See also the related requirements [2] Document Special Code Use, [2] Compiler Bug SOL-2022-5 in `assembly`, [2] Compiler Bug SOL-2022-4, [2] Compiler Bug SOL-2021-3, and [2] Compiler Bug SOL-2019-2 in `assembly`.

[2] Declare storage Explicitly Tested code that uses a version of Solidity older than 0.5.0 MUST explicitly declare storage or memory for storage objects, and must justify the need for any storage item.
This is an Overriding Requirement for [1] Explicit Storage. Solidity's default way of providing uninitialised storage can be and has been exploited [[storage-honeypots]], because it can enable access to an unnitiatilized pointer [[CWE-824]]. This was addressed by checking that storage is explicitly declared, from version 0.5.0, but for older compilers it is important to test for this exploit.

[2] No Overflow/Underflow
Tested code MUST NOT contain calculations that can overflow or underflow unless

  • there is a demonstrated need (e.g. for use in a modulo operation) and
  • there are guards around any calculations, if necessary, to ensure behavior consistent with the claims of the contract author.

This is an Overriding Requirement for [1] No Overflow/Underflow.

[2] Declare Explicit Constructors Tested code that uses a version of Solidity older than 0.4.22 MUST declare constructor methods explicitly.
This is an Overriding Requirement for [1] Explicit Constructors.

[2] Document Name Conflicts
Tested code MUST clearly document the order of inheritance for each function or variable that shares a name with another function or variable.
This is an Overriding Requirement for [1] No Conflicting Inheritance.

See also the related requirement [2] Compiler Bug SOL-2020-2.

[2] Sources of Randomness
Sources of randomness used in Tested Code MUST be sufficiently resistant to prediction that their purpose is met.

This requirement involves careful evaluation for each specific contract and case. Some uses of randomness rely on no prediction being more accurate than any other. For such cases, values that can be guessed at with some accuracy or controlled by miners or validators, like block difficulty, timestamps, and/or block numbers, introduces a vulnerability. Thus a "strong" source of randomness like an oracle service is necessary. Other uses are resistant to "good guesses" because using something that is close but wrong provides no more likelihood of gaining an advantage than any other guess. For example a competition to guess the block number of a chain at a specific time, that rewards the answer closest to the correct answer is using a source of "randomness" that is vulnerable to approximate guessing. On the other hand, for a lottery that will only pay if a number is submitted that exactly matches a winning entry in an offchain lottery to be held in the future, there is no advantage in being able to approximate the answer.

[2] Don't misuse block data
Block numbers and timespamps used in Tested Code MUST not introduce vulnerabilities to MEV or similar attacks.

Block numbers are vulnerable to approximate prediction, although they are generally not reliably precise indicators of elapsed time. `block.timestamp` is subject to manipulation by malicious actors. It is therefore important that these data are not trusted by Tested Code to function as if they were highly reliable or random information. The description of [SWC-116](https://swcregistry.io/docs/SWC-116) in [[swcregistry]] includes some code examples for techniques to avoid, for example using `block.number / 14` as a proxy for elapsed seconds, or relying on `block.timestamp` to indicate a precise time has passed. For low precision, such as "a few minutes", `block.number / 14 > 1000` can be sufficient on main net, or a blockchain with a regular block period of around 14 seconds. But using it to determine that e.g. "exactly 36 seconds" passed fails the requirement, and a contract that relies on a specific block period can introduce serious risks if it is deployed on another blockchain with a very different block frequency. Likewise, because block.timestamp depends on settings that can be manipulated by a malicious node operator, in cases likes Ethereum mainnet it is suitable for use as a coarse-grained approximation (on a scale of minutes) but the same code on a different blockchain can be vulnerable to MEV attacks. Note that this is related to the use of Oracles, which can also provide inaccurate information.

[2] Proper Signature Verification
Tested Code MUST use proper signature verification to ensure authenticity of messages that were signed off-chain, e.g. by using ecrecover().

See also SWC-122 [[swcregistry]]. For code that does use `ecrecover()`, see the related requirements [1] Compiler Bug SOL-2017-3 and [2] Validate ecrecover() input

[2] No Improper Usage of Malleable Signatures for Replay Attack Protection
Tested Code using signatures to prevent replay attacks MUST NOT rely on Malleable Signatures.

In Replay Attacks, an attacker replays correctly signed messages to exploit a system. Malleable signatures allow an attacker to create a new signature for the same message. Smart contracts that check against hashes of signatures to ensure that a message has only been processed once may be vulnerable to replay attacks if malleable signatures are used.

[2] Handle External Call Returns
Tested Code that makes external calls MUST reasonably handle possible errors.

See also the related requirements: [3] Process All Valid Inputs [1] Check External Calls Return.

[2] No failing `assert` statements
assert() statements in Tested Code MUST NOT fail.

`assert` statements are meant for invariants, not as a generic error-handling mechanism. If an `assert` statement fails because it is being used as a mechanism to catch errors, it SHOULD be replaced with a `require` statement or similar mechanism designed for the use case. If it fails due to a coding bug, that needs to be fixed. This requirement is based on [[CWE-670]] Always-Incorrect Control Flow Implementation.

Security Level 3

In addition to automatable verification (Level 1) and a manual audit (Level 2), EEA EthTrust Certification at Level 3 implies the intended functionality of Tested code is sufficently well documented that its functional correctness can be verified, and that the code and documentation has been thoroughly reviewed by a human auditor or audit team to ensure that they are both internally coherent and consistent with each other, as well as to eliminate complex security vulnerabilities. This level of review is especially relevant for tokens, for example using ERC20 [[ERC20]]. At this Level there are also checks to ensure the code does not contain errors that do not directly impact security, but do impact code quality. Code is often copied, so Level 3 code needs to be as well-written as possible. The risk being addressed is that it is easy and not uncommon to introduce weaknesses by copying existing code as a starting point.

[3] Pass Level 2
To be eligible for EthTrust Level 3 certification, Tested code MUST meet the requirements for .

[3] Code Linting
The following MUST all be true for the source code of the Tested code:

  • There are no unnecessary variables created, and
  • There is no code that cannot be reached in execution
    except for code explicitly intended to manage unexpected errors, such as assert statements, and
  • All functions and variables have explicitly declared visibility, and
  • No deprecated instruction codes are present.

Documentation requirements

Level 3 conformance requires a detailed description of how the Tested Code is intended to behave. Alongside detailed testing requirements to check that it does behave as described wth regard to specific known security vulnerabililies, it is important that the claims made for it are accurate. This requirement underpins a Good Practice, that it fulfils claims made for it outside audit-specific documentation. The combination of these requirements helps ensure there is no malicious code, such as malicious "back doors" or "time bombs" hidden in the Tested Code. Since there are legitimate use cases for code that behaves as e.g. a time bomb, or "phones home", this combination helps ensure that testing focuses on real problems. The requirements in this section extend the coverage required to meet the Level 2 requirement [**[2] Document Special Code Use**](#req-2-documented). As with that requirement, there are multiple requirements that require the documentation to perform an audit at this level.

[3] Document Contract Logic
A specification of the business logic that the Tested code functionality is intended to implement MUST be available to anyone who can call the Tested Code.

Contract Logic documented in a human-readable format and with enough detail that functional correctness and safety assumptions for special code use can be validated by auditors helps them assess complex code more efficiently and with higher confidence.

[3] Document System Architecture:
Documentation of the system architecture for the Tested code MUST be provided that conveys the overrall system design, privileged roles, security assumptions and intended usage.

System documentation provides auditor(s) information to understand security assumptions and ensure functional correctness. It is recommended that system documentation be included or referenced in the README file of the code repository alongside documentation for how the source code can be tested, built and deployed.

[3] Annotate Code with NatSpec:
All public interfaces contained in the Tested code MUST be annotated with inline comments according to the [[NatSpec]] format that explain the intent behind each function, parameter, and return variable, along with developer notes for safe usage.

Inline comments are important to ensure that developers and auditors understand the intent behind each function and other code components. Public interfaces should be interpreted as anything that would be contained in the ABI of the compiled Tested code. It is also recommended to use inline comments for private or internal functions that implement sensitive and/or complex logic. Following the [[NatSpec]] format allows these inline comments to be understood by the Solidity compiler for extracting them into a machine-readable format that may be used by other third-party tools for security assessments and automatic documentation. This may also be used to generate specifications that fully or partially satisfy the Requirement to [3] Document Contract Logic

[3] Implement as Documented
The Tested code MUST behave as described in the documentation provided for [3] Document Contract Logic.

Access Control

There are several common methods to implement access control, such as Role-Based Access Control [[RBAC]], and bespoke access control is often implemented for a given use case. Using industry-standard methods can help simplify the process of auditing, But is not sufficient to determine that there are no risks arising either from errors in implementation or due to a maliciously-crafted contract. It is particularly important that appropriate access control applies to payments, as noted in [SWC-105](https://swcregistry.io/docs/SWC-105), but other actions such as overwriting data as described in [SWC-124](https://swcregistry.io/docs/SWC-126), or changing specific access controls, also need to be appropriately protected [[swcregistry]]. This requirement effectively matches [[CWE-284]] Improper Access Control.

[3] Implement Access Control
The Tested code MUST implement appropriate access control mechanisms, based on the documentation provided for [3] Document Contract Logic.

[3] Safer External Calls
Contracts that contain external calls MUST document the need for them (see [3] Document Contract Logic), and the external calls MUST be protected in a way that is fully compatible with the claims of the contract author.
Meeting this requirement AND [3] Document Contract Logic constitutes an Overriding Requirement for: [1] Use Check-Effects-Interaction, and [2] Safe External Calls.

[3] Manage Gas Use Increases
Sufficient Gas must be available to work with data structures in the Tested Code that grow over time, in accordance with descriptions provided for [3] Document Contract Logic.

Some structures such as arrays can grow, and the value of variables is (by design) variable. Iterating over a structure whose size is not clear in advance, whether an array that grows, a bound that changes, or something determined by an external value, can result in significant increases in gas usage. What is reasonable growth to expect needs to be considered in the context of the business logic intended, and how the Tested Code protects against Gas Griefing attacks, where malicious actors or errors result in values occurring beyond the expected reasonable range(s). See also SWC-126, SWC-128 [[swcregistry]].

[3] Require Safe tx.origin
All uses of tx.origin MUST be verified to be consistent with all the stated security and functionality objectives of the contract, and not allow any such assertions about contract functionality to be violated by a malicious contract even if the malicious contract is called by a user who would be authorized to interact/take an action directly with the contract under audit.
This is an Overriding Requirement for [1] No tx.origin.

[3] Protect against Front-Running
Tested Code MUST NOT require information in a form that can be used to enable a front-running attack.

In front-running attacks, an attacker places their transaction in front of a victim's. This can be done by a malicious miner or by an attacker monitoring the mempool and preempting susceptible transactions by broadcasting their own transactions with higher transaction fees. Any smart contracts where an attacker would be incentivized to front-run should apply mitigations such as hash commitment schemes or batch execution.

[3] Protect against Miner Extractable Value (MEV)
Tested Code that is susceptible to MEV attacks MUST follow design patterns that mitigate this risk, such as hash commitment schemes or batch execution, where possible.

MEV, usually explained as "Miner (or Maximum) Extractable (or Extracted) Value", refers to the potential that a block producer can maliciously reorder or suppress transactions in order to gain a benefit that was not intended, for example by stealing or fraudulently claiming funds or information. See also the relevant part of .

[3] Process all valid inputs
All possible inputs MUST be processed correctly.

See also SWC-123 [[swcregistry]].

[3] State Changes Trigger Events
Tested code MUST emit a contract events for all transactions that cause state changes.

[3] No Private Data:
Tested code MUST NOT store private data on the blockchain

This is a Level 3 requirement primarily because the question of what is private data often requires careful and thoughtful assessment and a reasoned understanding of context. In general, this is likely to include an assessment of how the data is gathered, and what the providers of data are told about the usage of the information.

Private data is used in this specification to refer to information that should not be generally available to the public. For example, an individual's home telephone number is generally private data, while a business' customer enquiries telephone number is generally not private data. Information identifying a person's account is normally private data, but there are circumstances where it is public data. In such cases that data can be recorded on-chain in conformance with this requirement.

PLEASE NOTE: In some cases regulation such as the [[GDPR]] imposes formal legal requirements on some private data. However, performing a test for this requirement results in an expert technical opinion on whether data that the auditor considers private is exposed. A statement about whether Tested Code meets this requirement does not represent any form of legal advice or opinion, attorney representation, or the like.

Recommended Good Practices

This section describes good practices that require substantial human judgement to evaluate, or where a poor implementation can reduce rather than increase the security of the Tested Code. Testing for, and meeting these requirements does not directly affect conformance.

[GP] Check For and Address New Security Bugs If the Tested Code is audited after July 2022, check [[!solidity-bugs-json]] and other sources for bugs newer than SOL-2022-5 and address them.

This specification was written between April 2021 and July 2022. New vulnerabilities are discovered from time to time, on an unpredictable schedule. Checking for Solidity security alerts published too late to be incorporated into the current version of this document is an important technique for maintaining the highest possible levels of security. There are other sources of information on new security vulnerabilities, from [[CWE]] to following the blogs of many security-oriented organizations such as those that contributed to this specification.

[GP] Meet as many requirements as possible The Tested Code SHOULD meet as many requirements of this specification as possible at levels above the level for which it is certified.

While meeting some requirements for a higher EEA EthTrust certification level makes no change to the formal conformance of the Tested Code, each requirement is specified because meeting it provides protection against specific known security attacks. If it is possible to meet a particular requirement that is not necessary for conformance at the level being tested, meeting that requirement will improve the security of the Tested Code and is therefore worth doing.

[GP] Use Latest Compiler The Tested Code SHOULD use the latest available stable version of the Solidity compiler.

The Solidity compiler is regularly updated to improve performance but also specifically to fix security vulnerabilities that are discovered. There are many requirements in that are related to vunerabilities known at the time this specification was written, as well as ehancements made to provide better security by default. In general, newer versions of the compiler improve security, so unless there is a specific known reason not to do so, using the latest version available will result in better security.

[GP] Write clear, legible Solidity code The Tested Code SHOULD be written for easy understanding.

There are no strict rules defining how to write clear code. It is important to use sufficiently descriptive names, comment code appropriately, and use structures that are easy to understand without causing the code to become excessively large because that also makes it difficult to read and understand. Excessive nesting, unstructured comments, complex looping structures, and the use of very terse names for variables and functions are examples of coding styles that can also make code harder to understand. It is important to note that in some cases, developers can sacrifice easy reading for other benefits such as reducing gas costs - this can be mitigated somewhat by providing a reasonable level of comments in the code. This Good Practice extends somewhat the Related Requirement [3] Code Linting, but judgements about how to meet it are necessarily more subjective than in the specifics that requirement establishes. Those looking for additional guidance on code styling can refer to the [[Solidity-Style-Guide]].

[GP] Follow Accepted ERC Standards The Tested Code SHOULD conform to finalized [[ERC]] standards when it is reasonably capable of doing so for its use-case. An ERC is a category of [[EIP]] (Ethereum Improvement Proposal) that defines application-level standards and conventions, including smart contract standards such as token standards (EIP-20) and name registries (EIP-137).

While following ERC standards will not inherently make Solidity code secure, they do enable developers to integrate with common interfaces and follow known conventions for expected behavior. If the Tested Code does claim to follow a given ERC, its functional correctness in conforming to that standard can be verified by auditors.

[GP] Define a Software License The Tested Code SHOULD define a software license, which is commonly open-source for Solidity code deployed to public networks. A software license provides legal guidance on how contributors and users can interact with the code, including auditors and whitehats.

It is important to choose a [[software-license]] that best addresses the needs of the project, and clearly link to it throughout the Tested Code and documentation, e.g. using a prominent LICENSE file in the code repository, and referencing it from each source file.

Additional Information

Defined Terms

The following is a list of terms defined in this Specification.

Summary of Requirements

This section provides a summary of all requirements in this Specification.

Acknowledgments

The EEA acknowledges and thanks the many people who contributed to the development of this version of the specification. Please advise us of any errors or omissions. Enterprise Ethereum is built on top of Ethereum, and we are grateful to the entire community who develops Ethereum, for their work and their ongoing collaboration. It helps us maintain as much compatibility as possible with the Ethereum ecosystem. Security principles have also been developed over many years by many individuals, far too numerous to individually thank for contributions that have helped us to write the present specification. We are grateful to the many people on whose work we build.