Skip to content

Commit 04e6469

Browse files
authored
Merge branch 'DefiLlama:main' into main
2 parents 0a1be61 + 87ead2c commit 04e6469

File tree

1,264 files changed

+39120
-15520
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,264 files changed

+39120
-15520
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jobs:
66
runs-on: ubuntu-latest
77
steps:
88
- id: file_changes
9-
uses: trilom/file-changes-action@v1.2.4
9+
uses: trilom/file-changes-action@ce38c8ce2459ca3c303415eec8cb0409857b4272
1010
with:
1111
output: 'json'
1212
fileOutput: 'json'
@@ -15,7 +15,6 @@ jobs:
1515
- name: Run changes files through test script
1616
env:
1717
LLAMA_DEBUG_MODE: "true"
18-
BSC_RPC: https://rpc.ankr.com/bsc,https://bsc-dataseed4.binance.org
1918
run: |
2019
RUN_FILES=$(
2120
MODIFIED=${{ steps.file_changes.outputs.files_modified}} \

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@ historical-data.js
77
/.idea
88
yarn.lock
99
.DS_Store
10-
.vscode
10+
.vscode
11+
projects/binance/data.csv
12+
13+
*.log

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Also, don't hesitate to send a message on [our discord](https://discord.defillam
99
1010
1. PLEASE PLEASE **enable "Allow edits by maintainers" while putting up the PR.**
1111
2. Once your adapter has been merged, it takes time to show on the UI. No need to notify us on Discord.
12-
3. TVL must be computed from blockchain data (reason: https://github.com/DefiLlama/DefiLlama-Adapters/discussions/432), if you have trouble with creating a the adapter, please hop onto our discord, we are happy to assist you.
12+
3. TVL must be computed from blockchain data (reason: https://github.com/DefiLlama/DefiLlama-Adapters/discussions/432), if you have trouble with creating the adapter, please hop onto our discord, we are happy to assist you.
1313
4. **For updating listing info** It is a different repo, you can find your listing in this file: https://github.com/DefiLlama/defillama-server/blob/master/defi/src/protocols/data2.ts, you can edit it there and put up a PR
1414
5. Do not edit/push `package-lock.json` file as part of your changes, we use lockfileVersion 2, and most use v1 and using that messes up our CI
1515
6. No need to go to our discord and announce that you've created a PR, we monitor all PRs and will review it asap
@@ -20,7 +20,7 @@ Please send answers to questions there https://github.com/DefiLlama/DefiLlama-Ad
2020

2121
## Work in progress
2222

23-
This is a work in progress. The goal is to eventually handle historical data. DefiLlama aims to be transparent, accurate and open source.
23+
This is a work in progress. DefiLlama aims to be transparent, accurate, and open source.
2424

2525
If you have any suggestions, want to contribute or want to chat, please join [our discord](https://discord.defillama.com/) and drop a message.
2626

@@ -29,6 +29,8 @@ If you have any suggestions, want to contribute or want to chat, please join [ou
2929
node test.js projects/pangolin/index.js
3030
# Add a timestamp at the end to run the adapter at a historical timestamp
3131
node test.js projects/aave/v3.js 1729080692
32+
# or using YYYY-MM-DD
33+
node test.js projects/aave/v3.js 2024-10-16
3234
```
3335

3436
## Changing RPC providers
@@ -39,7 +41,7 @@ BSC_RPC="..."
3941
POLYGON_RPC="..."
4042
```
4143

42-
The name of each rpc is `{CHAIN-NAME}_RPC`, and the name we use for each chain can be found [here](https://github.com/DefiLlama/defillama-sdk/blob/master/src/providers.json)
44+
The name of each rpc is `{CHAIN-NAME}_RPC`, and the name we use for each chain can be found [here](https://unpkg.com/@defillama/sdk@latest/build/providers.json). If you run into issues with a chain make sure to update the sdk with `npm update @defillama/sdk`.
4345

4446
## Adapter rules
45-
- Never add extra npm packages, if you need a chain-level package for your chain, ask us and we'll consider it, but we can't accept any npm package that is project-specific
47+
- Never add extra npm packages, if you need a chain-level package for your chain, ask us, and we'll consider it, but we can't accept any npm package that is project-specific

add_enquiry.md

Lines changed: 0 additions & 11 deletions
This file was deleted.

bun.lockb

-145 KB
Binary file not shown.

env.sample

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# do not edit this file
2+
13
ETHEREUM_RPC=https://eth-mainnet.gateway.pokt.network/v1/5f3453978e354ab992c4da79
24
CNDL_RPC=https://rpc.cndlchain.com
35
BSC_RPC=https://bsc-dataseed4.binance.org
@@ -21,3 +23,6 @@ KLAYTN_RPC=https://public-node-api.klaytnapi.com/v1/cypress
2123
FINDORA_RPC=https://prod-mainnet.prod.findora.org:8545
2224
SOLANA_RPC=https://solana-api.projectserum.com
2325
NOVA_RPC=http://dataseed-0.rpc.novanetwork.io:8545/
26+
BERACHAIN_RPC=https://rpc.berachain.com
27+
28+
# do not edit this file

funding.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"opRetro": {
3+
"projectId": "0xae07bfec2c3c90937679f8c8c5c32e80407c09903aa03d1b5e5a075e67592b86"
4+
}
5+
}

liquidations/aave-v3/index.ts

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
import * as sdk from "@defillama/sdk";
2+
import { gql, request } from "graphql-request";
3+
import { Liq } from "../utils/types";
4+
import { getPagedGql } from "../utils/gql";
5+
6+
const query = gql`
7+
query users($lastId: String, $pageSize: Int) {
8+
accounts(
9+
first: $pageSize
10+
where: {id_gt: $lastId, openPositionCount_gt: 0, borrows_: {amountUSD_gt: "0"}}
11+
) {
12+
borrows: positions(where: {balance_gt: "0", side: BORROWER, timestampClosed: null}) {
13+
balance
14+
_eMode
15+
asset {
16+
symbol
17+
name
18+
decimals
19+
lastPriceUSD
20+
}
21+
}
22+
collateral: positions(where: {balance_gt: "0", side: COLLATERAL, timestampClosed: null}) {
23+
balance
24+
_eMode
25+
asset {
26+
symbol
27+
name
28+
decimals
29+
lastPriceUSD
30+
}
31+
}
32+
id
33+
}
34+
}`;
35+
36+
interface User {
37+
id: string;
38+
borrows: {
39+
emode: boolean;
40+
balance: string;
41+
asset: {
42+
name: string;
43+
symbol: string;
44+
decimals: number;
45+
lastPriceUSD: string;
46+
};
47+
}[];
48+
collateral: {
49+
emode: boolean;
50+
balance: string;
51+
asset: {
52+
symbol: string;
53+
name: string;
54+
decimals: number;
55+
lastPriceUSD: string;
56+
};
57+
isCollateral: boolean;
58+
}[];
59+
}[];
60+
61+
enum Chains {
62+
ethereum = "ethereum",
63+
arbitrum = "arbitrum",
64+
base = "base",
65+
polygon = "polygon",
66+
}
67+
68+
type AaveAdapterResource = {
69+
name: "aave";
70+
chain: Chains;
71+
usdcAddress: string;
72+
subgraphUrl: string;
73+
explorerBaseUrl: string;
74+
};
75+
76+
const rc: { [chain in Chains]: AaveAdapterResource } = {
77+
[Chains.ethereum]: {
78+
name: "aave",
79+
chain: Chains.ethereum,
80+
usdcAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
81+
subgraphUrl: sdk.graph.modifyEndpoint('JCNWRypm7FYwV8fx5HhzZPSFaMxgkPuw4TnR3Gpi81zk'), // Messari AAVE v3
82+
explorerBaseUrl: "https://etherscan.io/address/",
83+
},
84+
[Chains.arbitrum]: {
85+
name: "aave",
86+
chain: Chains.arbitrum,
87+
usdcAddress: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
88+
subgraphUrl: sdk.graph.modifyEndpoint('4xyasjQeREe7PxnF6wVdobZvCw5mhoHZq3T7guRpuNPf'), // Messari AAVE v3
89+
explorerBaseUrl: "https://arbiscan.io/address/",
90+
},
91+
[Chains.polygon]: {
92+
name: "aave",
93+
chain: Chains.polygon,
94+
usdcAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
95+
subgraphUrl: sdk.graph.modifyEndpoint('6yuf1C49aWEscgk5n9D1DekeG1BCk5Z9imJYJT3sVmAT'),
96+
explorerBaseUrl: "https://polygonscan.com/address/",
97+
},
98+
[Chains.base]: {
99+
name: "aave",
100+
chain: Chains.base,
101+
usdcAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
102+
subgraphUrl: sdk.graph.modifyEndpoint('D7mapexM5ZsQckLJai2FawTKXJ7CqYGKM8PErnS3cJi9'),
103+
explorerBaseUrl: "https://basescan.org/address/",
104+
}
105+
};
106+
107+
const LT: { [chain in Chains]: { [asset: string]: { normal: number, emode: number } } } = {
108+
[Chains.ethereum]: {},
109+
[Chains.polygon]: {},
110+
[Chains.arbitrum]: {},
111+
[Chains.base]: {},
112+
};
113+
114+
// Consider adding helper to derive live values from contracts; The subgraph does not contain emode LT values or categories
115+
const emodeCategories: { [chain in Chains]: { [symbol: string]: number } } = {
116+
[Chains.ethereum]: {
117+
// ETH Correlated
118+
"WETH": 0.95,
119+
"wstETH": 0.95,
120+
"weETH": 0.95,
121+
"osETH": 0.95,
122+
"rETH": 0.95,
123+
"ETHx": 0.95,
124+
"cbETH": 0.95,
125+
// sUSDe Stablecoins
126+
"USDT": 0.92,
127+
"USDC": 0.92,
128+
"USDS": 0.92,
129+
"sUSDe": 0.92,
130+
// rsETH LST Main
131+
"rsETH": 0.945,
132+
// LBTC / WBTC
133+
"LBTC": 0.86,
134+
"WBTC": 0.86,
135+
},
136+
[Chains.arbitrum]: {
137+
// ETH Correlated
138+
"WETH": 0.95,
139+
"wstETH": 0.95,
140+
"weETH": 0.95,
141+
// Stablecoins
142+
"USDT": 0.95,
143+
"USD₮0": 0.95,
144+
"USDC": 0.95,
145+
"USDC.e": 0.95,
146+
"DAI": 0.95,
147+
// ezETH wstETH
148+
"ezETH": 0.95,
149+
},
150+
[Chains.polygon]: {
151+
// ETH Correlated
152+
"WETH": 0.95,
153+
"wstETH": 0.95,
154+
"weETH": 0.95,
155+
"osETH": 0.95,
156+
"rETH": 0.95,
157+
"ETHx": 0.95,
158+
"cbETH": 0.95,
159+
// sUSDe Stablecoins
160+
"USDT": 0.92,
161+
"USDC": 0.92,
162+
"USDS": 0.92,
163+
"sUSDe": 0.92,
164+
// rsETH LST Main
165+
"rsETH": 0.945,
166+
// LBTC / WBTC
167+
"LBTC": 0.86,
168+
"WBTC": 0.86,
169+
},
170+
[Chains.base]: {
171+
// ETH Correlated
172+
"WETH": 0.93,
173+
"weETH": 0.93,
174+
"osETH": 0.93,
175+
"cbETH": 0.93,
176+
// ezETH wstETH
177+
"ezETH": 0.95,
178+
}
179+
};
180+
181+
const populateLT = async (chain: Chains) => {
182+
const subgraphUrl = rc[chain].subgraphUrl;
183+
const data = await request(subgraphUrl, gql`
184+
query {
185+
markets {
186+
inputToken {
187+
symbol
188+
}
189+
liquidationThreshold
190+
}
191+
}
192+
`);
193+
194+
data.markets.forEach((market: any) => {
195+
const symbol = market.inputToken.symbol;
196+
const liquidationThreshold = parseFloat(market.liquidationThreshold) / 100;
197+
const emodeThreshold = emodeCategories[chain][symbol] || null;
198+
LT[chain][symbol] = { normal: liquidationThreshold, emode: emodeThreshold };
199+
});
200+
};
201+
202+
const positions = (chain: Chains) => async () => {
203+
const explorerBaseUrl = rc[chain].explorerBaseUrl;
204+
const users = (await getPagedGql(rc[chain].subgraphUrl, query, "accounts")) as User[];
205+
206+
await populateLT(chain);
207+
208+
// Filter for active debt and remove users with no collateral, these should be accounted elsewhere as bad debt
209+
const debts = users
210+
.filter(user => user.collateral.length > 0)
211+
.filter(user => user.borrows.length > 0)
212+
.reduce((acc, user) => {
213+
const totalDebt = user.borrows.reduce((debts, b) => {
214+
const normalizedBalance = ((parseFloat(b.balance) / 10**b.asset.decimals) * parseFloat(b.asset.lastPriceUSD == null ? "0" : b.asset.lastPriceUSD)).toString();
215+
debts += parseFloat(normalizedBalance);
216+
return debts;
217+
}, 0);
218+
219+
const totalCollateral = user.collateral.reduce((collateral, c) => {
220+
const normalizedBalance = ((parseFloat(c.balance) / 10**c.asset.decimals) * parseFloat(c.asset.lastPriceUSD == null ? "0" : c.asset.lastPriceUSD));
221+
collateral += normalizedBalance;
222+
return collateral;
223+
}, 0);
224+
225+
// Early return for positions in liquidation range; Likely stale data or unprofitable to liquidate
226+
if (totalDebt >= totalCollateral) {
227+
return acc;
228+
};
229+
230+
const collateralWeights = user.collateral.map((c) => {
231+
const normalizedBalance = ((parseFloat(c.balance) / 10**c.asset.decimals) * parseFloat(c.asset.lastPriceUSD == null ? "0" : c.asset.lastPriceUSD)).toString();
232+
return parseFloat(normalizedBalance) / totalCollateral;
233+
}, [] as { weight: Number; asset: { name: string; symbol: string; decimals: number; lastPriceUSD: string; } }[]);
234+
235+
const weightedLT = user.collateral.reduce((lt, c) => {
236+
const normalizedBalance = ((parseFloat(c.balance) / 10**c.asset.decimals) * parseFloat(c.asset.lastPriceUSD == null ? "0" : c.asset.lastPriceUSD)).toString();
237+
LT[chain][c.asset.symbol] ? (lt += (parseFloat(normalizedBalance) / totalCollateral) * (c.emode ? LT[chain][c.asset.symbol].emode : LT[chain][c.asset.symbol].normal)) : console.log("No LT for ", c.asset.symbol);
238+
return lt;
239+
}, 0);
240+
241+
const priceImpact = totalDebt / totalCollateral / weightedLT;
242+
243+
// Return for positions in liquidation range; Likely stale data or unprofitable to liquidate
244+
if (weightedLT < totalDebt / totalCollateral) {
245+
return acc;
246+
} else {
247+
acc.push(...user.collateral.map((collateral, i) => {
248+
return {
249+
owner: user.id,
250+
liqPrice: parseFloat(collateral.asset.lastPriceUSD == null ? "0" : collateral.asset.lastPriceUSD) * priceImpact * collateralWeights[i],
251+
collateral: collateral.asset.symbol,
252+
collateralAmount: collateral.balance,
253+
extra: {
254+
url: explorerBaseUrl + user.id,
255+
},
256+
} as Liq;
257+
})
258+
);
259+
};
260+
return acc;
261+
}, [] as Liq[]).flat();
262+
return debts;
263+
};
264+
265+
module.exports = {
266+
ethereum: {
267+
liquidations: positions(Chains.ethereum),
268+
},
269+
polygon: {
270+
liquidations: positions(Chains.polygon),
271+
},
272+
base: {
273+
liquidations: positions(Chains.base),
274+
},
275+
arbitrum: {
276+
liquidations: positions(Chains.arbitrum),
277+
},
278+
};

0 commit comments

Comments
 (0)