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.
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(andlocked_amount); querying thesame address lowercased returns
credit_balance: 0andlocked_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):
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 withInsufficient balance(402) when<addr>is passed lowercase, and accepted with theidentical command when
<addr>is EIP-55 checksummed — same wallet, samecredits. 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 integratorhas to discover it the hard way.
Environment
the balance reads above
Possibly relevant code:
src/aleph/web/controllers/accounts.py(balanceendpoint),
src/aleph/jobs/cron/credit_balance_job.py,src/aleph/services/cost_validation.py— the fix presumably wants a singlenormalization (lowercase or checksum) applied at both write and read of the
per-address indexes.