Skip to content

Commit b465343

Browse files
authored
add pancakeswap, shadow, bluefin, rocketpool (#109)
* pancakeswap * Shadow Exchange * remove clever because it do have emissions * add bluefin * add rocketpool * rocketpool use get rocket storage instead of hardcoded so we can backfill emission data * rocketpool abi * fluid * stakewise maple
1 parent 17ace52 commit b465343

File tree

16 files changed

+937
-1
lines changed

16 files changed

+937
-1
lines changed

adapters/fluid/abi.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const abi = {
2+
factoryAbi: {
3+
LogVestingStarted: "event LogVestingStarted(address indexed recipient, address indexed vesting, address owner, uint256 amount)",
4+
},
5+
vestingContractAbi: {
6+
vestingBegin: "function vestingBegin() external view returns (uint32)",
7+
vestingCliff: "function vestingCliff() external view returns (uint32)",
8+
vestingEnd: "function vestingEnd() external view returns (uint32)",
9+
vestingAmount: "function vestingAmount() external view returns (uint256)"
10+
}
11+
};
12+
13+
export default abi;

adapters/fluid/index.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { getLogs, lookupBlock } from "@defillama/sdk/build/util";
2+
import { multiCall } from "@defillama/sdk/build/abi/abi2";
3+
import abi from "./abi";
4+
import { LinearAdapterResult } from "../../types/adapters";
5+
6+
const FACTORY_ADDRESS = "0x3b05a5295Aa749D78858E33ECe3b97bB3Ef4F029";
7+
const FLUID_TOKEN = "0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb";
8+
9+
export default async function adapter(): Promise<LinearAdapterResult[]> {
10+
const logs = await getLogs({
11+
target: FACTORY_ADDRESS,
12+
topic: "0x4ac20a376998e094ddc7f2886aacc04793f0967d837b03bcfea523a8f27f2485",
13+
topics: [],
14+
fromBlock: 12602043,
15+
toBlock: 12782627,
16+
keys: [],
17+
chain: "ethereum",
18+
});
19+
20+
21+
const vestingContracts: { vesting: string; amount: number }[] = [];
22+
logs.output.map((log: any) => {
23+
if (log.topics[0] !== "0x4ac20a376998e094ddc7f2886aacc04793f0967d837b03bcfea523a8f27f2485") {
24+
return;
25+
}
26+
vestingContracts.push({
27+
vesting: `0x${log.topics[2].substring(26)}`,
28+
amount: log.data / 1e18
29+
});
30+
});
31+
32+
const [beginTimes, cliffTimes, endTimes, amounts] = await Promise.all([
33+
multiCall({
34+
calls: vestingContracts.map(v => ({
35+
target: v.vesting
36+
})),
37+
abi: abi.vestingContractAbi.vestingBegin,
38+
chain: "ethereum"
39+
}),
40+
multiCall({
41+
calls: vestingContracts.map(v => ({
42+
target: v.vesting
43+
})),
44+
abi: abi.vestingContractAbi.vestingCliff,
45+
chain: "ethereum"
46+
}),
47+
multiCall({
48+
calls: vestingContracts.map(v => ({
49+
target: v.vesting
50+
})),
51+
abi: abi.vestingContractAbi.vestingEnd,
52+
chain: "ethereum"
53+
}),
54+
multiCall({
55+
calls: vestingContracts.map(v => ({
56+
target: v.vesting
57+
})),
58+
abi: abi.vestingContractAbi.vestingAmount,
59+
chain: "ethereum"
60+
})
61+
]);
62+
63+
return vestingContracts.map((_, i) => ({
64+
type: "linear" as const,
65+
token: FLUID_TOKEN,
66+
start: Number(beginTimes[i]),
67+
end: Number(endTimes[i]),
68+
cliff: Number(cliffTimes[i]),
69+
amount: Number(amounts[i]) / 1e18
70+
}));
71+
}

adapters/pancakeswap/abi.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
const abi = {
2+
cakeRateToRegularFarm: {
3+
inputs: [],
4+
name: "cakeRateToRegularFarm",
5+
outputs: [{ name: "", type: "uint256" }],
6+
stateMutability: "view",
7+
type: "function"
8+
},
9+
cakeRateToSpecialFarm: {
10+
inputs: [],
11+
name: "cakeRateToSpecialFarm",
12+
outputs: [{ name: "", type: "uint256" }],
13+
stateMutability: "view",
14+
type: "function"
15+
},
16+
MASTERCHEF_CAKE_PER_BLOCK: {
17+
inputs: [],
18+
name: "MASTERCHEF_CAKE_PER_BLOCK",
19+
outputs: [{ name: "", type: "uint256" }],
20+
stateMutability: "view",
21+
type: "function"
22+
},
23+
CAKE_RATE_TOTAL_PRECISION: {
24+
inputs: [],
25+
name: "CAKE_RATE_TOTAL_PRECISION",
26+
outputs: [{ name: "", type: "uint256" }],
27+
stateMutability: "view",
28+
type: "function"
29+
},
30+
poolLength: {
31+
inputs: [],
32+
name: "poolLength",
33+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
34+
stateMutability: "view",
35+
type: "function"
36+
},
37+
cakePerBlock: {
38+
inputs: [{ name: "_isRegular", type: "bool" }],
39+
name: "cakePerBlock",
40+
outputs: [{ name: "amount", type: "uint256" }],
41+
stateMutability: "view",
42+
type: "function"
43+
},
44+
totalRegularAllocPoint: {
45+
inputs: [],
46+
name: "totalRegularAllocPoint",
47+
outputs: [{ name: "", type: "uint256" }],
48+
stateMutability: "view",
49+
type: "function"
50+
},
51+
totalSpecialAllocPoint: {
52+
inputs: [],
53+
name: "totalSpecialAllocPoint",
54+
outputs: [{ name: "", type: "uint256" }],
55+
stateMutability: "view",
56+
type: "function"
57+
},
58+
// Pool info
59+
poolInfo: {
60+
inputs: [{ name: "", type: "uint256" }],
61+
name: "poolInfo",
62+
outputs: [
63+
{ name: "accCakePerShare", type: "uint256" },
64+
{ name: "lastRewardBlock", type: "uint256" },
65+
{ name: "allocPoint", type: "uint256" },
66+
{ name: "totalBoostedShare", type: "uint256" },
67+
{ name: "isRegular", type: "bool" }
68+
],
69+
stateMutability: "view",
70+
type: "function"
71+
},
72+
lpToken: {
73+
inputs: [{ name: "", type: "uint256" }],
74+
name: "lpToken",
75+
outputs: [{ name: "", type: "address" }],
76+
stateMutability: "view",
77+
type: "function"
78+
}
79+
};
80+
81+
const CONSTANTS = {
82+
MASTERCHEF_CAKE_PER_BLOCK: "40000000000000000000", // 40 CAKE per block
83+
CAKE_RATE_TOTAL_PRECISION: "1000000000000"
84+
};
85+
86+
export default abi;
87+
export { CONSTANTS };

adapters/pancakeswap/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import adapter from "./masterchef";
2+
3+
const MASTERCHEF_V2 = "0xa5f8C5Dbd5F286960b9d90548680aE5ebFf07652";
4+
5+
export const pancakeRegular = adapter(MASTERCHEF_V2, "bsc", true);
6+
export const pancakeSpecial = adapter(MASTERCHEF_V2, "bsc", false);

adapters/pancakeswap/masterchef.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { call, multiCall } from "@defillama/sdk/build/abi/abi2";
2+
import { AdapterResult } from "../../types/adapters";
3+
import abi, { CONSTANTS } from "./abi";
4+
5+
const BLOCKS_PER_DAY = 28800; // approximate number of blocks per day (assuming 3s block time)
6+
const ONE_YEAR = 365 * 24 * 60 * 60;
7+
const DECIMALS = 18;
8+
const CAKE_TOKEN = "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82";
9+
10+
export default function adapter(target: string, chain: string, isRegular: boolean) {
11+
return async function calculateEmissions(): Promise<AdapterResult[]> {
12+
try {
13+
const poolLength = await call({
14+
target,
15+
abi: abi.poolLength,
16+
chain,
17+
});
18+
19+
const [cakeRateToRegularFarm, cakeRateToSpecialFarm, masterPerBlock, ratePrecision, totalAlloc] = await Promise.all([
20+
call({
21+
target,
22+
abi: abi.cakeRateToRegularFarm,
23+
chain,
24+
}),
25+
call({
26+
target,
27+
abi: abi.cakeRateToSpecialFarm,
28+
chain,
29+
}),
30+
call({
31+
target,
32+
abi: abi.MASTERCHEF_CAKE_PER_BLOCK,
33+
chain,
34+
}).catch(() => CONSTANTS.MASTERCHEF_CAKE_PER_BLOCK),
35+
call({
36+
target,
37+
abi: abi.CAKE_RATE_TOTAL_PRECISION,
38+
chain,
39+
}).catch(() => CONSTANTS.CAKE_RATE_TOTAL_PRECISION),
40+
call({
41+
target,
42+
abi: isRegular ? abi.totalRegularAllocPoint : abi.totalSpecialAllocPoint,
43+
chain,
44+
}),
45+
]);
46+
47+
const netEmissionRate = BigInt(masterPerBlock) *
48+
BigInt(isRegular ? cakeRateToRegularFarm : cakeRateToSpecialFarm) /
49+
BigInt(ratePrecision);
50+
51+
const poolIndexes = Array.from({ length: Number(poolLength) }, (_, i) => i);
52+
53+
const [poolInfos, lpTokens] = await Promise.all([
54+
multiCall({
55+
calls: poolIndexes.map(pid => ({
56+
target,
57+
params: [pid],
58+
})),
59+
abi: abi.poolInfo,
60+
chain,
61+
permitFailure: true,
62+
}),
63+
multiCall({
64+
calls: poolIndexes.map(pid => ({
65+
target,
66+
params: [pid],
67+
})),
68+
abi: abi.lpToken,
69+
chain,
70+
permitFailure: true,
71+
}),
72+
]);
73+
74+
const results: AdapterResult[] = [];
75+
const now = Math.floor(Date.now() / 1000);
76+
77+
for (let pid = 0; pid < poolLength; pid++) {
78+
const poolInfo = poolInfos[pid];
79+
const lpToken = lpTokens[pid];
80+
81+
if (!poolInfo || !lpToken) continue;
82+
if (poolInfo.allocPoint === "0") continue;
83+
if (poolInfo.isRegular !== isRegular) continue;
84+
85+
if (BigInt(totalAlloc) === BigInt(0)) continue;
86+
87+
const poolEmissionWei = BigInt(poolInfo.allocPoint) *
88+
BigInt(BLOCKS_PER_DAY) *
89+
netEmissionRate /
90+
BigInt(totalAlloc);
91+
92+
const dailyEmission = Number(poolEmissionWei) / (10 ** DECIMALS);
93+
const yearlyEmission = dailyEmission * 365;
94+
95+
results.push({
96+
type: "linear",
97+
start: now,
98+
end: now + ONE_YEAR,
99+
amount: yearlyEmission,
100+
receiver: lpToken,
101+
token: CAKE_TOKEN
102+
});
103+
}
104+
105+
return results;
106+
107+
} catch (error) {
108+
throw new Error(`Failed to fetch PancakeSwap ${isRegular ? "regular" : "special"} emissions: ${error}`);
109+
}
110+
};
111+
}

adapters/rocketpool/abi.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export default {
2+
getAddress: {
3+
"inputs": [{"type": "bytes32"}],
4+
"name": "getAddress",
5+
"outputs": [{"type": "address"}],
6+
"stateMutability": "view",
7+
"type": "function"
8+
},
9+
getRewardsClaimersPerc: {
10+
"inputs": [],
11+
"name": "getRewardsClaimersPerc",
12+
"outputs": [
13+
{ "name": "trustedNodePerc", "type": "uint256" },
14+
{ "name": "protocolPerc", "type": "uint256" },
15+
{ "name": "nodePerc", "type": "uint256" }
16+
],
17+
"stateMutability": "view",
18+
"type": "function"
19+
},
20+
getInflationIntervalRate: {
21+
"inputs": [],
22+
"name": "getInflationIntervalRate",
23+
"outputs": [{ "type": "uint256" }],
24+
"stateMutability": "view",
25+
"type": "function"
26+
},
27+
getInflationIntervalStartTime: {
28+
"inputs": [],
29+
"name": "getInflationIntervalStartTime",
30+
"outputs": [{ "type": "uint256" }],
31+
"stateMutability": "view",
32+
"type": "function"
33+
},
34+
getInflationIntervalTime: {
35+
"inputs": [],
36+
"name": "getInflationIntervalTime",
37+
"outputs": [{ "type": "uint256" }],
38+
"stateMutability": "view",
39+
"type": "function"
40+
},
41+
totalSupply: {
42+
"inputs": [],
43+
"name": "totalSupply",
44+
"outputs": [{ "type": "uint256" }],
45+
"stateMutability": "view",
46+
"type": "function"
47+
},
48+
getInflationCalcTime: {
49+
"inputs": [],
50+
"name": "getInflationCalcTime",
51+
"outputs": [{ "type": "uint256" }],
52+
"stateMutability": "view",
53+
"type": "function"
54+
}
55+
}

0 commit comments

Comments
 (0)