Skip to content

feat: add balance-reliance detector for unsafe address.balance usage#2941

Open
ep0chzer0 wants to merge 3 commits intocrytic:masterfrom
ep0chzer0:feature/balance-reliance-detector
Open

feat: add balance-reliance detector for unsafe address.balance usage#2941
ep0chzer0 wants to merge 3 commits intocrytic:masterfrom
ep0chzer0:feature/balance-reliance-detector

Conversation

@ep0chzer0
Copy link
Contributor

Summary

Adds a new detector that identifies potentially unsafe uses of address.balance in smart contracts.

Fixes #2778

Features

The detector flags two dangerous patterns:

1. Strict Equality Comparisons (== or !=)

// BAD: Can be manipulated via selfdestruct
require(address(this).balance == 1 ether);
require(address(this).balance != 0);

2. State Variable Assignment

// BAD: Balance becomes stale immediately
savedBalance = address(this).balance;

Why These Are Dangerous

  • Selfdestruct forcing: Attackers can forcibly send ETH using selfdestruct, breaking equality assumptions
  • Pre-deployment deposits: Pre-calculated contract addresses can receive ETH before deployment
  • Stale state: Balance can change between transactions, making stored values unreliable

Implementation

  • Uses SolidityCall with balance(address) to identify balance accesses
  • Tracks data dependency to catch indirect usage (balance stored in local var, then compared)
  • Checks for BinaryType.EQUAL and BinaryType.NOT_EQUAL comparisons
  • Detects assignment to StateVariable (both direct and via SSA)

Test Coverage

Test file includes:

  • Direct strict equality (==)
  • Direct strict inequality (!=)
  • Indirect comparison via local variable
  • Direct state assignment
  • Indirect state assignment via local variable
  • External address balance checks
  • Good patterns that should NOT be flagged (>=, <, range checks, arithmetic, local-only)

Example Output

BalanceRelianceTest.checkExactBalance() uses address.balance in strict equality (==):
    - address(this).balance == 1000000000000000000

BalanceRelianceTest.saveCurrentBalance() uses address.balance in state variable assignment:
    - savedBalance = address(this).balance

Recommended Patterns

// GOOD: use >= for minimum balance checks
require(address(this).balance >= 1 ether);

// GOOD: use range checks
require(address(this).balance >= min && address(this).balance <= max);

@ep0chzer0 ep0chzer0 requested a review from smonicas as a code owner January 20, 2026 17:14
@smonicas
Copy link
Collaborator

Hi, we already have the incorrect-equality detector for the same use case and i'm not sure it makes sense to have a detector flag every assignment of address(this).balance

@ep0chzer0 ep0chzer0 force-pushed the feature/balance-reliance-detector branch 2 times, most recently from 1562b34 to 2423f4a Compare January 21, 2026 01:04
@ep0chzer0
Copy link
Contributor Author

Hi @smonicas, thanks for the feedback!

You raise a good point about incorrect-equality. However, I believe this detector provides additional value:

Key differences from incorrect-equality:

  1. Specific attack vector: incorrect-equality is general-purpose (timestamps, block numbers, etc.), while this detector specifically targets address.balance manipulation via selfdestruct - a well-known attack pattern that deserves explicit flagging.

  2. State variable assignments: This detector also catches assignments like savedBalance = address(this).balance which stores a balance that becomes stale immediately. incorrect-equality doesn't flag this pattern since there's no equality comparison.

  3. Clearer guidance: The detector provides specific recommendations about balance manipulation risks, whereas incorrect-equality gives generic "don't use strict equality" advice.

Example patterns this catches that incorrect-equality doesn't:

// Pattern 1: Stale balance storage (no equality, just assignment)
savedBalance = address(this).balance;

// Pattern 2: Indirect comparison (depends on data flow analysis)
uint256 bal = address(this).balance;
require(bal == expected);  // incorrect-equality might miss the connection

That said, I understand if you feel this overlaps too much. Would you prefer I:

  1. Keep it as a separate detector (more specific guidance)
  2. Close this and potentially enhance incorrect-equality to cover these cases
  3. Make adjustments to reduce overlap

Happy to go with whatever approach works best for the project!

@ep0chzer0 ep0chzer0 force-pushed the feature/balance-reliance-detector branch 2 times, most recently from 0aeb52b to d3bb211 Compare January 23, 2026 18:03
Adds a new detector that identifies potentially unsafe uses of
address.balance in smart contracts:

1. Strict equality comparisons (== or !=) - vulnerable to ETH forcing
   via selfdestruct or pre-deployment balance manipulation

2. Assignment to state variables - leads to stale data and incorrect
   assumptions about current balances

The detector uses data dependency analysis to catch indirect usage
patterns where balance values flow through local variables.

Fixes crytic#2778
@ep0chzer0 ep0chzer0 force-pushed the feature/balance-reliance-detector branch from d3bb211 to 58fc464 Compare February 23, 2026 17:54
@ep0chzer0
Copy link
Contributor Author

Hi @smonicas, just checking in — did you get a chance to look at my response above? Happy to adjust the scope or close this if you feel it overlaps too much with incorrect-equality. Let me know either way!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: Add Balance Reliance Detector

2 participants