Skip to content

self-transfer guard detection only checks presence of a from == to comparison, not that it gates execution #368

Description

@unrealtim-tech

Labels: bug, checks-crate
Crate: checks

Description
crates/checks/src/transfer.rs's GuardScan (lines ~56-116) sets found = true the moment it sees any ExprBinary comparing the from/to parameters, with no verification that the comparison appears inside an if/assert!/early-return that actually prevents the transfer:

if (left_is_from && right_is_to) || (left_is_to && right_is_from) {
    self.found = true;
    return;
}

A no-op comparison assigned to an unused binding is enough to suppress the finding even though the actual transfer proceeds completely unguarded afterward:

pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
    from.require_auth();
    let _unused = from == to;     // never acted on
    do_actual_transfer(&env, &from, &to, amount);   // self-transfer proceeds unguarded
}

This is a distinct, more specific defect than the already-open #297 (severity mismatch).

Acceptance Criteria

  • Require the from/to comparison to be the condition of an if/assert!/require! (or similar control-flow-affecting construct) that can prevent the transfer, not merely present anywhere in the function.
  • Add a test with a no-op comparison assigned to an unused variable followed by an unguarded transfer, asserting a finding is still produced.

Difficulty: intermediate

Metadata

Metadata

Assignees

No one assigned

    Labels

    Stellar WaveIssues in the Stellar wave programbugSomething isn't workingchecks-crate

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions