A security-focused static analyzer for Sway written in Rust. The tool makes use of the existing sway-ast
and sway-parse
crates in order to parse Sway source code into its abstract syntax tree (AST). A recursive AST visitor is implemented on top of this, which will walk the AST structures top-down in a context-sensitive manner. Detectors leverage the AST visitor in order to implement their logic by inspecting the values contained in certain parts of the AST structures.
The sway-analyzer
binary requires the Rust compiler and its package manager, cargo.
See the Rust Install page for installation options.
The sway-analyzer
binary can be installed using the following commands:
cargo install sway-analyzer
The sway-analyzer
binary can be uninstalled using the following command:
cargo uninstall sway-analyzer
sway-analyzer [OPTIONS]
Flags | |
---|---|
-h , --help |
Prints help information |
-V , --version |
Prints version information |
Options | |
---|---|
--detectors <detectors>... |
The specific detectors to utilize. (Optional; Leave unused for all) |
--directory <directory> |
The path to the Forc project directory. (Optional) |
--display-format <display-format> |
The display format of the report. Can be "Text" or "Json". (Default = Text) |
--files <files>... |
The paths to the Sway source files. (Optional) |
--sorting <sorting> |
The order to sort report entries by. Can be "Line" or "Severity". (Default = Line) |
Color | Severity |
---|---|
🔴 | High |
🟡 | Medium |
🟢 | Low |
Name | Description | |
---|---|---|
🔴 | arbitrary_asset_transfer |
Checks for functions that transfer native assets to an arbitrary address without access restriction. |
🔴 | arbitrary_code_execution |
Checks for functions that make use of the LDC assembly instruction without access restriction. |
🟢 | boolean_comparison |
Checks if an expression contains a comparison with a boolean literal, which is unnecessary. |
🔴 | discarded_assignment |
Checks for variables that are assigned to without being utilized. |
🟢 | division_before_multiplication |
Checks for division operations before multiplications, which can result in value truncation. |
🟢 | explicit_return_statement |
Checks for functions that end with explicit return statements, which is unnecessary. |
🟡 | external_call_in_loop |
Checks if any functions contain any loops which performs calls to external functions. |
🟡 | inline_assembly_usage |
Checks functions for inline assembly usage. |
🟢 | large_literal |
Checks for expressions that contain large literal values, which may be difficult to read or interpreted incorrectly. |
🔴 | locked_native_asset |
Checks if a contract can withdraw potential incoming native assets. |
🟢 | magic_number |
Checks for expressions that contain irregular numerical constants that can be introduced as named constants. |
🟡 | manipulatable_balance_usage |
Checks if any functions contain balance usage which can potentially be manipulated. |
🟡 | missing_logs |
Checks for publicly-accessible functions that make changes to storage variables without emitting logs. |
🟡 | msg_amount_in_loop |
Checks for calls to std::context::msg_amount() or std::registers::balance() inside a while loop. In most cases, the result of the call should be stored in a local variable and decremented over each loop iteration. |
🟢 | non_zero_identity_validation |
Checks to see if functions containing Identity , Address and ContractId parameters are checked for a zero value. |
🔴 | potential_infinite_loop |
Checks for potentially infinite loops. |
🟡 | redundant_comparison |
Checks for functions that make redundant comparisons. |
🟡 | redundant_storage_access |
Checks for redundant calls to storage.x.read() and storage.x.write(x) . |
🟢 | storage_field_mutability |
Checks for any storage fields that can be refactored into constants or configurable fields. |
🔴 | storage_not_updated |
Checks for local variables that are read from storage, then modified without being written back to storage. |
🟢 | storage_read_in_loop_condition |
Checks for loops that contain a storage read in their condition, which can increase gas costs for each iteration. |
🔴 | strict_equality |
Checks for the use of strict equalities, which can be manipulated by an attacker. |
🟢 | unchecked_call_payload |
Checks for functions that supply a raw_ptr argument to the CALL assembly instruction, or a Bytes argument without checking its length. |
🔴 | unprotected_initialization |
Checks for initializer functions that can be called without requirements. |
🔴 | unprotected_storage_variable |
Checks for functions that make changes to storage variables without access restriction. |
🟡 | unsafe_timestamp_usage |
Checks for dependence on std::block::timestamp or std::block::timestamp_of_block , which can be manipulated by an attacker. |
🟢 | unused_import |
Checks for imported symbols that are not used. |
🟡 | weak_prng |
Checks for weak PRNG due to a modulo operation on a block timestamp. |