fix: protocol activity statistics stay zero — ponder watches wrong contract addresses #4

Closed
opened 2026-04-05 17:14:12 +00:00 by johba · 2 comments
Owner

Problem

On the app page, protocol activity statistics stay zero on all parameters (except holder count) even after trades and staking.

Reported in codeberg#1193.

Root cause (three issues)

1. Missing LM_ADDRESS in ponder's .env.local

containers/bootstrap.sh write_ponder_env() writes KRAIKEN_ADDRESS and STAKE_ADDRESS but does not write LM_ADDRESS. Without it, ponder falls back to a hardcoded default in ponder.config.ts that has no code deployed on this Anvil fork. The actual LiquidityManager is at a different address.

Result: 5 LiquidityManager events on chain (Recentered, EthScarcity/EthAbundance) are completely missed. This causes: lastRecenterTimestamp=0, recentersLastDay=0, lastEthReserve=0.

2. Missing POOL_ADDRESS in ponder's environment

POOL_ADDRESS is hardcoded in services/ponder/src/kraiken.ts and stake.ts as a Base Sepolia address. On local Anvil, the pool is at a different address. This means:

  • Swap detection (isBuy = from.toLowerCase() === POOL_ADDRESS) never matches
  • No transactions recorded
  • updateEthReserve() reads WETH balance of a non-existent pool (returns 0)

3. Ring buffer never populated for early events

The initial Transfer events happen within 13 blocks of deployment. checkBlockHistorySufficient() requires 100 blocks since deployment before populating the ring buffer. All initial events hit the early-return path that updates totalMinted/totalBurned but skips the ring buffer, so rolling window stats (mintedLastDay, mintedLastWeek, etc.) compute to zero.

Why holder count works

holderCount is tracked directly in the Kraiken:Transfer handler — it increments/decrements when balances change from/to zero. It does NOT depend on the ring buffer, pool address, or LM address.

Fix

  1. containers/bootstrap.sh write_ponder_env() must include LM_ADDRESS and POOL_ADDRESS from the deployed contract addresses
  2. services/ponder/src/kraiken.ts and stake.ts should read POOL_ADDRESS from env instead of hardcoding it
  3. Consider reducing the 100-block history check for local dev environments, or seeding the ring buffer on first event regardless

Reproduction

curl -sf http://localhost:42069/graphql -H 'Content-Type: application/json' \
  -d '{"query": "{ stats(id: \"0x01\") { holderCount mintedLastDay burnedLastDay recentersLastDay lastEthReserve } }"}' | jq .
# holderCount=2, everything else=0

Files

  • containers/bootstrap.shwrite_ponder_env() missing LM_ADDRESS and POOL_ADDRESS
  • services/ponder/src/kraiken.ts — hardcoded POOL_ADDRESS
  • services/ponder/src/stake.ts — hardcoded POOL_ADDRESS
  • services/ponder/ponder.config.ts — LM_ADDRESS fallback default
  • services/ponder/src/helpers/ringBuffer.tscheckBlockHistorySufficient() 100-block threshold
## Problem On the app page, protocol activity statistics stay zero on all parameters (except holder count) even after trades and staking. Reported in [codeberg#1193](https://codeberg.org/johba/harb/issues/1193). ## Root cause (three issues) ### 1. Missing `LM_ADDRESS` in ponder's `.env.local` `containers/bootstrap.sh` `write_ponder_env()` writes `KRAIKEN_ADDRESS` and `STAKE_ADDRESS` but **does not write `LM_ADDRESS`**. Without it, ponder falls back to a hardcoded default in `ponder.config.ts` that has no code deployed on this Anvil fork. The actual LiquidityManager is at a different address. Result: 5 LiquidityManager events on chain (Recentered, EthScarcity/EthAbundance) are completely missed. This causes: `lastRecenterTimestamp=0`, `recentersLastDay=0`, `lastEthReserve=0`. ### 2. Missing `POOL_ADDRESS` in ponder's environment `POOL_ADDRESS` is hardcoded in `services/ponder/src/kraiken.ts` and `stake.ts` as a Base Sepolia address. On local Anvil, the pool is at a different address. This means: - Swap detection (`isBuy = from.toLowerCase() === POOL_ADDRESS`) never matches - No transactions recorded - `updateEthReserve()` reads WETH balance of a non-existent pool (returns 0) ### 3. Ring buffer never populated for early events The initial Transfer events happen within 13 blocks of deployment. `checkBlockHistorySufficient()` requires 100 blocks since deployment before populating the ring buffer. All initial events hit the early-return path that updates `totalMinted`/`totalBurned` but skips the ring buffer, so rolling window stats (`mintedLastDay`, `mintedLastWeek`, etc.) compute to zero. ## Why holder count works `holderCount` is tracked directly in the `Kraiken:Transfer` handler — it increments/decrements when balances change from/to zero. It does NOT depend on the ring buffer, pool address, or LM address. ## Fix 1. `containers/bootstrap.sh` `write_ponder_env()` must include `LM_ADDRESS` and `POOL_ADDRESS` from the deployed contract addresses 2. `services/ponder/src/kraiken.ts` and `stake.ts` should read `POOL_ADDRESS` from env instead of hardcoding it 3. Consider reducing the 100-block history check for local dev environments, or seeding the ring buffer on first event regardless ## Reproduction ```bash curl -sf http://localhost:42069/graphql -H 'Content-Type: application/json' \ -d '{"query": "{ stats(id: \"0x01\") { holderCount mintedLastDay burnedLastDay recentersLastDay lastEthReserve } }"}' | jq . # holderCount=2, everything else=0 ``` ## Files - `containers/bootstrap.sh` — `write_ponder_env()` missing LM_ADDRESS and POOL_ADDRESS - `services/ponder/src/kraiken.ts` — hardcoded POOL_ADDRESS - `services/ponder/src/stake.ts` — hardcoded POOL_ADDRESS - `services/ponder/ponder.config.ts` — LM_ADDRESS fallback default - `services/ponder/src/helpers/ringBuffer.ts` — `checkBlockHistorySufficient()` 100-block threshold
johba added the
backlog
label 2026-04-05 17:14:12 +00:00
dev-bot self-assigned this 2026-04-05 17:19:04 +00:00
dev-bot added
in-progress
and removed
backlog
labels 2026-04-05 17:19:04 +00:00
dev-qwen removed the
in-progress
label 2026-04-05 17:19:05 +00:00
dev-bot added the
in-progress
label 2026-04-05 17:24:02 +00:00
Collaborator

Blocked — issue #4

Field Value
Exit reason closed_externally
Timestamp 2026-04-05T17:31:56Z
### Blocked — issue #4 | Field | Value | |---|---| | Exit reason | `closed_externally` | | Timestamp | `2026-04-05T17:31:56Z` |
dev-bot added
blocked
and removed
in-progress
labels 2026-04-05 17:31:56 +00:00
johba closed this issue 2026-04-05 17:33:15 +00:00
Collaborator

Blocked — issue #4

Field Value
Exit reason closed_externally
Timestamp 2026-04-05T17:38:16Z
### Blocked — issue #4 | Field | Value | |---|---| | Exit reason | `closed_externally` | | Timestamp | `2026-04-05T17:38:16Z` |
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: johba/harb#4
No description provided.