Methodology

How Stabledesk measures stablecoin activity on the Arc. ← Back to the terminal

Stabledesk indexes on-chain Transfer events for the Arc stablecoins and turns them into time series, supply metrics and flow analytics — with a deliberate focus on real economic volume, not raw event counts.

Data source

Everything is read directly from the chain — no third-party data provider. Blocks and logs come from the Arc public RPC (with fallback endpoints), chain ID 5042. Arc is an EVM chain where gas is paid in USDC and blocks are ~0.5s with no reorgs.

We track the official Arc stablecoins (ERC-20 interface): USDC (native gas token), EURC and USYC (yield / tokenized MMF). A historical indexer backfills recent history on first run, then keeps indexing forward and persists aggregates in SQLite.

Three volume measures

Naïve volume badly overstates real activity, for two independent reasons. We correct each with its own filter, and publish all three figures so you can see exactly what every step removes.

1 · Raw volume — every Transfer event, unfiltered.

2 · Real volume — a transaction-level filter. A single user action often emits several Transfer events (routing hops, contract internals), so within each transaction we keep only the largest transfer per token and discard the rest. Per token, not per transaction: a swap moves two different assets in one transaction, and collapsing it to a single leg would erase the smaller asset's volume entirely.

3 · Adjusted volume — real volume, plus an address-level filter. Some addresses are infrastructure rather than economic actors: market-making bots, faucets, sequencers, test harnesses. Any address whose activity rate exceeds 1,000 transfers or $10M of volume per month is flagged. A transfer is dropped when both of its ends are flagged — infrastructure talking to infrastructure. The thresholds come from the Visa / Allium onchain analytics methodology.

Why "both ends", not "either end". Visa drops a transfer if either end is flagged. That is right for retail-shaped chains, where most transfers run user-to-user and a flagged counterparty is a strong signal of noise. Arc is hub-and-spoke: almost every transfer touches a faucet, router or sequencer, so the "either end" rule deletes genuine payments along with the churn — measured on the testnet, it removed 99.9% of volume and stopped describing anything. A bot paying a user, or a user funding an exchange, is real value delivered to a real party, so we keep it. Only bot-to-bot movement is discarded.

How flags are applied. Our retention window is a rolling ~7 days rather than a calendar month, so the monthly thresholds are converted to a daily rate and multiplied by however many days of history we actually hold. That window is floored at one full day, so a freshly-restarted indexer can't brand an ordinary address a bot off a handful of transfers. The flag set is recomputed every minute, and the terminal lists the currently flagged addresses — the filter is auditable, not a black box.

Flags are derived from the same history they filter, so on a cold start the initial backfill is indexed before any address has been flagged. Rather than ship a figure we know is wrong, the indexer re-reads that range once the first pass has revealed the high-frequency addresses and rewrites the adjusted numbers.

Network fees & economics

Gas on Arc is paid in USDC. That makes fee metrics unusually direct: a fee figure is already a dollar figure, with no token price, no exchange rate and no oracle in the path. We read fees from transaction receiptsgasUsed × effectiveGasPrice, summed per block — which captures the priority tip as well as the base fee.

Sampling. Receipts only exist per transaction, and at ~0.5s blocks fetching every one would mean ~172,000 requests a day against a rate-limited public RPC. So we sample a few blocks per poll, at a randomised offset behind the head. Each sampled block is exact; the per-day and per-window figures derived from them are extrapolations. The terminal and the API always report how many blocks a fee number rests on — an estimate is never presented as a measured total.

Cost to move $1M divides total network fees by real volume, not adjusted volume. The fee total in the numerator includes every transaction, high-frequency addresses included; dividing it by only the non-bot volume would price the whole network's cost against a fraction of its throughput and badly overstate it.

TVL & the protocol registry

TVL is measured as stablecoin balances held by contractsbalanceOf on each indexed asset, for every address we have established has bytecode. On a chain where value is denominated in USDC this is what TVL means: there is no volatile base asset to price and no LP share maths, so no per-protocol adapter is needed. On Ethereum the same method would be worthless; here it is the direct measurement.

Only contracts count. Contract-ness comes from eth_getCode, never from a heuristic. A balance sitting in a plain wallet is someone's money, not value locked in a protocol, and is excluded.

Unattributed value is reported, never hidden. A contract holding a balance that no registry entry claims is counted in the chain total and listed separately as unattributed. We publish the share of TVL we can actually name, next to the total — an ecosystem page that quietly drops what it cannot label is understating the chain, and one that assigns it to a plausible protocol is inventing data.

Registry provenance. Each protocol entry records how we know its contracts: canonical (a deterministic address identical on every EVM chain), team (the operator confirmed it), or observed (we found and classified it ourselves — which is not a claim about who operates it). Only the first two are marked verified. Two entries may never claim the same contract, because that would double-count its balance.

Known limits. Value held in assets other than the indexed stablecoins is invisible to this method. A protocol's own accounting may therefore be higher than ours, and where we know that to be the case the entry says so. TVL history begins the day measurement began — nothing is back-filled or estimated. Registry submissions and corrections: PROTOCOLS.md.

Metric definitions

MetricDefinition
Raw volumeSum of every Transfer event value.
Real volumeSum of the largest transfer per transaction, per token (routing hops & contract internals removed).
Adjusted volumeReal volume, minus transfers where both ends are flagged high-frequency addresses.
TransfersCount of transfer events in the period.
Mint / BurnTransfers from / to the zero address 0x000…000 — supply created / destroyed on-chain.
Net issuanceMint − Burn over the period: net new supply minted on-chain.
SupplyERC-20 totalSupply() read live from each token contract.
DominanceA token's supply ÷ total tracked stablecoin supply.
VelocityReal transfer volume per day ÷ supply — how often the supply turns over.
Active addressesDistinct addresses that sent or received in the trailing window (e.g. 1h).
Size distributionHistogram of transfer amounts bucketed by magnitude, over recently indexed transfers.
Avg fee / txTotal fees ÷ transaction count over sampled blocks, in USDC. Measured from receipts, not estimated from a gas assumption.
Fees / dayMean fee per sampled block × blocks per day — a run rate, not a cumulative total.
Cost to move $1MTotal network fees ÷ real volume, scaled to $1M. What the network charges to move a million dollars.
Flagged addressAn address exceeding 1,000 transfers or $10M volume per month, pro-rated to the retained window.
TVLSum of indexed stablecoin balances held by addresses with bytecode, read with balanceOf.
Attributed TVLThe part of TVL held by contracts a registry entry claims. The remainder is reported as unattributed.
Protocol "moved"Transfer volume across a protocol's contracts over the retained window (~7 days) — not 24 hours.
ObservedA listed protocol we have seen hold a balance or move value. Distinguishes a live entry from one only listed.

Timestamps & freshness

Because Arc blocks are ~0.5s and never reorg, a transfer's timestamp is derived from its block number against a rolling anchor (a recent block → timestamp reference) rather than fetching every block header — this keeps the indexer light on the rate-limited public RPC. Aggregates are stored per minute; the live snapshot refreshes every few seconds, and the header shows a live / delayed status. History is retained on a rolling ~7-day window.

Caveats

Address labels are a small curated / heuristic set and will grow over time. Figures are best-effort from public RPC data, may lag or reset, and are provided for informational purposes only — not investment advice.