Skip to content

Commit f44a5a5

Browse files
treeoflife2ZNSCTO
andauthored
CheapGM add missing chains (#4569)
* Create index.ts fees calculation * Update index.ts * Update index.ts * Update index.ts added new chains and updated methodology of Income Statement * Update index.ts * Update index.ts Added tx-scan fallback to avoid 0s when historical getBalance is unavailable; still reporting net inflow * Update index.ts * Update index.ts * refactor cheapgm --------- Co-authored-by: ZNSCTO <[email protected]>
1 parent 01d3e5f commit f44a5a5

File tree

1 file changed

+239
-16
lines changed

1 file changed

+239
-16
lines changed

fees/cheapgm.ts

Lines changed: 239 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,260 @@
1-
2-
import { CHAIN } from "../helpers/chains";
31
import { Adapter, FetchOptions } from "../adapters/types";
2+
import { CHAIN } from "../helpers/chains";
43

5-
const TREASURY = "0x21ad6eF3979638d8e73747f22B92C4AadE145D82";
4+
const TREASURY = "0x21ad6ef3979638d8e73747f22b92c4aade145d82".toLowerCase();
65

76
const CHAINS: Array<string> = [
87
CHAIN.ETHEREUM, CHAIN.BASE, CHAIN.OPTIMISM, CHAIN.ARBITRUM, CHAIN.POLYGON, CHAIN.BSC,
9-
CHAIN.SCROLL, CHAIN.MANTLE, CHAIN.LINEA, CHAIN.ERA, CHAIN.TAIKO, CHAIN.BLAST, CHAIN.MODE, CHAIN.ZORA, CHAIN.METIS,
10-
CHAIN.CRONOS, CHAIN.CELO, CHAIN.CONFLUX, CHAIN.RONIN, CHAIN.LISK, CHAIN.BERACHAIN, CHAIN.CORE, CHAIN.BOB,
11-
CHAIN.ABSTRACT, CHAIN.SONEIUM, CHAIN.INK, CHAIN.UNICHAIN, CHAIN.PLUME, CHAIN.SONIC,
8+
CHAIN.SCROLL, CHAIN.MANTLE, CHAIN.LINEA, CHAIN.ERA, CHAIN.TAIKO, CHAIN.BLAST, CHAIN.MODE,
9+
CHAIN.ZORA, CHAIN.METIS, CHAIN.REDSTONE, CHAIN.XDAI, CHAIN.APECHAIN, CHAIN.XLAYER, CHAIN.BOTANIX,
10+
CHAIN.CRONOS, CHAIN.CELO, CHAIN.CONFLUX, CHAIN.RONIN, CHAIN.LISK, CHAIN.BERACHAIN, CHAIN.CORE,
11+
CHAIN.BOB, CHAIN.ZIRCUIT, CHAIN.MORPH, CHAIN.MANTA, CHAIN.ANCIENT8, CHAIN.TAIKO,
12+
CHAIN.POLYGON_ZKEVM, CHAIN.WC, CHAIN.KLAYTN, CHAIN.ABSTRACT, CHAIN.SONEIUM, CHAIN.INK,
13+
CHAIN.UNICHAIN, CHAIN.PLUME, CHAIN.SONIC
1214
]
1315

14-
async function fetch(options: FetchOptions) {
15-
const dailyFees = options.createBalances();
16+
const COUNTERS: Record<string, string[]> = {
17+
[CHAIN.BASE]: [
18+
"0x8fc7aa44971a7b111017fc435ef6daf10bf1b887",
19+
"0x8ccd9c0a9c084412416a85fd748c7f1e9b86442d",
20+
],
21+
[CHAIN.LINEA]: [
22+
"0xc11ee6c94a86e18481d9206c29ecdd3b40c59898",
23+
"0x0246d65ba41da3db6db55e489146eb25ca3634e5",
24+
],
25+
[CHAIN.SCROLL]: [
26+
"0x064dacc2f126f036d77cd4b8887efedb2f5201fe",
27+
"0x53092f84ef2460d8517f011f7722125758de5aa2",
28+
],
29+
[CHAIN.MANTLE]: [
30+
"0xc11ee6c94a86e18481d9206c29ecdd3b40c59898",
31+
"0x0246d65ba41da3db6db55e489146eb25ca3634e5",
32+
],
33+
[CHAIN.CRONOS]: [
34+
"0xc11ee6c94a86e18481d9206c29ecdd3b40c59898",
35+
"0x0246d65ba41da3db6db55e489146eb25ca3634e5",
36+
],
37+
[CHAIN.CELO]: [
38+
"0xc11ee6c94a86e18481d9206c29ecdd3b40c59898",
39+
"0x0246d65ba41da3db6db55e489146eb25ca3634e5",
40+
],
41+
[CHAIN.BSC]: [
42+
"0xc11ee6c94a86e18481d9206c29ecdd3b40c59898",
43+
"0x0246d65ba41da3db6db55e489146eb25ca3634e5",
44+
],
45+
[CHAIN.ABSTRACT]: [
46+
"0xe94158b16cd46b190f74a2ccbff7fdecf0da8bf4",
47+
"0xefb45cd4cff4d11d4b029659e618daacd8d18f3",
48+
],
49+
[CHAIN.KLAYTN]: [
50+
"0x5fcea004bc26308bc91d8599dba4a271c57cba85",
51+
"0x72fe6c968d0da46f45e65923330a262a1f75963c",
52+
],
53+
[CHAIN.BERACHAIN]: [
54+
"0x2522bfee6451f7a1f64e3ab287d8cf46c173601f",
55+
"0x9cad0d6a8927cb0757f435b8e5ecb6b095862596",
56+
],
57+
[CHAIN.OPTIMISM]: [
58+
"0xc11ee6c94a86e18481d9206c29ecdd3b40c59898",
59+
"0x0246d65ba41da3db6db55e489146eb25ca3634e5",
60+
],
61+
[CHAIN.UNICHAIN]: [
62+
"0x30efc910a135d73016a788fdd9a9e8b022dea208",
63+
"0xff4e5275f5b1b69e94773fa4134be4c752c42705",
64+
],
65+
[CHAIN.INK]: [
66+
"0x3033d7ded400547d6442c55159da5c61f2721633",
67+
"0x63c489d31a2c3de0638360931f47ff066282473f",
68+
],
69+
[CHAIN.SONEIUM]: [
70+
"0x6baaa0653e53f92e11316973bfc1fc8291fc6f58",
71+
"0xdefe1db2713ba0c51334343dca576bd5f4e793b2",
72+
],
73+
[CHAIN.BOB]: [
74+
"0xc11ee6c94a86e18481d9206c29ecdd3b40c59898",
75+
"0x0246d65ba41da3db6db55e489146eb25ca3634e5",
76+
],
77+
[CHAIN.PLUME]: [
78+
"0x86683f28df33adcd1cadc815855102c1685731fc",
79+
"0x6e126d13a5451780401804f55cec3686192d29f7",
80+
],
81+
[CHAIN.CONFLUX]: [
82+
"0x649617c710776c6ac41be36eda94929654a685a7",
83+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
84+
],
85+
[CHAIN.LISK]: [
86+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
87+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
88+
],
89+
[CHAIN.ZIRCUIT]: [
90+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
91+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
92+
],
93+
[CHAIN.METIS]: [
94+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
95+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
96+
],
97+
[CHAIN.ARBITRUM]: [
98+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
99+
"0x6c8de6c102a844b885291d1ce1cafdacf0a553d8",
100+
],
101+
[CHAIN.AVAX]: [
102+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
103+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
104+
],
105+
[CHAIN.SONIC]: [
106+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
107+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
108+
],
109+
[CHAIN.XDAI]: [
110+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
111+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
112+
],
113+
[CHAIN.TAIKO]: [
114+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
115+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
116+
],
117+
[CHAIN.APECHAIN]: [
118+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
119+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
120+
],
121+
[CHAIN.BLAST]: [
122+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
123+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
124+
],
125+
[CHAIN.ANCIENT8]: [
126+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
127+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
128+
],
129+
[CHAIN.BOTANIX]: [
130+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
131+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
132+
],
133+
[CHAIN.ZORA]: [
134+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
135+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
136+
],
137+
[CHAIN.XLAYER]: [
138+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
139+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
140+
],
141+
[CHAIN.MORPH]: [
142+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
143+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
144+
],
145+
[CHAIN.MANTA]: [
146+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
147+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
148+
],
149+
[CHAIN.CORE]: [
150+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
151+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
152+
],
153+
[CHAIN.REDSTONE]: [
154+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
155+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
156+
],
157+
// [CHAIN.XAI]: [
158+
// "0xf617d89a811a39f06f5271f89db346a0ae297f71",
159+
// "0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
160+
// ],
161+
[CHAIN.POLYGON_ZKEVM]: [
162+
"0xf617d89a811a39f06f5271f89db346a0ae297f71",
163+
"0x2f96d7dd813b8e17071188791b78ea3fab5c109c",
164+
],
165+
};
166+
167+
const abis = {
168+
GMSent: "event GMSent(address indexed sender, address indexed referral)",
169+
fee: "function fee() view returns (uint256)",
170+
referralFees: "function referralFees() view returns (uint256)",
171+
};
172+
173+
function toBig(v: any): bigint {
174+
try {
175+
if (v == null) return 0n;
176+
if (typeof v === "bigint") return v;
177+
if (typeof v === "number") return BigInt(Math.trunc(v));
178+
if (typeof v === "string") return v.startsWith("0x") ? BigInt(v) : BigInt(v);
179+
} catch { }
180+
return 0n;
181+
}
182+
183+
async function computeGrossByLogs(opts: FetchOptions, chainSlug: string): Promise<bigint> {
184+
const counters = COUNTERS[chainSlug];
185+
if (!counters?.length) return 0n;
186+
187+
const from_block = (opts as any).fromBlock;
188+
const to_block = (opts as any).toBlock;
189+
const BASIS = 10000n;
190+
let total = 0n;
16191

17-
const balanceStart = await options.fromApi.provider.getBalance(TREASURY);
18-
const balanceEnd = await options.toApi.provider.getBalance(TREASURY);
192+
for (const counter of counters) {
193+
const logs = (await opts.getLogs({
194+
target: counter,
195+
fromBlock: from_block,
196+
toBlock: to_block,
197+
eventAbi: abis.GMSent,
198+
entireLog: true,
199+
}).catch(() => [])) as any[];
19200

20-
dailyFees.addGasToken(balanceEnd - balanceStart)
201+
if (!logs.length) continue;
21202

22-
return {
23-
dailyFees,
24-
dailyRevenue: dailyFees,
203+
const [feeWei, refBpRaw] = await Promise.all([
204+
(opts as any).api.call({ target: counter, abi: abis.fee, block: to_block }).catch(() => 0),
205+
(opts as any).api.call({ target: counter, abi: abis.referralFees, block: to_block }).catch(() => 0),
206+
]);
207+
const fee = toBig(feeWei);
208+
const refBP = toBig(refBpRaw);
209+
210+
let withRef = 0n, noRef = 0n;
211+
for (const e of logs) {
212+
const ref = e?.args?.referral ?? e?.args?.[1] ?? "0x0000000000000000000000000000000000000000";
213+
const isZero = typeof ref === "string" ? /^0x0{40}$/i.test(ref) : (!ref);
214+
if (isZero) noRef += 1n; else withRef += 1n;
215+
}
216+
const perWithRef = fee * (BASIS - refBP) / BASIS;
217+
total += fee * noRef + perWithRef * withRef;
25218
}
219+
return total > 0n ? total : 0n;
220+
}
221+
222+
223+
async function computeNetByBalance(options: FetchOptions): Promise<bigint> {
224+
try {
225+
const [balStart, balEnd] = await Promise.all([
226+
options.fromApi.provider.getBalance(TREASURY),
227+
options.toApi.provider.getBalance(TREASURY)
228+
]);
229+
const delta = toBig(balEnd) - toBig(balStart);
230+
return delta > 0n ? delta : 0n;
231+
} catch { return 0n; }
26232
}
27233

234+
235+
const fetch = async (options: FetchOptions) => {
236+
const dailyFees = options.createBalances();
237+
238+
let gross = 0n;
239+
try { gross = await computeGrossByLogs(options, options.chain); } catch { }
240+
if (gross > 0n) {
241+
dailyFees.addGasToken(gross);
242+
return { dailyFees, dailyRevenue: dailyFees };
243+
}
244+
245+
const net = await computeNetByBalance(options);
246+
if (net > 0n) dailyFees.addGasToken(net);
247+
return { dailyFees, dailyRevenue: dailyFees };
248+
};
249+
28250
const adapter: Adapter = {
29251
version: 2,
30252
fetch,
253+
start: "2025-08-11",
31254
chains: CHAINS,
32255
methodology: {
33-
Fees: "Daily net increase in treasury address balance in each chain's native token (net inflow)",
34-
Revenue: "All fees are revenue.",
256+
Fees: "fees from GMCounter logs: if referral is set, fee x (1 - referralFees/BPS), otherwise full fee.",
257+
Revenue: "fees accrue to protocol treasury. If no GMCounter address provided for a chain, fallback is treasury net inflow for that chain/day.",
35258
},
36259
};
37260

0 commit comments

Comments
 (0)