Sanctifier now uses a unified finding code system across sanctifier-core and sanctifier-cli outputs.
Each code emitted by a detector links to its full page in the Detector Catalog — what it catches, a vulnerable example, the fix, and references.
| Code | Category | Meaning | Detector page |
|---|---|---|---|
S001 |
authentication | Missing authentication guard in a state-mutating function | auth_gap |
S002 |
panic_handling | panic! / unwrap / expect usage that may abort execution |
panic_detection |
S003 |
arithmetic | Unchecked arithmetic with overflow/underflow risk | arithmetic_overflow |
S004 |
storage_limits | Ledger entry size exceeds or approaches configured limits | ledger_size |
S005 |
storage_keys | Potential storage key collision | — |
S006 |
storage_durability | Persistent/instance storage access without a TTL extension | missing_ttl |
S007 |
custom_rule | User-defined custom rule match | — |
S009 |
logic | A Result that is silently dropped |
unhandled_result |
S012 |
code_hygiene | Hardcoded admin address / secret literal in an auth context | hardcoded_addr |
S013 |
code_hygiene | transfer/mint/burn missing amount > 0 / from != to guards |
edge_amount |
S015 |
code_hygiene | Unused local binding (dead code) | unused_variable |
S016 |
code_hygiene | Duplicate/inconsistent #[contracterror] discriminants |
error_code_collision |
S017 |
arithmetic | Fee/interest integer division that rounds to zero for micro-amounts | fee_rounding |
SANCT_ARG_DOS |
denial_of_service | Vec/Map argument iterated without a length cap |
arg_dos |
SANCT_UNWRAP |
panic_handling | unwrap / expect / risky unwrap_or_default inside #[contractimpl] entrypoints; replace with typed errors or explicit domain defaults |
sanct_unwrap |
SANCT_VISIBILITY |
authentication | Helper-shaped state mutator exposed through #[contractimpl] without authorization |
sanct_visibility |
SANCT_UNBOUNDED_STORAGE |
denial_of_service | Persistent/instance collection grows via append/insert with no removal or length cap | unbounded_storage |
SANCT_UNBOUNDED_RETURN |
scalability | Public entrypoint returning an unbounded collection (Vec or Map) |
unbounded_return |
SANCT_EAGER_UNWRAP_OR |
gas_efficiency | Eagerly-computed expensive fallback in unwrap_or() wastes gas |
eager_unwrap_or |
SANCT_CONTRACTERROR_ENUM |
logic | Public function returns error enum missing #[contracterror] or repr |
contracterror_enum |
SANCT_PROOF_LENGTH_UNVALIDATED |
zk_verification | Proof/public-input byte array reaches a verifier call with no length check first | proof_length_check |
SANCT_VK_PROVENANCE |
cryptography | ZK verifying key accepted at runtime and stored with no auth/hash-pin guard | vk_provenance |
Full catalog: Detector Catalog →
Emitted only by sanctifier wasm, which analyzes a deployed
module directly. See Source-Optional WASM Analysis for the
full source-vs-WASM comparison.
| Code | Category | Meaning |
|---|---|---|
W001 |
wasm | Compiled module has no Soroban contract spec section; may not be a Soroban contract |
W002 |
wasm | Compiled module exports no callable functions |
W003 |
wasm | Compiled module is missing Soroban environment metadata (interface version) |
W004 |
wasm | Compiled module uses floating-point value types, which the Soroban host rejects |
Flags unwrap(), expect(..), and risky unwrap_or_default() calls inside
Soroban #[contractimpl] entrypoints. In an entrypoint, an attacker-triggered
missing value can abort the whole transaction or silently turn absent financial
state into a default value.
#[contractimpl]
impl Token {
pub fn balance(env: Env, id: Address) -> i128 {
env.storage().persistent().get(&DataKey::Balance(id)).unwrap_or_default()
}
}Prefer explicit handling: return a typed Result, map missing state to a
domain-specific Error, or use an explicit default such as unwrap_or(0) only
when zero is the intended contract state.
Flags public helper-shaped methods inside #[contractimpl] that mutate contract
state without calling require_auth() or require_auth_for_args(). Leading
underscores and explicit helper or internal naming are treated as evidence
that a method was intended for internal use.
#[contractimpl]
impl Token {
pub fn _set_balance(env: Env, owner: Address, amount: i128) {
write_balance(&env, &owner, amount);
}
}Keep helpers private when possible. If a helper is intentionally exposed as a contract entrypoint, authenticate the appropriate principal before any state mutation.
- Text output from
sanctifier analyze - JSON report output under:
error_codes(full mapping table)- each item inside
findings.*ascode