Checklist for EEA EthTrust Security Levels Version 2

EEA Document

This version:
https://entethalliance.org/specs/ethtrust-sl/v2/checklist.html
Latest editor's draft:
https://entethalliance.github.io/eta-registry/checklist.html

Status of This Document

This section describes the status of this document at the time of its publication. Newer documents may supersede this document.

This specification is licensed by the Enterprise Ethereum Alliance, Inc. (EEA) under the terms of the Apache License, Version 2.0 [License]. Unless otherwise explicitly authorised in writing by the EEA, you can only use this document in accordance with those terms.

Unless required by applicable law or agreed to in writing, this document is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

Please send any comments to the EEA at https://entethalliance.org/contact/, or as issues via the EthTrust-public GitHub repository.

The Working Group expects at the time of publication to publish the next release version of this checklist alongside the next version of the Specification, in 2025.

1. Introduction

This section is non-normative.

This companion document is a checklist for [EthTrust-sl-v2], the EEA EthTrust Security Levels Specification. It lists the requirements for granting EEA EthTrust Certification to a smart contract written in Solidity as a convenience for security reviewers, developers, or others, who are familiar with the EEA EthTrust Security Levels Specification, and want an aide memoire.

In case of any discrepancy between this checklist, and the relevant version of the EEA EthTrust Security Levels Specification, readers should assume that this document is in error, and the definitive version is the text in the specification.

EEA EthTrust Certification is a claim by a security reviewer that the Tested Code is not vulnerable to a number of known attacks or failures to operate as expected, based on the reviewer's assessment against those specific requirements.

EEA EthTrust Certification does not and cannot ensure that the Tested Code is completely secure from any attack.

1.1.2 Typographic Conventions

Definitions of terms are formatted Like this. Most of the terms are defined in the main specification document. Some definitions are repeated in this document. References to defined terms are rendered as links Like This.

References to other documents are links to the relevant entry in the § B. References section, within square brackets, such as: [CWE].

Links to requirements begin with a Security Level: [S], [M] or [Q], and recommended good practices begin with [GP]. They then include the requirement or good practice name. They are rendered as links in bold type, for example:

Example of a link to [M] Document Special Code Use.

Variables, introduced to be described further on in a statement or requirement, are formatted as var.

2. Conformance

The key words MAY, MUST, MUST NOT, RECOMMENDED, and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

The EthTrust Security Levels Specification defines a number of requirements. As described in more detail by § 1.1.3 How to Read a Requirement of that document, each requirement has a Security Level ([S], [M] or [Q]), and a statement of the requirement that Tested Code MUST meet.

In order to achieve EEA EthTrust Certification at a specific Security Level, the Tested Code MUST meet all the requirements for that Security Level, including all the requirements for lower Security Levels. Some requirements can either be met directly, or by meeting one or more Overriding requirements that mean the requirement is considered met.

Section § 4.4 Recommended Good Practices, contains further recommendations. Although they are formatted similarly to requirements, they begin with a "level" marker [GP]. 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.

To provide as strong a level of assurance as possible, Tested Code SHOULD meet as many requirements as possible at all Security Levels.

This document does not create an affirmative duty of compliance on any party, though requirements to comply with it could be created by contract negotiations or other processes with prospective customers or investors.

2.1 Conformance Claims

To grant Tested Code EEA EthTrust Certification, an auditor provides a Valid Conformance Claim, that the Tested Code meets the requirements of the Security Level for which it is certified.

There is no required format for a Valid conformance claim for Version 1 of this specification, beyond being legible and containing the required information as specified in this section.

A Valid Conformance Claim MUST include:

A Valid Conformance Claim for Security Level [Q] MUST contain a [SHA3-256] hash of the documentation provided to meet [Q] Document Contract Logic and [Q] Document System Architecture.

A Valid Conformance Claim SHOULD include

A Valid Conformance Claim MAY include:

2.2 Security Level Requirements

