From 306941d8a40c5dfbd98063fd1209d7fa7d682ab7 Mon Sep 17 00:00:00 2001 From: pavel Date: Wed, 1 Oct 2025 10:12:02 +0300 Subject: [PATCH 1/5] add tvl for mstable v2 --- projects/mstable-v2/abis.js | 10 +++++++++ projects/mstable-v2/config.js | 10 +++++++++ projects/mstable-v2/index.js | 42 +++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 projects/mstable-v2/abis.js create mode 100644 projects/mstable-v2/config.js create mode 100644 projects/mstable-v2/index.js diff --git a/projects/mstable-v2/abis.js b/projects/mstable-v2/abis.js new file mode 100644 index 0000000000..eaaedec363 --- /dev/null +++ b/projects/mstable-v2/abis.js @@ -0,0 +1,10 @@ +const DHEDGE_FACTORY_ABI = + "function getManagedPools(address manager) view returns (address[] managedPools)"; + +const MSTABLE_POOL_ABI = + "function getFundSummary() view returns (tuple(string name, uint256 totalSupply, uint256 totalFundValue))"; + +module.exports = { + DHEDGE_FACTORY_ABI, + MSTABLE_POOL_ABI, +}; diff --git a/projects/mstable-v2/config.js b/projects/mstable-v2/config.js new file mode 100644 index 0000000000..ed3c8c6ab9 --- /dev/null +++ b/projects/mstable-v2/config.js @@ -0,0 +1,10 @@ +const CONFIG_DATA = { + ethereum: { + dhedgeFactory: "0x96d33bcf84dde326014248e2896f79bbb9c13d6d", + mstableManager: "0x3dd46846eed8D147841AE162C8425c08BD8E1b41", + }, +}; + +module.exports = { + CONFIG_DATA, +}; diff --git a/projects/mstable-v2/index.js b/projects/mstable-v2/index.js new file mode 100644 index 0000000000..d5378870f6 --- /dev/null +++ b/projects/mstable-v2/index.js @@ -0,0 +1,42 @@ +const {CONFIG_DATA} = require("./config"); +const {DHEDGE_FACTORY_ABI, MSTABLE_POOL_ABI} = require("./abis"); + + +async function tvl(api) { + const { chain, } = api + const { dhedgeFactory, mstableManager } = CONFIG_DATA[chain]; + + const pools = await api.call({ + abi: DHEDGE_FACTORY_ABI, + target: dhedgeFactory, + params: [mstableManager], + }); + + const poolSummariesRes = await api.multiCall({ + abi: MSTABLE_POOL_ABI, + calls: pools, + permitFailure: true + }); + + const poolSummaries = poolSummariesRes.filter(i => i && i.totalFundValue !== null && i.totalFundValue !== undefined); + + const totalValue = poolSummaries.reduce( + (acc, i) => acc + +i.totalFundValue, + 0 + ); + + return { + tether: totalValue / 1e18, + }; +} + +module.exports = { + misrepresentedTokens: true, + start: '2025-08-12', // Friday, August 8, 2025 12:00:00 AM + methodology: + "Aggregates total value of each mStable vaults on Ethereum", + ethereum: { + tvl, + }, + +}; From 2c97ec5cae99773c0afd6aff4c3585e3d3811f87 Mon Sep 17 00:00:00 2001 From: pavel Date: Tue, 7 Oct 2025 13:33:23 +0300 Subject: [PATCH 2/5] return assets balances for funds --- projects/mstable-v2/abis.js | 10 ++++--- projects/mstable-v2/index.js | 52 +++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/projects/mstable-v2/abis.js b/projects/mstable-v2/abis.js index eaaedec363..8cb2f380c9 100644 --- a/projects/mstable-v2/abis.js +++ b/projects/mstable-v2/abis.js @@ -1,10 +1,14 @@ const DHEDGE_FACTORY_ABI = "function getManagedPools(address manager) view returns (address[] managedPools)"; -const MSTABLE_POOL_ABI = - "function getFundSummary() view returns (tuple(string name, uint256 totalSupply, uint256 totalFundValue))"; +const DHEDGE_POOL_LOGIC_ABI = + "function poolManagerLogic() view returns (address)"; + +const MSTABLE_POOL_MANAGER_LOGIC_ABI = + "function getFundComposition() view returns (tuple(address asset, bool isDeposit)[] assets, uint256[] balances)"; module.exports = { DHEDGE_FACTORY_ABI, - MSTABLE_POOL_ABI, + DHEDGE_POOL_LOGIC_ABI, + MSTABLE_POOL_MANAGER_LOGIC_ABI, }; diff --git a/projects/mstable-v2/index.js b/projects/mstable-v2/index.js index d5378870f6..620406193f 100644 --- a/projects/mstable-v2/index.js +++ b/projects/mstable-v2/index.js @@ -1,8 +1,9 @@ const {CONFIG_DATA} = require("./config"); -const {DHEDGE_FACTORY_ABI, MSTABLE_POOL_ABI} = require("./abis"); +const {DHEDGE_FACTORY_ABI, DHEDGE_POOL_LOGIC_ABI, MSTABLE_POOL_MANAGER_LOGIC_ABI} = require("./abis"); +const sdk = require("@defillama/sdk"); -async function tvl(api) { +async function getLockedAssetsForFunds(api) { const { chain, } = api const { dhedgeFactory, mstableManager } = CONFIG_DATA[chain]; @@ -12,22 +13,47 @@ async function tvl(api) { params: [mstableManager], }); - const poolSummariesRes = await api.multiCall({ - abi: MSTABLE_POOL_ABI, + const poolManagerLogicAddresses = await api.multiCall({ + abi: DHEDGE_POOL_LOGIC_ABI, calls: pools, permitFailure: true }); - const poolSummaries = poolSummariesRes.filter(i => i && i.totalFundValue !== null && i.totalFundValue !== undefined); + const fundCompositions = await api.multiCall({ + abi: MSTABLE_POOL_MANAGER_LOGIC_ABI, + calls: poolManagerLogicAddresses, + permitFailure: true + }); + + return fundCompositions.map(composition => { + return composition.assets.reduce( + (lockedTokens, [address], i) => ({ ...lockedTokens, [address]: composition.balances[i] }), + {}, + ) + }) +} + + +async function tvlForChain(api) { + const { chain, } = api + const isEthereum = chain === 'ethereum'; + + const assetBalances = await getLockedAssetsForFunds(api); + + const lockedBalances = {}; + + assetBalances + .forEach((locked) => Object.entries(locked) + .map(([underlying, balance]) => ( + [isEthereum ? underlying : `${chain}:${underlying}`, balance] + )) + .forEach(([address, balance]) => + sdk.util.sumSingleBalance(lockedBalances, address, balance) + ) + ); - const totalValue = poolSummaries.reduce( - (acc, i) => acc + +i.totalFundValue, - 0 - ); + return lockedBalances; - return { - tether: totalValue / 1e18, - }; } module.exports = { @@ -36,7 +62,7 @@ module.exports = { methodology: "Aggregates total value of each mStable vaults on Ethereum", ethereum: { - tvl, + tvl: tvlForChain, }, }; From b67963b17c509e5001987d3ce1d5dd7830858e87 Mon Sep 17 00:00:00 2001 From: pavel Date: Thu, 9 Oct 2025 12:20:55 +0300 Subject: [PATCH 3/5] add tracking aave v3 positions --- projects/mstable-v2/abis.js | 12 ++++++++++ projects/mstable-v2/config.js | 2 ++ projects/mstable-v2/index.js | 44 ++++++++++++++++++++++++++++------- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/projects/mstable-v2/abis.js b/projects/mstable-v2/abis.js index 8cb2f380c9..a2e90768fc 100644 --- a/projects/mstable-v2/abis.js +++ b/projects/mstable-v2/abis.js @@ -7,8 +7,20 @@ const DHEDGE_POOL_LOGIC_ABI = const MSTABLE_POOL_MANAGER_LOGIC_ABI = "function getFundComposition() view returns (tuple(address asset, bool isDeposit)[] assets, uint256[] balances)"; +const AAVE_GET_RESERVE_DATA = + "function getReserveData(address asset) view returns (((uint256 data) configuration, uint128 liquidityIndex, uint128 currentLiquidityRate, uint128 variableBorrowIndex, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, uint16 id, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint128 accruedToTreasury, uint128 unbacked, uint128 isolationModeTotalDebt))"; + +const AAVE_GET_RESERVES_LIST = "address[]:getReservesList"; + +const AAVE_GET_USER_RESERVE_DATA = + "function getUserReserveData(address asset, address user) view returns (uint256 currentATokenBalance, uint256 currentStableDebt, uint256 currentVariableDebt, uint256 principalStableDebt, uint256 scaledVariableDebt, uint256 stableBorrowRate, uint256 liquidityRate, uint40 stableRateLastUpdated, bool usageAsCollateralEnabled)"; + + module.exports = { DHEDGE_FACTORY_ABI, DHEDGE_POOL_LOGIC_ABI, MSTABLE_POOL_MANAGER_LOGIC_ABI, + AAVE_GET_RESERVE_DATA, + AAVE_GET_RESERVES_LIST, + AAVE_GET_USER_RESERVE_DATA }; diff --git a/projects/mstable-v2/config.js b/projects/mstable-v2/config.js index ed3c8c6ab9..6cfaf5b6d9 100644 --- a/projects/mstable-v2/config.js +++ b/projects/mstable-v2/config.js @@ -2,6 +2,8 @@ const CONFIG_DATA = { ethereum: { dhedgeFactory: "0x96d33bcf84dde326014248e2896f79bbb9c13d6d", mstableManager: "0x3dd46846eed8D147841AE162C8425c08BD8E1b41", + aavePool: '0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2', + aavePoolDataProvider: '0x7B4EB56E7CD4b454BA8ff71E4518426369a138a3', }, }; diff --git a/projects/mstable-v2/index.js b/projects/mstable-v2/index.js index 620406193f..fa41cbdc61 100644 --- a/projects/mstable-v2/index.js +++ b/projects/mstable-v2/index.js @@ -1,11 +1,18 @@ const {CONFIG_DATA} = require("./config"); -const {DHEDGE_FACTORY_ABI, DHEDGE_POOL_LOGIC_ABI, MSTABLE_POOL_MANAGER_LOGIC_ABI} = require("./abis"); -const sdk = require("@defillama/sdk"); +const { + DHEDGE_FACTORY_ABI, + DHEDGE_POOL_LOGIC_ABI, + MSTABLE_POOL_MANAGER_LOGIC_ABI, + AAVE_GET_RESERVES_LIST, + AAVE_GET_RESERVE_DATA, + AAVE_GET_USER_RESERVE_DATA +} = require("./abis"); +const {sumTokens2} = require("../helper/unwrapLPs"); async function getLockedAssetsForFunds(api) { const { chain, } = api - const { dhedgeFactory, mstableManager } = CONFIG_DATA[chain]; + const { dhedgeFactory, mstableManager, aavePool, aavePoolDataProvider } = CONFIG_DATA[chain]; const pools = await api.call({ abi: DHEDGE_FACTORY_ABI, @@ -13,6 +20,8 @@ async function getLockedAssetsForFunds(api) { params: [mstableManager], }); + await processAaveTvl(pools, api, aavePool, aavePoolDataProvider); + const poolManagerLogicAddresses = await api.multiCall({ abi: DHEDGE_POOL_LOGIC_ABI, calls: pools, @@ -33,26 +42,45 @@ async function getLockedAssetsForFunds(api) { }) } +async function processAaveTvl(aaveVaults, api, AAVE_POOL, AAVE_POOL_DATA_PROVIDER) { + if (aaveVaults.length === 0 || !AAVE_POOL || !AAVE_POOL_DATA_PROVIDER) return + + const aaveReservesList = await api.call({ abi: AAVE_GET_RESERVES_LIST, target: AAVE_POOL }); + + const aaveReserveDetails = await api.multiCall({ abi: AAVE_GET_RESERVE_DATA, target: AAVE_POOL, calls: aaveReservesList }); + + const aaveQueryParams = []; + aaveReservesList.forEach(asset => aaveVaults.forEach(vault => aaveQueryParams.push({ params: [asset, vault], }))); + const aavePositions = await api.multiCall({ abi: AAVE_GET_USER_RESERVE_DATA, target: AAVE_POOL_DATA_PROVIDER, calls: aaveQueryParams }); + + for (const i in aavePositions) { + const aavePosition = aavePositions[i]; + const reserveIdx = aaveReservesList.findIndex(x => x === aaveQueryParams[i].params[0]); + + api.addToken(aaveReserveDetails[reserveIdx].aTokenAddress, aavePosition.currentATokenBalance); + api.addToken(aaveReserveDetails[reserveIdx].stableDebtTokenAddress, aavePosition.currentStableDebt); + api.addToken(aaveReserveDetails[reserveIdx].variableDebtTokenAddress, aavePosition.currentVariableDebt); + } + +} + async function tvlForChain(api) { const { chain, } = api const isEthereum = chain === 'ethereum'; const assetBalances = await getLockedAssetsForFunds(api); - - const lockedBalances = {}; - assetBalances .forEach((locked) => Object.entries(locked) .map(([underlying, balance]) => ( [isEthereum ? underlying : `${chain}:${underlying}`, balance] )) .forEach(([address, balance]) => - sdk.util.sumSingleBalance(lockedBalances, address, balance) + api.addToken(address, balance) ) ); - return lockedBalances; + return sumTokens2({ api }); } From 8f34cdf77ee043862a8885020c8a325ca251136a Mon Sep 17 00:00:00 2001 From: pavel Date: Thu, 9 Oct 2025 21:52:36 +0300 Subject: [PATCH 4/5] add checking not null --- projects/mstable-v2/index.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/projects/mstable-v2/index.js b/projects/mstable-v2/index.js index fa41cbdc61..49340f1ffd 100644 --- a/projects/mstable-v2/index.js +++ b/projects/mstable-v2/index.js @@ -35,10 +35,12 @@ async function getLockedAssetsForFunds(api) { }); return fundCompositions.map(composition => { - return composition.assets.reduce( - (lockedTokens, [address], i) => ({ ...lockedTokens, [address]: composition.balances[i] }), - {}, - ) + if (composition.assets) { + return composition.assets.reduce( + (lockedTokens, [address], i) => ({...lockedTokens, [address]: composition.balances[i]}), + {}, + ) + } }) } From 23ed256ce503e9b2366cbedbd7b162aee679d54a Mon Sep 17 00:00:00 2001 From: pavel Date: Fri, 10 Oct 2025 18:47:34 +0300 Subject: [PATCH 5/5] fix not null --- projects/mstable-v2/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/mstable-v2/index.js b/projects/mstable-v2/index.js index 49340f1ffd..5e562924c0 100644 --- a/projects/mstable-v2/index.js +++ b/projects/mstable-v2/index.js @@ -35,7 +35,7 @@ async function getLockedAssetsForFunds(api) { }); return fundCompositions.map(composition => { - if (composition.assets) { + if (composition && composition.assets) { return composition.assets.reduce( (lockedTokens, [address], i) => ({...lockedTokens, [address]: composition.balances[i]}), {},