Skip to content

Commit 95c75a3

Browse files
feat(termmax): Add Aave vault APY calculations and improve vault retrieval efficiency
1 parent b400de8 commit 95c75a3

File tree

1 file changed

+183
-36
lines changed

1 file changed

+183
-36
lines changed

src/adaptors/termmax/index.js

Lines changed: 183 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ const sdk = require('@defillama/sdk');
33
const { default: BigNumber } = require('bignumber.js');
44
const { Interface } = require('ethers/lib/utils');
55

6+
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
7+
68
const EVENTS = {
79
V1: {
810
CreateVault:
@@ -277,40 +279,170 @@ async function getVaultV2Addresses(chain, blockNumber) {
277279
return addresses;
278280
}
279281

282+
async function getAaveVaultEffectiveApy({
283+
aavePool,
284+
apy,
285+
assetAddress,
286+
chain,
287+
poolAddress,
288+
vaultAddress,
289+
}) {
290+
const aToken = await sdk.api.abi
291+
.call({
292+
target: poolAddress,
293+
abi: 'address:aToken',
294+
chain,
295+
})
296+
.then((r) => r.output)
297+
.catch(() => NULL_ADDRESS);
298+
if (aToken === NULL_ADDRESS) return apy;
299+
300+
const [assetsInThirdPool, idle] = await Promise.all([
301+
sdk.api.abi
302+
.call({
303+
target: aToken,
304+
abi: {
305+
inputs: [{ type: 'address' }],
306+
name: 'balanceOf',
307+
outputs: [{ type: 'uint256' }],
308+
},
309+
params: [poolAddress],
310+
chain,
311+
})
312+
.then((r) => r.output),
313+
sdk.api.abi
314+
.call({
315+
target: assetAddress,
316+
abi: {
317+
inputs: [{ type: 'address' }],
318+
name: 'balanceOf',
319+
outputs: [{ type: 'uint256' }],
320+
},
321+
params: [poolAddress],
322+
chain,
323+
})
324+
.then((r) => r.output),
325+
]);
326+
327+
const idleFund = new BigNumber(assetsInThirdPool).plus(idle);
328+
if (idleFund.isZero()) return apy;
329+
330+
const passiveRatio = new BigNumber(assetsInThirdPool).div(idleFund);
331+
332+
const currentLiquidityRate = await sdk.api.abi
333+
.call({
334+
target: aavePool,
335+
abi: {
336+
inputs: [{ type: 'address' }],
337+
name: 'getReserveData',
338+
outputs: [
339+
{
340+
components: [
341+
{
342+
components: [{ type: 'uint256', name: 'data' }],
343+
name: 'configuration',
344+
type: 'tuple',
345+
},
346+
{ type: 'uint128', name: 'liquidityIndex' },
347+
{ type: 'uint128', name: 'currentLiquidityRate' },
348+
{ type: 'uint128', name: 'variableBorrowIndex' },
349+
{ type: 'uint128', name: 'currentVariableBorrowRate' },
350+
{ type: 'uint128', name: 'currentStableBorrowRate' },
351+
{ type: 'uint40', name: 'lastUpdateTimestamp' },
352+
{ type: 'uint16', name: 'id' },
353+
{ type: 'address', name: 'aTokenAddress' },
354+
{ type: 'address', name: 'stableDebtTokenAddress' },
355+
{ type: 'address', name: 'variableDebtTokenAddress' },
356+
{ type: 'address', name: 'interestRateStrategyAddress' },
357+
{ type: 'uint128', name: 'accruedToTreasury' },
358+
{ type: 'uint128', name: 'unbacked' },
359+
{ type: 'uint128', name: 'isolationModeTotalDebt' },
360+
],
361+
name: 'res',
362+
type: 'tuple',
363+
},
364+
],
365+
},
366+
params: [assetAddress],
367+
chain,
368+
})
369+
.then((r) => r.output.currentLiquidityRate);
370+
371+
const passiveApy = new BigNumber(currentLiquidityRate).div(
372+
new BigNumber(10).pow(27)
373+
);
374+
return new BigNumber(apy).plus(passiveApy.times(passiveRatio)).toNumber();
375+
}
376+
377+
async function getVaultEffectiveApy({
378+
apy,
379+
assetAddress,
380+
chain,
381+
chainId,
382+
poolAddress,
383+
vaultAddress,
384+
}) {
385+
const aavePool = await sdk.api.abi
386+
.call({
387+
target: poolAddress,
388+
abi: 'address:aavePool',
389+
chain,
390+
})
391+
.then((r) => r.output)
392+
.catch(() => NULL_ADDRESS);
393+
if (aavePool !== NULL_ADDRESS)
394+
return await getAaveVaultEffectiveApy({
395+
apy,
396+
assetAddress,
397+
chain,
398+
poolAddress,
399+
vaultAddress,
400+
aavePool,
401+
});
402+
403+
return apy;
404+
}
405+
280406
async function getVaultV2({ alias, chain, chainId, number, opportunities }) {
281407
const vaults = [];
282408

283409
const addresses = await getVaultV2Addresses(chain, number).then((addresses) =>
284410
addresses.filter((a) => !VAULT_BLACKLIST[chain].includes(a))
285411
);
286412
const calls = addresses.map((target) => ({ target }));
287-
const [apys, assets, decimalses, names, totalAssetses] = await Promise.all([
288-
sdk.api.abi.multiCall({
289-
chain,
290-
calls,
291-
abi: 'uint256:apy',
292-
}),
293-
sdk.api.abi.multiCall({
294-
chain,
295-
calls,
296-
abi: 'address:asset',
297-
}),
298-
sdk.api.abi.multiCall({
299-
chain,
300-
calls,
301-
abi: 'uint8:decimals',
302-
}),
303-
sdk.api.abi.multiCall({
304-
chain,
305-
calls,
306-
abi: 'string:name',
307-
}),
308-
sdk.api.abi.multiCall({
309-
chain,
310-
calls,
311-
abi: 'uint256:totalAssets',
312-
}),
313-
]);
413+
const [apys, assets, decimalses, names, totalAssetses, pools] =
414+
await Promise.all([
415+
sdk.api.abi.multiCall({
416+
chain,
417+
calls,
418+
abi: 'uint256:apy',
419+
}),
420+
sdk.api.abi.multiCall({
421+
chain,
422+
calls,
423+
abi: 'address:asset',
424+
}),
425+
sdk.api.abi.multiCall({
426+
chain,
427+
calls,
428+
abi: 'uint8:decimals',
429+
}),
430+
sdk.api.abi.multiCall({
431+
chain,
432+
calls,
433+
abi: 'string:name',
434+
}),
435+
sdk.api.abi.multiCall({
436+
chain,
437+
calls,
438+
abi: 'uint256:totalAssets',
439+
}),
440+
sdk.api.abi.multiCall({
441+
chain,
442+
calls,
443+
abi: 'address:pool',
444+
}),
445+
]);
314446

315447
const [assetNames, priceMap] = await Promise.all([
316448
sdk.api.abi.multiCall({
@@ -328,9 +460,19 @@ async function getVaultV2({ alias, chain, chainId, number, opportunities }) {
328460
const address = addresses[i];
329461
const assetAddress = assets.output[i].output;
330462

331-
const readableApy = new BigNumber(apys.output[i].output)
463+
let apy = new BigNumber(apys.output[i].output)
332464
.div(new BigNumber(10).pow(8))
333465
.toNumber();
466+
if (pools.output[i].output !== NULL_ADDRESS) {
467+
apy = await getVaultEffectiveApy({
468+
apy,
469+
assetAddress,
470+
chain,
471+
chainId,
472+
poolAddress: pools.output[i].output,
473+
vaultAddress: address,
474+
});
475+
}
334476
const tvlUsd = new BigNumber(totalAssetses.output[i].output)
335477
.div(new BigNumber(10).pow(decimalses.output[i].output))
336478
.times(priceMap.get(assetAddress) || 0)
@@ -347,7 +489,7 @@ async function getVaultV2({ alias, chain, chainId, number, opportunities }) {
347489
project: 'termmax',
348490
symbol: assetNames.output[i].output,
349491
tvlUsd,
350-
apyBase: readableApy,
492+
apyBase: apy,
351493
url: String(url),
352494
underlyingTokens: [assetAddress],
353495
poolMeta: names.output[i].output,
@@ -385,7 +527,7 @@ async function getVaultsOnChain(chain, chainId, alias) {
385527

386528
const tasks = [];
387529
{
388-
const task1 = async () => {
530+
const taskV1 = async () => {
389531
const vaultsV1 = await getVaultsV1({
390532
alias,
391533
chain,
@@ -395,10 +537,10 @@ async function getVaultsOnChain(chain, chainId, alias) {
395537
});
396538
for (const vault of vaultsV1) vaultsOnChain.push(vault);
397539
};
398-
tasks.push(task1());
540+
tasks.push(taskV1());
399541
}
400542
{
401-
const task2 = async () => {
543+
const taskV2 = async () => {
402544
const vaultsV2 = await getVaultV2({
403545
alias,
404546
chain,
@@ -408,7 +550,7 @@ async function getVaultsOnChain(chain, chainId, alias) {
408550
});
409551
for (const vault of vaultsV2) vaultsOnChain.push(vault);
410552
};
411-
tasks.push(task2());
553+
tasks.push(taskV2());
412554
}
413555
await Promise.all(tasks);
414556

@@ -417,11 +559,16 @@ async function getVaultsOnChain(chain, chainId, alias) {
417559

418560
async function apy() {
419561
const vaults = [];
562+
const tasks = [];
420563
for (const key of Object.keys(VAULTS)) {
421-
const { alias, chain, chainId } = VAULTS[key];
422-
const vaultsOnChain = await getVaultsOnChain(chain, chainId, alias);
423-
for (const vault of vaultsOnChain) vaults.push(vault);
564+
const task = async () => {
565+
const { alias, chain, chainId } = VAULTS[key];
566+
const vaultsOnChain = await getVaultsOnChain(chain, chainId, alias);
567+
for (const vault of vaultsOnChain) vaults.push(vault);
568+
};
569+
tasks.push(task());
424570
}
571+
await Promise.all(tasks);
425572
return vaults;
426573
}
427574

0 commit comments

Comments
 (0)