RequirementStatus
[S] Encode Hashes with chainid 🔗
Tested code MUST create hashes for transactions that incorporate chainid values following the recommendation described in [EIP-155]

[S] No tx.origin 🔗
Tested code MUST NOT contain a tx.origin instruction
unless it meets the Overriding Requirement [Q] Verify tx.origin Usage

[S] 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
unless it meets the Overriding Requirement [M] Verify Exact Balance Checks.

[S] No Conflicting Names 🔗
Tested code MUST NOT include more than one variable, or operative function with different code, with the same name
unless it meets the Overriding Requirement: [M] Document Name Conflicts.

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

[S] No selfdestruct() 🔗
Tested code MUST NOT contain the selfdestruct() instruction or its now-deprecated alias suicide()
unless it meets the Set of Overriding Requirements

[S] No Unicode Direction Control Characters 🔗
Tested code MUST NOT contain any of 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 [M] No Unnecessary Unicode Controls.

[S] Check External Calls Return 🔗
Tested Code that makes external calls using the Low-level Call Functions (i.e. call(), delegatecall(), staticcall(), and send()) MUST check the returned value from each usage to determine whether the call failed,
unless it meets the Overriding Requirement [M] Handle External Call Returns.

[S] No Overflow/Underflow 🔗
Tested code MUST NOT use a Solidity compiler version older than 0.8.0
unless it meets the Set of Overriding Requirements

[S] Compiler Bug SOL-2023-3 🔗
Tested code that includes Yul code and uses the `verbatim` instruction twice, in each case surrounded identical code, MUST disable the Block Deduplicator when using a Solidity compiler version between 0.8.5 and 0.8.22 (inclusive).

[S] Compiler Bug SOL-2022-6 🔗
Tested code that ABI-encodes a tuple (including a struct, return value, or paramater list) with the ABIEncoderV2, that includes a dynamic component and whose last element is a calldata static array of base type uint or bytes32 MUST NOT use a Solidity compiler version between 0.5.8 and 0.8.15 (inclusive).

[S] 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 Solidity compiler version older than 0.8.15.

[S] 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 Solidity compiler version between 0.6.9 and 0.8.13 (inclusive).

[S] Compiler Bug SOL-2022-2 🔗
Tested code with a nested array that

  • passes it to an external function, or
  • passes it as input to abi.encode(), or
  • uses it in an event

MUST NOT use a Solidity compiler version between 0.6.9 and 0.8.13 (inclusive).

[S] Compiler Bug SOL-2022-1 🔗
Tested code that

  • uses Number literals for a bytesNN type shorter than 32 bytes, or
  • uses String literals for any bytesNN type,

and passes such literals to abi.encodeCall() as the first parameter, MUST NOT use Solidity compiler version 0.8.11 nor 0.8.12.

[S] Compiler Bug SOL-2021-4 🔗
Tested Code that uses custom value types shorter than 32 bytes MUST NOT use Solidity compiler version 0.8.8.

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

[S] 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
  • the values of length are not multiples of 32,

MUST NOT use the Optimizer with a Solidity compiler version older than 0.8.3.

[S] 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 use a Solidity compiler version older than 0.7.4.

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

[S] Compiler Bug SOL-2020-9 🔗
Tested code that defines Free Functions MUST NOT use Solidity compiler version 0.7.1.

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

[S] 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 Solidity compiler version between 0.6.0 and 0.6.7 (inclusive).

[S] 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 Solidity compiler version between 0.5.14 and 0.6.7 (inclusive).

[S] 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 Solidity compiler version between 0.4.5 and 0.6.7 (inclusive), unless it meets the Overriding Requirement [M] Check Constructor Payment.

[S] Compiler Bug SOL-2020-4 🔗
Tested code that makes assignments to tuples that

  • have nested tuples, or
  • include a pointer to an external function, or
  • reference a dynamically sized calldata array

