Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions projects/mstable-v2/abis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const DHEDGE_FACTORY_ABI =
"function getManagedPools(address manager) view returns (address[] managedPools)";

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)";

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
};
12 changes: 12 additions & 0 deletions projects/mstable-v2/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const CONFIG_DATA = {
ethereum: {
dhedgeFactory: "0x96d33bcf84dde326014248e2896f79bbb9c13d6d",
mstableManager: "0x3dd46846eed8D147841AE162C8425c08BD8E1b41",
aavePool: '0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2',
aavePoolDataProvider: '0x7B4EB56E7CD4b454BA8ff71E4518426369a138a3',
},
};

module.exports = {
CONFIG_DATA,
};
98 changes: 98 additions & 0 deletions projects/mstable-v2/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
const {CONFIG_DATA} = require("./config");
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, aavePool, aavePoolDataProvider } = CONFIG_DATA[chain];

const pools = await api.call({
abi: DHEDGE_FACTORY_ABI,
target: dhedgeFactory,
params: [mstableManager],
});

await processAaveTvl(pools, api, aavePool, aavePoolDataProvider);

const poolManagerLogicAddresses = await api.multiCall({
abi: DHEDGE_POOL_LOGIC_ABI,
calls: pools,
permitFailure: true
});

const fundCompositions = await api.multiCall({
abi: MSTABLE_POOL_MANAGER_LOGIC_ABI,
calls: poolManagerLogicAddresses,
permitFailure: true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The adapter doesnt run. When a call here fails (currently the third call) it returns null. Then the following map fails because there is no 'assets' on null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added checking for not null.C ould you please send the output of the adapter before merging the PR?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error in ethereum: TypeError: Cannot read properties of null (reading 'assets')
at /home/runner/work/DefiLlama-Adapters/DefiLlama-Adapters/projects/mstable-v2/index.js:38:25
at Array.map ()
at getLockedAssetsForFunds (/home/runner/work/DefiLlama-Adapters/DefiLlama-Adapters/projects/mstable-v2/index.js:37:29)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async tvlForChain (/home/runner/work/DefiLlama-Adapters/DefiLlama-Adapters/projects/mstable-v2/index.js:74:27)
at async getTvl (/home/runner/work/DefiLlama-Adapters/DefiLlama-Adapters/test.js:53:21)
at async /home/runner/work/DefiLlama-Adapters/DefiLlama-Adapters/test.js:172:11
at async Promise.all (index 0)
at async Promise.all (index 3)
at async /home/runner/work/DefiLlama-Adapters/DefiLlama-Adapters/test.js:198:3

https://github.com/DefiLlama/DefiLlama-Adapters/actions/runs/18386046228/job/52384618140?pr=16500#step:4:62

});

return fundCompositions.map(composition => {
if (composition && composition.assets) {
return composition.assets.reduce(
(lockedTokens, [address], i) => ({...lockedTokens, [address]: composition.balances[i]}),
{},
)
}
})
}

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);
assetBalances
.forEach((locked) => Object.entries(locked)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same issue around undefined array elements here in assetBalances. Does this run successfully when you use test.js locally?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, its worging fine locally. parameres: projects/mstable-v2/index.js
ETHEREUM_RPC=https://eth-mainnet.gateway.pokt.network/v1/5f3453978e354ab992c4da79
result:
2025-10-14_11-46-55

.map(([underlying, balance]) => (
[isEthereum ? underlying : `${chain}:${underlying}`, balance]
))
.forEach(([address, balance]) =>
api.addToken(address, balance)
)
);

return sumTokens2({ api });

}

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: tvlForChain,
},

};
Loading