Skip to content

Commit

Permalink
Merge pull request #2036 from GainsNetwork-org/master
Browse files Browse the repository at this point in the history
[Gains Network | gTrade] Update fees/volume stats
  • Loading branch information
dtmkeng authored Oct 23, 2024
2 parents 13e247b + 92e7fe8 commit 74843dd
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 262 deletions.
181 changes: 15 additions & 166 deletions dexs/gains-network/index.ts
Original file line number Diff line number Diff line change
@@ -1,174 +1,23 @@
import { FetchResultVolume, SimpleAdapter } from "../../adapters/types";
import { ChainBlocks, FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types";
import { CHAIN } from "../../helpers/chains";
import { Chain } from "@defillama/sdk/build/general";
import { queryDune } from "../../helpers/dune";

type IAddresses = {
[s: string | Chain]: string[];
};

type IPrecisionException = {
[chain in CHAIN]?: {
[key: string | number]: number;
};
};

interface ILog {
address: string;
data: string;
topics: string[];
interface IStats {
unix_ts: number;
day: string;
blockchain: string;
daily_volume: number;
}

const V8_LIMIT_TOPIC0 = "0xc10f67c0e22c53149183a414c16a62334103432a2c48b839a057cd9bd5fdeb99";
const V8_MARKET_TOPIC0 = "0xbbd5cfa7b4ec0d44d4155fcaad32af9cf7e65799d6b8b08f233b930de7bcd9a8";

const topic0_limit_ex = [
"0x1ab0771256522e5114b583b488c490436d6f8fe02b1e1c9697443e8704c4e840", // v5-v6
"0xa97091b8c54bf9d1906c2a06322d0ea74fedde4538cdcdf95d81d0ffdca41857", // v7
V8_LIMIT_TOPIC0, // v8
];
const topic0_market_ex = [
"0x2739a12dffae5d66bd9e126a286078ed771840f2288f0afa5709ce38c3330997", // v5-v6
"0xca42b0e44cd853d207b87e8f8914eaefef9c9463a8c77ca33754aa62f6904f00", // v7
V8_MARKET_TOPIC0, // v8
];
const topic0_partials = [
"0xf09a9c949c4bd4cbe75b424bea11c683c3ae55e7cdb8321c3ec37e01af72c8d5", // PositionSizeIncreaseExecuted
"0xe74b50af866d7f8e3577bc959bf73a2690841f0abce22ab0cfb1b1c84122a7d7", // PositionSizeDecreaseExecuted
];

const precisionException: IPrecisionException = {
[CHAIN.POLYGON]: {
"0x2ac6749d0affd42c8d61ef25e433f92e375a1aef": 1e6,
"0x4542256c583bcad66a19a525b57203773a6485bf": 1e6,
3: 1e6, // v8 USDC
},
[CHAIN.ARBITRUM]: {
"0x2ac6749d0affd42c8d61ef25e433f92e375a1aef": 1e6,
"0x4542256c583bcad66a19a525b57203773a6485bf": 1e6,
3: 1e6, // v8 USDC
},
[CHAIN.BASE]: {
1: 1e6, // USDC is collateralIndex 1 on Base
},
};

const diamonds = {
[CHAIN.POLYGON]: "0x209a9a01980377916851af2ca075c2b170452018",
[CHAIN.ARBITRUM]: "0xff162c694eaa571f685030649814282ea457f169",
[CHAIN.BASE]: "0x6cD5aC19a07518A8092eEFfDA4f1174C72704eeb",
};

const contract_addresses: IAddresses = {
[CHAIN.POLYGON]: [
"0x82e59334da8c667797009bbe82473b55c7a6b311", // DAI TradingCallbacks
"0x0bbed2eac3237ba128643670b7cf3be475933755", // ETH TradingCallbacks
"0x2ac6749d0affd42c8d61ef25e433f92e375a1aef", // USDC TradingCallbacks
diamonds[CHAIN.POLYGON], // v8 Diamond
],
[CHAIN.ARBITRUM]: [
"0x298a695906e16aea0a184a2815a76ead1a0b7522", // DAI TradingCallbacks
"0x62a9f50c92a57c719ff741133caa55c7a81ce019", // ETH TradingCallbacks
"0x4542256c583bcad66a19a525b57203773a6485bf", // USDC TradingCallbacks
diamonds[CHAIN.ARBITRUM], // v8 Diamond
],
[CHAIN.BASE]: [diamonds[CHAIN.BASE]],
};

const fetch: any = async (timestamp: number, _, { getLogs, chain }): Promise<FetchResultVolume> => {
const chainPrecisionExceptions = precisionException[chain];
const [limitLogs, marketLogs, partialsLogs] = (
await Promise.all([
// Limit Executed logs
(await Promise.all(
topic0_limit_ex.map(async (topic0) =>
getLogs({
targets: contract_addresses[chain],
topics: [topic0],
})
)
)) as ILog[][],

// Market Executed logs
(await Promise.all(
topic0_market_ex.map(async (topic0) =>
getLogs({
targets: contract_addresses[chain],
topics: [topic0],
})
)
)) as ILog[][],

// Partial Increase/Decrease logs
(await Promise.all(
topic0_partials.map(async (topic0) =>
getLogs({
targets: [diamonds[chain]],
topics: [topic0],
})
)
)) as ILog[][],
])
).map((logs: ILog[][]) => logs.flat());

const limit_volume = limitLogs
.map((e: ILog) => {
const data = e.data.replace("0x", "");

// v8
if (e.topics[0] === V8_LIMIT_TOPIC0) {
const leverage = Number("0x" + data.slice(320, 384)) / 1e3;
const collateralIndex = Number("0x" + data.slice(512, 576));
const collateralAmount = Number("0x" + data.slice(640, 704)) / (chainPrecisionExceptions[collateralIndex] ?? 1e18);
const collateralPriceUsd = Number("0x" + data.slice(1280, 1344)) / 1e8;
return leverage * collateralAmount * collateralPriceUsd;
} else {
// v5-v7
const leverage = Number("0x" + data.slice(512, 576));
const positionSizeDai = Number("0x" + data.slice(896, 960)) / (chainPrecisionExceptions[e.address] ?? 1e18);
const collateralPrice = (data.length === 1216 ? Number("0x" + data.slice(1088, 1152)) : 1e8) / 1e8;
return leverage * positionSizeDai * collateralPrice;
}
})
.reduce((a: number, b: number) => a + b, 0);

const market_volume = marketLogs
.map((e: ILog) => {
const data = e.data.replace("0x", "");
// v8
if (e.topics[0] === V8_MARKET_TOPIC0) {
const leverage = Number("0x" + data.slice(320, 384)) / 1e3;
const collateralIndex = Number("0x" + data.slice(512, 576));
const collateralAmount = Number("0x" + data.slice(640, 704)) / (chainPrecisionExceptions[collateralIndex] ?? 1e18);
const collateralPriceUsd = Number("0x" + data.slice(1280, 1344)) / 1e8;
return leverage * collateralAmount * collateralPriceUsd;
} else {
// v5-v7
const leverage = Number("0x" + data.slice(448, 512));
const positionSizeDai = Number("0x" + data.slice(832, 896)) / (chainPrecisionExceptions[e.address] ?? 1e18);
const collateralPrice = (data.length === 1088 ? Number("0x" + data.slice(1024, 1088)) : 1e8) / 1e8;
return leverage * positionSizeDai * collateralPrice;
}
})
.reduce((a: number, b: number) => a + b, 0);

const partials_volume = partialsLogs
.map((e: ILog) => {
const data = e.data.replace("0x", "");
const cancelReason = Number("0x" + data.slice(128, 192));

if (cancelReason > 0) return 0;

const collateralPrecision = chainPrecisionExceptions[Number(e.topics[1])] ?? 1e18;
const collateralPriceUsd = Number("0x" + data.slice(384, 448)) / 1e8;
const positionSizeDelta = Number("0x" + data.slice(576, 640)) / collateralPrecision;

return positionSizeDelta * collateralPriceUsd;
})
.reduce((a: number, b: number) => a + b, 0);

const dailyVolume = limit_volume + market_volume + partials_volume;
const fetch: any = async (
timestamp: number,
_: ChainBlocks,
{ chain, startOfDay, toTimestamp }: FetchOptions
): Promise<FetchResultVolume> => {
const stats: IStats[] = await queryDune("4192496", { start: startOfDay, end: toTimestamp });
const chainStat = stats.find((stat) => stat.unix_ts === startOfDay && stat.blockchain === chain);

return { dailyVolume, timestamp };
return { timestamp, dailyVolume: chainStat?.daily_volume || 0 };
};

const adapter: SimpleAdapter = {
Expand Down
139 changes: 43 additions & 96 deletions fees/gains-network.ts
Original file line number Diff line number Diff line change
@@ -1,119 +1,66 @@
import { Adapter, ChainBlocks, FetchOptions, FetchResultFees } from "../adapters/types";
import { CHAIN } from "../helpers/chains";
import ADDRESSES from "../helpers/coreAssets.json";
import { Chain } from "@defillama/sdk/build/general";
import { queryDune } from "../helpers/dune";

type IAddresses = {
[s: string | Chain]: string[];
};

const event: string[] = [
"event DevGovFeeCharged(address indexed trader, uint valueDai)",
"event SssFeeCharged(address indexed trader, uint valueDai)",
"event ReferralFeeCharged(address indexed trader, uint valueDai)",
"event NftBotFeeCharged(address indexed trader, uint valueDai)",
"event DaiVaultFeeCharged(address indexed trader, uint valueDai)",
"event LpFeeCharged(address indexed trader, uint valueDai)",
"event TriggerFeeCharged(address indexed trader, uint valueDai)",
"event GovFeeCharged(address indexed trader, uint valueDai, bool distributed)",
"event BorrowingFeeCharged(address indexed trader, uint tradeValueDai, uint valueDai)",
];

const eventV8: string[] = [
"event GovFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)",
"event ReferralFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)",
"event TriggerFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)",
"event GnsStakingFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)",
"event GTokenFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)",
"event BorrowingFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)",
];

// Pre-v8
const addressConfig: { [a: string]: string } = {
"0x82e59334da8c667797009bbe82473b55c7a6b311": ADDRESSES.polygon.DAI,
"0x0bbed2eac3237ba128643670b7cf3be475933755": ADDRESSES.polygon.WETH,
"0x2ac6749d0affd42c8d61ef25e433f92e375a1aef": ADDRESSES.polygon.USDC_CIRCLE,
"0x298a695906e16aea0a184a2815a76ead1a0b7522": ADDRESSES.arbitrum.DAI,
"0x62a9f50c92a57c719ff741133caa55c7a81ce019": ADDRESSES.arbitrum.WETH,
"0x4542256c583bcad66a19a525b57203773a6485bf": ADDRESSES.arbitrum.USDC_CIRCLE,
};

// Post-v8
const collateralIndexMap: { [s: string | Chain]: { [a: number]: string } } = {
[CHAIN.POLYGON]: { 1: ADDRESSES.polygon.DAI, 2: ADDRESSES.polygon.WETH, 3: ADDRESSES.polygon.USDC_CIRCLE },
[CHAIN.ARBITRUM]: { 1: ADDRESSES.arbitrum.DAI, 2: ADDRESSES.arbitrum.WETH, 3: ADDRESSES.arbitrum.USDC_CIRCLE },
[CHAIN.BASE]: { 1: ADDRESSES.base.USDC },
};

const contract_addresses: IAddresses = {
[CHAIN.POLYGON]: [
"0x82e59334da8c667797009bbe82473b55c7a6b311", // DAI TradingCallbacks
"0x0bbed2eac3237ba128643670b7cf3be475933755", // ETH TradingCallbacks
"0x2ac6749d0affd42c8d61ef25e433f92e375a1aef", // USDC TradingCallbacks
"0x209a9a01980377916851af2ca075c2b170452018", // v8 Diamond
],
[CHAIN.ARBITRUM]: [
"0x298a695906e16aea0a184a2815a76ead1a0b7522", // DAI TradingCallbacks
"0x62a9f50c92a57c719ff741133caa55c7a81ce019", // ETH TradingCallbacks
"0x4542256c583bcad66a19a525b57203773a6485bf", // USDC TradingCallbacks
"0xff162c694eaa571f685030649814282ea457f169", // v8 Diamond
],
[CHAIN.BASE]: [
"0x6cD5aC19a07518A8092eEFfDA4f1174C72704eeb", // v9.3 Diamond
],
};

const fetch = (chain: Chain) => {
return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs }: FetchOptions): Promise<FetchResultFees> => {
const collateralIndexToToken = collateralIndexMap[chain];
const dailyFees = createBalances();
const dailyRevenue = createBalances();
const dailyHoldersRevenue = createBalances();
interface IStats {
unix_ts: number;
day: string;
blockchain: string;
daily_volume: number;

for (const target of contract_addresses[chain]) {
const token = addressConfig[target];
// Fees
project_fund: number;
dev_fund: number; // deprecated; only used for older entries
referral: number;
nft_bots: number;
all_fees: number;
borrowing_fee: number;
rollover_fee: number;

// pre-v8
if (token) {
const [devFee, ssFee, referralFee, nftBotFee, daiVault, lpFee, triggerFee, govFee, borrowingFee]: any = await Promise.all(
event.map((eventAbi) => getLogs({ target, eventAbi }))
);
// gTokens
dai_stakers: number;
usdc_stakers: number;
weth_stakers: number;

[devFee, ssFee, referralFee, nftBotFee, daiVault, lpFee, triggerFee, govFee, borrowingFee]
.flat()
.forEach((i: any) => dailyFees.add(token, i.valueDai));
[devFee, ssFee, govFee].flat().forEach((i: any) => dailyRevenue.add(token, i.valueDai));
ssFee.forEach((i: any) => dailyHoldersRevenue.add(token, i.valueDai));
} else {
// v8
const [govFee, referralFee, triggerFee, stakingFee, gTokenFee, borrowingFee]: any = await Promise.all(
eventV8.map((eventAbi) => getLogs({ target, eventAbi }))
);
// GNS staking
gns_stakers: number;
}

[govFee, referralFee, triggerFee, stakingFee, gTokenFee, borrowingFee]
.flat()
.forEach((i: any) => dailyFees.add(collateralIndexToToken[i.collateralIndex], i.amountCollateral));
[govFee, stakingFee].flat().forEach((i: any) => dailyRevenue.add(collateralIndexToToken[i.collateralIndex], i.amountCollateral));
stakingFee.forEach((i: any) => dailyHoldersRevenue.add(collateralIndexToToken[i.collateralIndex], i.amountCollateral));
}
}
const fetch = async (timestamp: number, _: ChainBlocks, { chain, startOfDay, toTimestamp }: FetchOptions): Promise<FetchResultFees> => {
const stats: IStats[] = await queryDune("4192496", { start: startOfDay, end: toTimestamp });
const chainStat = stats.find((stat) => stat.unix_ts === startOfDay && stat.blockchain === chain);
const [dailyFees, dailyRevenue, dailyHoldersRevenue, dailySupplySideRevenue, totalFees] = chainStat
? [
chainStat.all_fees,
chainStat.dev_fund + chainStat.project_fund + chainStat.gns_stakers,
chainStat.gns_stakers,
chainStat.dai_stakers + chainStat.usdc_stakers + chainStat.weth_stakers,
chainStat.all_fees + chainStat.rollover_fee + chainStat.borrowing_fee,
]
: [0, 0, 0, 0, 0];

return { timestamp, dailyFees, dailyRevenue, dailyHoldersRevenue };
return {
timestamp,
dailyFees,
dailyRevenue,
dailyHoldersRevenue,
dailySupplySideRevenue,
totalFees,
};
};

const adapter: Adapter = {
adapter: {
[CHAIN.POLYGON]: {
fetch: fetch(CHAIN.POLYGON),
fetch: fetch,
start: 1654214400,
},
[CHAIN.ARBITRUM]: {
fetch: fetch(CHAIN.ARBITRUM),
fetch: fetch,
start: 1672358400,
},
[CHAIN.BASE]: {
fetch: fetch(CHAIN.BASE),
fetch: fetch,
start: 1727351131,
},
},
Expand Down

0 comments on commit 74843dd

Please sign in to comment.