Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions benchmarks/memecoin-platforms.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,7 +46,7 @@ methodology:
- "Gas: meta.fee (lamports) converted to USD at the current SOL/USD price fetched from CoinGecko every 5 min."
- "Platform fees: explicit SOL or USDC/WSOL transfers to known fee wallet owners (confirmed on-chain). Unknown small recipients are captured via heuristics: SOL recipients receiving less than 5% of the user net flow, USDC/WSOL recipients receiving less than 5% of the largest pool receipt. Trading bots that use pre-funded escrow accounts (Trojan, Maestro) collect fees through a separate settlement mechanism not visible in the swap transaction; their displayed fee represents gas only."
- "AMM LP fees excluded: the 0.20% PumpSwap fee and 0.25% Raydium fee are settled inside pool accounts as LP fees — they are not transferred to any platform wallet and are outside this benchmark's scope."
- "Grouping: trades are split by the platform field returned by Mobula. Trades with no platform tag are currently assigned to pump-fun — known limitation: untagged traffic (MEV bots, snipers, direct scripts) inflates the pump-fun sample with zero-platform-fee trades, pulling its median toward gas-only. A dedicated Unattributed bucket is on the roadmap."
- "Grouping: platform tag from Mobula's platform field (frontend referral attribution). Trades with no platform tag use poolType to detect pump.fun natively: poolType=pumpfun (bonding curve) or poolType=pumpswap (graduated AMM) → attributed to pump-fun. All other untagged trades go to an internal unattributed bucket and are excluded from provider rows."
- "Cadence: full sweep every 5 minutes; tx results are cached to avoid re-parsing the same hash."
- "Aggregation: headline is the 24h median of the trade-count-weighted average of memecoin_platform_fee_pct across all tracked tokens."

Expand All@@ -63,8 +63,8 @@ faq:
a: "For confirmed platforms like Fomo, the fee wallet owner address is verified by inspecting multiple tagged trades on-chain. For platforms without a confirmed wallet, the harness uses a heuristic: any non-system, non-pool account receiving less than 5% of the user's net SOL flow, or less than 5% of the largest token pool receipt, is counted as a fee recipient. This captures Phantom-style referral tips without hardcoding every address."
- q: "Why does Trojan show near-zero fee?"
a: "Trojan and similar escrow-based bots (Maestro) pre-fund a shared wallet, execute trades from it, then settle with users in a separate transaction. The swap transaction itself shows a fair-price trade with no fee deduction. Their advertised ~0.9% fee is collected in the settlement step, which is not a swap and not captured by this benchmark. A near-zero value here does not mean Trojan is free — it means their fee is outside the on-chain scope this benchmark measures. Trojan's displayed value reflects gas only."
- q: "Why does pump.fun show near-zero?"
a: "Two factors combine. First, trades with no Mobula platform tag are assigned to the pump-fun row — this includes MEV bots, snipers, and untagged scripts that pay no platform fee, pulling the pump-fun median toward gas-only. Second, pump.fun's bonding-curve fee is embedded in the output token amount rather than a discrete SOL or USDC transfer to an identifiable wallet, so it is not captured by on-chain fee parsing. PumpSwap (the AMM for graduated tokens) does charge explicit protocol and creator fees as on-chain transfers — these are captured when they appear in tagged trades. The unattributed-to-pump-fun assignment rule is a known limitation; a dedicated Unattributed bucket is on the roadmap."
- q: "Why does pump.fun show a low fee?"
a: "pump.fun trades are identified via the poolType field in Mobula's trades-enriched API: poolType=pumpfun for bonding-curve swaps and poolType=pumpswap for post-migration AMM swaps. PumpSwap charges explicit protocol and creator fees as on-chain SOL or USDC transfers — these are captured. The bonding-curve fee (pre-migration) is embedded in the output token amount, not a discrete transfer to an identifiable wallet, so it is not captured. Since August 7 2026, pump.fun cut bonding-curve trading fees to zero, making the bonding-curve row gas-only by design. The low displayed value reflects PumpSwap protocol fees on graduated tokens."

prometheus:
window: 24h
Expand Down
6 changes: 5 additions & 1 deletion harnesses/memecoin-platforms/cmd/monitor/main.go
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,11 @@ func runPoll(mobulaClient, rpcClient, heliusClient *http.Client, heliusKey, apiK
}
p := t.Platform
if p == "" {
p = "unattributed"
if t.isPumpFunNative() {
p = "pump-fun"
} else {
p = "unattributed"
}
}
s := byPlatform[p]
if s == nil {
Expand Down
7 changes: 7 additions & 0 deletions harnesses/memecoin-platforms/cmd/monitor/mobula.go
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,13 @@ type MobulaTrade struct {
Hash string `json:"hash"`
Sender string `json:"sender"`
AmountUSD float64 `json:"amountUSD"`
PoolType string `json:"poolType"`
}

// isPumpFunNative returns true for trades on pump.fun's bonding curve or
// PumpSwap AMM (post-migration). Uses poolType field from token/trades-enriched.
func (t *MobulaTrade) isPumpFunNative() bool {
return t.PoolType == "pumpfun" || t.PoolType == "pumpswap"
}

type mobulaTradesResp struct {
Expand Down
Loading