MUST NOT use a Solidity compiler version older than 0.6.4.

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

[S] 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 Solidity compiler version 0.6.0 nor a Solidity compiler version between 0.5.8 and 0.5.15 (inclusive).

[S] No Ancient Compilers 🔗
Tested code MUST NOT use a Solidity compiler version older than 0.3.

[M] Pass Security Level [S] 🔗
To be eligible for EEA EthTrust certification at Security Level [M], Tested code MUST meet the requirements for § 4.1 Security Level [S].

[M] Explicitly Disambiguate Evaluation Order 🔗
Tested code MUST NOT contain statements where variable evaluation order can result in different outcomes

[M] No Failing assert() Statements 🔗
assert() statements in Tested Code MUST NOT fail.

[M] Verify Exact Balance Checks 🔗
Tested code that checks whether the balance of an account is exactly equal to (i.e. ==) a specified amount or the value of a variable. MUST protect itself against transfers affecting the balance tested.
This is an Overriding Requirement for [S] No Exact Balance Check.

[M] 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 [S] No Unicode Direction Control Characters.

[M] 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.

[M] Protect External Calls 🔗
For Tested code that makes external calls:

unless it meets the Set of Overriding Requirements

This is an Overriding Requirement for [S] Use Check-Effects-Interaction.

[M] Avoid Read-only Re-entrancy Attacks 🔗
Tested Code that makes external calls MUST protect itself against Read-only Re-entrancy Attacks.

[M] Handle External Call Returns 🔗
Tested Code that makes external calls MUST reasonably handle possible errors.
This is an Overriding Requirement for [S] Check External Calls Return.

