Skip to content

Credit balance lookup is case-sensitive on EVM address: lowercase form of a funded address reads 0, rejecting on-behalf-of STOREs with "Insufficient balance" #1218

Description

@cpascariello

Summary

The CCN's per-address balance/credit index treats two case-variants of the same
EVM address as different accounts. Querying a funded address in EIP-55 checksum
case returns its real credit_balance (and locked_amount); querying the
same address lowercased returns credit_balance: 0 and locked_amount: 0.0.
EVM address identity is case-insensitive — EIP-55 casing is a display/integrity
encoding, not part of the identity (https://eips.ethereum.org/EIPS/eip-55) — so
the index should normalize the address before lookup (and on ingestion).

Reproduction

Against the public load balancer (any funded address shows this; this one is
ours and currently funded, feel free to verify):

curl -s "https://api.aleph.im/api/v0/addresses/0xB136a85c95a0ea573793AB9739c7dF8682B87fCa/balance"
curl -s "https://api.aleph.im/api/v0/addresses/0xb136a85c95a0ea573793ab9739c7df8682b87fca/balance"

Observed (2026-07-03):

{"address":"0xB136a85c95a0ea573793AB9739c7dF8682B87fCa","balance":0.0,"details":{},"locked_amount":456.70008868005937,"credit_balance":1379752353,"credit_balance_details":null}
{"address":"0xb136a85c95a0ea573793ab9739c7df8682b87fca","balance":0.0,"details":{},"locked_amount":0.0,"credit_balance":0,"credit_balance_details":null}

Expected

Both queries return the same record — one funded account, regardless of the
case the caller used.

Impact

This is not just a read-path cosmetic: the same index appears to back credit
validation for paid messages. aleph file upload --payment-type credit --on-behalf-of <addr> (aleph-rs CLI) is rejected with Insufficient balance (402) when <addr> is passed lowercase, and accepted with the
identical command when <addr> is EIP-55 checksummed — same wallet, same
credits. Any integrator that stores addresses lowercase (a very common
normalization, e.g. for use as map keys) hits this as a confusing payment
failure on a funded account.

Our workaround

We checksum at the boundary before every CCN-facing call
(ethers.utils.getAddress(walletAddress)), which works but every integrator
has to discover it the hard way.

Environment

  • CCN: api.aleph.im (load balancer), observed 2026-07-03
  • Client: aleph-rs CLI v0.10.3 for the upload-rejection path; plain curl for
    the balance reads above

Possibly relevant code: src/aleph/web/controllers/accounts.py (balance
endpoint), src/aleph/jobs/cron/credit_balance_job.py,
src/aleph/services/cost_validation.py — the fix presumably wants a single
normalization (lowercase or checksum) applied at both write and read of the
per-address indexes.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions