Level [S] Certification Requirements according to EEA EthTrust Security Levels Specification v1.
This tool is designed to attain Security Level [S], where the rules are configured to exclusively require static tools, eliminating the necessity for human analysis. The guidelines adhere to the directives outlined in the EEA EthTrust Security Levels Specification v1 dated August 22, 2022, accessible at entethalliance.org/specs/ethtrust-sl/.
Security Level [S]
EEA EthTrust Certification at Security Level [S] 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 difficult to verify automatically, usually 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 Security Level. To be eligible for EEA EthTrust Certification for Security Level [S], Tested code MUST fulfill all Security Level [S] requirements, unless it meets the applicable Overriding Requirement(s) for any Security Level [S] requirement it does not meet.
No CREATE2
Tested code MUST NOT contain a CREATE2 instruction.
unless it meets the Set of Overriding Requirements
[M] Protect CREATE2 Calls, and [M] Document Special Code Use
The CREATE2 opcode provides the ability to interact with addresses that do not exist yet on-chain but could possibly eventually contain code. While this can be useful for deployments and counterfactual interactions with contracts, it may allow external calls to code that is not yet known, and could turn out to be malicous or insecure due to errors or weak protections.
No tx.origin
Tested code MUST NOT contain a tx.origin instruction.
unless it meets the Overriding Requirement [Q] Verify tx.origin usage
tx.origin is a global variable in Solidity which returns the address of the account that sent the transaction. A contract using tx.origin could be made vulnerable if an authorized account calls into a malicious contract, allowing it to pass the authorization check in unintended cases. Use msg.sender for authorization instead of tx.origin.
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 MEV attack.
No Conflicting Inheritance
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.
In most programming languages, including Solidity, it is possible to use the same name for variables or functions that have different types or (for functions) input parameters. This can be hard to interpret in the source code, meaning reviewers misunderstand the code or are maliciously misled to do so, analogously to Homoglyph Attacks.
This requirement means that unless the Overriding Requirement is met, any function or variable name will not be repeated, to eliminate confusion. It does however allow functions to be overridden, e.g. from a Base contract, so long as there is only one version of the function that operates within the code. See also the related requirement [M] Compiler Bug SOL-2020-2, and the documentation of function inheritance in [solidity-functions].
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.
No Self-destruct
Tested code MUST NOT contain the selfdestruct() instruction or its now-deprecated alias suicide().
unless it meets the Set of Overriding Requirements
[M] Protect Self-destruction, and [M] Document Special Code Use
If the selfdestruct() instruction (or its deprecated alternative suicide()) is not carefully protected, malicious code can call it and destroy a contract, sending any Ether held by the contract, which may result in stealing it. This feature can often break immutability and trustless guarantees to introduce numerous security issues. In addition, once the contract has been destroyed any Ether sent is simply lost, unlike when a contract is disabled which causes a transaction sending Ether to revert.
No assembly()
Tested Code MUST NOT contain the assembly() instruction
unless it meets the Set of Overriding Requirements
[M] Avoid Common assembly() Attack Vectors, [M] Document Special Code Use, [M] Compiler Bug SOL-2022-5 in assembly(), [M] Compiler Bug SOL-2022-4, [M] Compiler Bug SOL-2021-3, and [M] Compiler Bug SOL-2019-2 in assembly().
The assembly() instruction allows lower-level code to be included. This give the authors much stronger control over the bytecode that is generated, which can be used for example to optimise gas usage. However, it also potentially exposes a number of vulnerabilites and bugs that are additional attack surfaces, and there are a number of ways to use assembly() to introduce deliberately malicious code that is difficult to detect.
For more information on S Certification:
Go to EthTrust Certified Section.