[M] Document Special Code Use 🔗
Tested Code MUST document the need for each instance of:

  • CREATE2,
  • assembly {},
  • selfdestruct() or its deprecated alias suicide(),
  • external calls,
  • delegatecall(),
  • code that can cause an overflow or underflow,
  • use of block.number or block.timestamp, or
  • use of oracles and pseudo-randomness,
  • 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.

    This is part of several Sets of Overriding Requirements, one for each of

    [M] Ensure Proper Rounding of Computations Affecting Value 🔗
    Tested code MUST identify and protect against exploiting rounding errors:

    • The possible range of error introduced by such rounding MUST be documented.
    • Tested code MUST NOT unintentionally create or lose value through rounding.
    • Tested code MUST apply rounding in a way that does not allow round-trips "creating" value to repeat causing unexpectedly large transfers.
    [M] Protect Self-destruction 🔗
    Tested code that contains the selfdestruct() or suicide() instructions MUST

    • ensure that only authorised parties can call the method, and
    • MUST protect those calls in a way that is fully compatible with the claims of the contract author.

    unless it meets the Overriding Requirement[Q] Enforce Least Privilege

    This is an Overriding Requirement for [S] No selfdestruct().

    [M] Avoid Common assembly {} Attack Vectors 🔗
    Tested Code MUST NOT use the assembly {} instruction to change a variable unless the code cannot:

    • create storage pointer collisions, nor
    • allow arbitrary values to be assigned to variables of type function.

    This is part of a Set of Overriding Requirements for [S] No assembly {}.

    [M] Protect CREATE2 Calls 🔗
    For Tested Code that uses the CREATE2 instruction, any contract to be deployed using CREATE2

    • MUST be within the Tested Code, and
    • MUST NOT use any selfdestruct(), delegatecall() nor callcode() instructions, and
    • MUST be fully compatible with the claims of the contract author,

    unless it meets the Set of Overriding Requirements

    This is part of a Set of Overriding Requirements for [S] No CREATE2.

    [M] 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 [S] No Overflow/Underflow.

    [M] 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 [S] No Conflicting Names.

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

    [M] Don't Misuse Block Data 🔗
    Block numbers and timestamps used in Tested Code MUST not introduce vulnerabilities to MEV or similar attacks.

    [M] Proper Signature Verification 🔗
    Tested Code MUST properly verify signatures to ensure authenticity of messages that were signed off-chain.

    [M] No Improper Usage of Signatures for Replay Attack Protection 🔗
    Tested Code using signatures to prevent replay attacks MUST ensure that signatures cannot be reused:

    • In the same function to verify the same message,
    • In more than one function to verify the same message within the Tested Code,
    • In more than one contract address to verify the same message, in which the same account(s) may be signing messages, and
    • In the same contract address across multiple chains.

    unless it meets the Overriding Requirement [Q] Intended Replay. Additionally, Tested Code MUST verify that multiple signatures cannot be created for the same message, as is the case with Malleable Signatures.

    [M] Solidity Compiler Bug 2023-1 🔗
    Tested code that contains a compound expression with side effects that uses .selector MUST use the viaIR option with Solidity compiler versions between 0.6.2 and 0.8.20 inclusive.

    [M] Compiler Bug SOL-2022-7 🔗
    Tested code that has storage writes followed by conditional early terminations from inline assembly functions containing return() or stop() instructions, MUST NOT not use a Solidity compiler version between 0.8.13 and 0.8.17 inclusive.
    This is part of the Set of Overriding Requirements for [S] No assembly {}.

    [M] 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 Solidity compiler version older than 0.8.15.
    This is part of the Set of Overriding Requirements for [S] No assembly {}.

    [M] 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 Solidity compiler versions 0.8.13 or 0.8.14.
    This is part of the Set of Overriding Requirements for [S] No assembly {}.

    [M] 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 Solidity compiler version between 0.6.5 and 0.8.8 (inclusive).
    This is part of the Set of Overriding Requirements for [S] No assembly {}.

    [M] Compiler Bug Check Constructor Payment 🔗
    Tested code that allows payment to a constructor function that is

    • defined in a base contract, and
    • used by default in another contract without an explicit constructor, and
    • not explicity marked payable,

    MUST NOT use a Solidity compiler version between 0.4.5 and 0.6.7 (inclusive).
    This is an Overriding Requirement for [S] Compiler Bug SOL-2020-5.

    [Q] Pass Security Level [M] 🔗
    To be eligible for EEA EthTrust certification at Security Level [Q], Tested code MUST meet the requirements for § 4.2 Security Level [M].

    [Q] Code Linting 🔗
    Tested code

    • MUST NOT create unnecessary variables, and
    • MUST NOT include code that cannot be reached in execution
      except for code explicitly intended to manage unexpected errors, such as assert() statements, and
    • MUST NOT contain a function that has the same name as the smart contract unless it is explicitly declared as a constructor using the constructor keyword, and
    • MUST explicitly declare the visibility of all functions and variables.

    [Q] 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 [Q] Document Contract Logic.

    [Q] Protect Gas Usage 🔗
    Tested Code MUST protect against malicious actors stealing or wasting gas.

    [Q] Protect against Oracle Failure 🔗
    Tested Code MUST protect itself against malfunctions in Oracles it relies on.

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

    [Q] Protect against MEV Attacks 🔗
    Tested Code that is susceptible to MEV attacks MUST follow appropriate design patterns to mitigate this risk.

    [Q] Protect against Governance Takeovers 🔗
    Tested Code which includes a governance system MUST protect against one external entity taking control via exploit of the governance design.

    [Q] Process All Inputs 🔗
    Tested Code MUST validate inputs, and function correctly whether the input is as designed or malformed.

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

    [Q] No Private Data 🔗
    Tested code MUST NOT store Private Data on the blockchain

    [Q] Intended Replay 🔗
    If a signature within the Tested Code can be reused, the replay instance MUST be intended, documented, and safe for re-use.

    This is an Overriding Requirement for [M] No Improper Usage of Signatures for Replay Attack Protection.

    [Q] 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.

    [Q] 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.

    [Q] 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, event, and return variable, along with developer notes for safe usage.

    [Q] Implement as Documented 🔗
    The Tested code MUST behave as described in the documentation provided for [Q] Document Contract Logic, and [Q] Document System Architecture.

    [Q] Enforce Least Privilege 🔗
    Tested code that enables privileged access MUST implement appropriate access control mechanisms that provide the least privilege necessary for those interactions, based on the documentation provided for [Q] Document Contract Logic.
    This is an Overriding Requirement for [S] Protect Self-destruction.

    [Q] Use Revocable and Transferable Access Control Permissions 🔗
    If the Tested code makes uses of Access Control for privileged actions, it MUST implement a mechanism to revoke and transfer those permissions.

    [Q] No Single Admin EOA for Privileged Actions 🔗
    If the Tested code makes uses of Access Control for privilieged actions, it MUST ensure that all critical administrative tasks require multiple signatures to be executed, unless there is a multisg admin that has greater privileges and can revoke permissions in case of a compromised or rogue EOA and reverse any adverse action the EOA has taken.

    [Q] Verify External Calls 🔗
    Tested Code that contains external calls

    • MUST document the need for them, and
    • MUST protect them in a way that is fully compatible with the claims of the contract author.

    This is part of a Set of Overriding Requirements for [S] Use Check-Effects-Interaction, and for [M] Protect External Calls.

    [Q] Verify tx.origin Usage 🔗
    For Tested Code that uses tx.origin, each instance

    This is an Overriding Requirement for [S] No tx.origin.

    A. Additional Information

    A.1 Defined Terms

    The following terms are defined in this document:

    The following terms used in this checklist are defined in the EEA EthTrust Security Levels Specification.

    B. References

    B.1 Normative references

    [CWE]
    Common Weakness Enumeration. MITRE. URL: https://cwe.mitre.org/index.html
    [EIP-155]
    Simple Replay Attack Protection. Ethereum Foundation. URL: https://eips.ethlibrary.io/eip-155.html
    [ERC]
    ERC Final - Ethereum Improvement Proposals. Ethereum Foundation. URL: https://eips.ethereum.org/erc
    [EthTrust-sl-v2]
    EEA EthTrust Security Levels Specification. Version 2. Enterprise Ethereum Alliance. URL: https://entethalliance.org/specs/ethtrust-sl/v2/
    [EVM-version]
    Using the Compiler - Solidity Documentation. (§Targets). Ethereum Foundation. URL: https://docs.soliditylang.org/en/latest/using-the-compiler.html#target-options
    [NatSpec]
    NatSpec Format - Solidity Documentation.. Ethereum Foundation. URL: https://docs.soliditylang.org/en/latest/natspec-format.html
    [RFC2119]
    Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
    [RFC8174]
    Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
    [SHA3-256]
    FIPS 202 - SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions. The National Institute of Standards (US Department of Commerce). URL: http://dx.doi.org/10.6028/NIST.FIPS.202
    [solidity-alerts]
    Solidity Blog - Security Alerts. Ethereum Foundation. URL: https://blog.soliditylang.org/category/security-alerts/
    [solidity-bugs]
    List of Known Bugs. Ethereum Foundation. URL: https://github.com/ethereum/solidity/blob/develop/docs/bugs.rst
    [solidity-bugs-json]
    A JSON-formatted list of some known security-relevant Solidity bugs. Ethereum Foundation. URL: https://github.com/ethereum/solidity/blob/develop/docs/bugs.json
    [swcregistry]
    Smart Contract Weakness Classification Registry. ConsenSys Diligence. URL: https://swcregistry.io
    [TimeLock]
    Protect Your Users With Smart Contract Timelocks. OpenZeppelin. URL: https://blog.openzeppelin.com/protect-your-users-with-smart-contract-timelocks/

    B.2 Informative references

    [License]
    Apache license version 2.0. The Apache Software Foundation. URL: http://www.apache.org/licenses/LICENSE-2.0