Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
291a61d
Turtle Club Treasury & TVL
Ralphy105 Apr 29, 2025
bfc23e0
Added Solidly NFTs to treasury adapter
Ralphy105 May 7, 2025
6986802
add/change treasury assets
Ralphy105 May 7, 2025
6e9bc5a
Erc721 fixes and add exception tokens
Ralphy105 May 12, 2025
9f94653
asset changes (now hits 7.44m/7.74m)
Ralphy105 May 12, 2025
6168376
asset recommenting
Ralphy105 May 12, 2025
562e2b2
update assets
Ralphy105 May 12, 2025
61a57d7
Merge branch 'main' into main
Ralphy105 May 12, 2025
c2f2c3c
Add eUSDC-2 and Morpho
Ralphy105 May 13, 2025
bd7e666
price usdc2 at usdc
Ralphy105 May 13, 2025
90588a4
Merge branch 'main' of https://github.com/turtle-dao/DefiLlama-Adapters
Ralphy105 May 13, 2025
b6c7e89
Merge branch 'DefiLlama:main' into main
Ralphy105 May 13, 2025
8585f14
remove try catch
Ralphy105 May 13, 2025
2bc7506
Merge branch 'main' of https://github.com/turtle-dao/DefiLlama-Adapters
Ralphy105 May 13, 2025
5c42fee
Merge branch 'DefiLlama:main' into main
Ralphy105 May 14, 2025
33e93ba
Add etherex staking position and lagoon vaults
Ralphy105 Aug 29, 2025
f9ad5f5
not forgetting the doublecounted param
Ralphy105 Aug 29, 2025
2891520
Merge branch 'DefiLlama:main' into main
Ralphy105 Aug 29, 2025
a09cdcb
fix: turtle tvl
ftarantuviez Oct 8, 2025
d2d5975
Merge branch 'DefiLlama:main' into main
ftarantuviez Oct 8, 2025
5a73696
fix: address pr comments
ftarantuviez Oct 20, 2025
412d590
Merge branch 'main' of github.com:turtle-dao/DefiLlama-Adapters
ftarantuviez Oct 20, 2025
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
47 changes: 38 additions & 9 deletions projects/TurtleClub/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ const tokens = {
WBTC: '0x3aAB2285ddcDdaD8edf438C1bAB47e1a9D05a9b4',
FOXY: '0x5FBDF89403270a1846F5ae7D113A989F850d1566',
CROAK: '0xaCb54d07cA167934F57F829BeE2cC665e1A5ebEF',
REX33: '0xe4eeb461ad1e4ef8b8ef71a33694ccd84af051c4',
xREX: '0xc93b315971a4f260875103f5da84cb1e30f366cc',
z0weETH: '0x77E305B4D4D3b9DA4e82Cefd564F5b948366A44b', // TODO all ZeroLend not priced properly
z0WETH: '0xB4FFEf15daf4C02787bC5332580b838cE39805f5',
z0ezETH: '0x0684FC172a0B8e6A65cF4684eDb2082272fe9050',
Expand Down Expand Up @@ -137,7 +139,16 @@ const tokens = {
}
};

const exceptions = {
const tokenMapping = {
linea: {
[tokens.linea.xREX]: {
coingeckoId: 'etherex',
decimals: 18,
},
},
}

const tokenMappingERC20 = {
ethereum: [
{ token: tokens.ethereum.rEUL, use: tokens.ethereum.EUL },
{ token: tokens.ethereum.ezREZ, use: tokens.ethereum.REZ }, // TODO ezREZ not priced properly
Expand All @@ -146,6 +157,8 @@ const exceptions = {
],
linea: [
{ token: tokens.linea.oLYNX, use: tokens.linea.LYNX },
{ token: tokens.linea.xREX, coingeckoId: "etherex", decimals: 18 },
{ token: tokens.linea.REX33, coingeckoId: "etherex", decimals: 18 },
// { token: tokens.linea.z0WETH, use: tokens.linea.ETH },
// { token: tokens.linea.z0ezETH, use: tokens.linea.ETH },
// { token: tokens.linea.z0rsETH, use: tokens.linea.ETH },
Expand Down Expand Up @@ -184,19 +197,35 @@ const treasuryNFTs = {
mode: [
// { name: 'MODE', veNft: '0x06ab1Dc3c330E9CeA4fDF0C7C6F6Fb6442A4273C', baseToken: tokens.mode.MODE, owner: '0x41FC0479A3E67Ac6d26760D1205dC523abee8b94', useLocked: false },
]
};
};

const turtleVaults = {
linea: [
{address: '0x1b316fA2D6C44b65C1ed6D29b37743Cd362F0f71', strategy: "erc4626" }, // Turtle Linea ETH
{address: '0x7df7e45ab573ace8f872b5d5a1689af7ff1a07f7', strategy: "erc4626" }, // Turtle Linea USDC
],
ethereum: [
{address: '0x6Bf340dB729d82af1F6443A0Ea0d79647b1c3DDf', strategy: "erc20" }, // tacBTC
{address: '0x294eecec65A0142e84AEdfD8eB2FBEA8c9a9fbad', strategy: "erc20" }, // tacETH
{address: '0x699e04F98dE2Fc395a7dcBf36B48EC837A976490', strategy: "erc20" }, // tacUSD
{address: '0xe0dfbe4748ed96350754f1328679bd9647bf9621', strategy: "erc20" }, // Lagoon USDT
{address: '0xbca723C30d55F0915e32019a95AA29ea21fd555C', strategy: "erc20" }, // Lagoon WETH
{address: '0x423b469268b15821107C38d1E1f702877219bc52', strategy: "erc20" }, // Lagoon WBTC
{address: '0xd56031b6E6860Bd41dCe2729D1beD21c387B26ce', strategy: "erc20" }, // Lagoon USDC
{address: '0x1E2aAaDcF528b9cC08F43d4fd7db488cE89F5741', strategy: "erc4626" }, // Morpho USDC
{address: '0xb5e4576C2FAA16b0cC59D1A2f3366164844Ef9E0', strategy: "erc4626" }, // Morpho cbBTC
{address: '0x0bB2751a90fFF62e844b1521637DeD28F3f5046A', strategy: "erc4626" }, // Morpho WETH
],
}


const vaultContracts = [
'0x294eecec65A0142e84AEdfD8eB2FBEA8c9a9fbad', // tacETH
'0x6Bf340dB729d82af1F6443A0Ea0d79647b1c3DDf', // tacBTC
'0x699e04F98dE2Fc395a7dcBf36B48EC837A976490', // tacUSD
];

module.exports = {
defaultTokens,
tokens,
treasuryMultisigs,
exceptions,
tokenMapping,
tokenMappingERC20,
treasuryNFTs,
vaultContracts,
turtleVaults,
};
52 changes: 52 additions & 0 deletions projects/TurtleClub/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const { log } = require("../helper/utils");


const getVaultsERC20Tvl = async (api, vaults) => {
for (const vault of vaults) {
try {
// Get total supply of the boring vault token
const totalSupply = await api.call({
abi: 'erc20:totalSupply',
target: vault,
});

// Add the vault token to balances with its total supply
// The vault token itself represents the TVL
api.add(vault, totalSupply);
} catch (error) {
log(`Error fetching data for boring vault:`, error.message);
}
}
}

const getERC4626VaultsTvl = async (api, vaults) => {
for (const vault of vaults) {
try {
// Get the underlying asset from the vault
const asset = await api.call({
abi: 'function asset() view returns (address)',
target: vault,
});

// Get total assets from the morpho vault
const totalAssets = await api.call({
abi: 'function totalAssets() view returns (uint256)',
target: vault,
});


// Add the underlying asset with the total assets amount
// This represents the actual underlying assets held by the vault
api.add(asset, totalAssets);

} catch (error) {
log(`Error fetching data for morpho vault ${vault}:`, error.message);
// Continue with other vaults if one fails
}
}
}

module.exports = {
getVaultsERC20Tvl,
getERC4626VaultsTvl,
}
40 changes: 27 additions & 13 deletions projects/TurtleClub/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
const { sumTokensExport } = require("../helper/unwrapLPs");
const { tokens, vaultContracts } = require("./assets");

const plainTokens = Object.values(tokens).map(chain => Object.values(chain)).flat(1);

const { getVaultsERC20Tvl, getERC4626VaultsTvl } = require("./helpers");
const { turtleVaults } = require("./assets");

module.exports = {
// All vaults currently ethereum
doublecounted: true,
ethereum: {
tvl: sumTokensExport({
owners: vaultContracts,
tokens: plainTokens,
permitFailure: true,
tokenConfig: { onlyWhitelisted: false },
}),
tvl: async (api) => {
const erc20Vaults = turtleVaults.ethereum.filter(vault => vault.strategy === "erc20").map(vault => vault.address);

// Handle Boring Vaults
await getVaultsERC20Tvl(api, erc20Vaults);
const erc4626Vaults = turtleVaults.ethereum.filter(vault => vault.strategy === "erc4626").map(vault => vault.address);

// Handle Morpho Vaults
await getERC4626VaultsTvl(api, erc4626Vaults);

return api.getBalances();
},
},
linea: {
tvl: async (api) => {
const erc4626Vaults = turtleVaults.linea.filter(vault => vault.strategy === "erc4626").map(vault => vault.address);

// Handle ERC4626 Vaults
await getERC4626VaultsTvl(api, erc4626Vaults);

return api.getBalances();
},
},
};
};

30 changes: 24 additions & 6 deletions projects/treasury/turtleclub.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { tokens, treasuryMultisigs, treasuryNFTs, defaultTokens, exceptions } = require('../TurtleClub/assets');
const { tokens, treasuryMultisigs, treasuryNFTs, defaultTokens, tokenMappingERC20, tokenMapping } = require('../TurtleClub/assets');
const { ankrChainMapping } = require('../helper/token');
const { sumTokens2, unwrapSolidlyVeNft } = require('../helper/unwrapLPs');
const SOLIDLY_VE_NFT_ABI = require('../helper/abis/solidlyVeNft.json');
Expand All @@ -13,7 +13,7 @@ function formatForTreasuryExport(tokens = {}) {
return treasuryExportsFormat;
}

async function sumPositions(api, NFTs) {
async function sumNFTs(api, NFTs) {
const waitNFTs = [];
for (const treasuryNFT of NFTs) {
const { veNft, owner, baseToken, useLocked = true } = treasuryNFT;
Expand Down Expand Up @@ -50,9 +50,12 @@ function turtleTreasuryExports(config, treasuryNFTs) {
}

const tvl = async (api) => {
if (exceptions[chain]?.length > 0) {
if (tokenMappingERC20[chain]?.length > 0) {
const es = [];
exceptions[chain].forEach(async ({ token, use }) => {
tokenMappingERC20[chain].forEach(async ({ token, use, coingeckoId, decimals }) => {
const balanceLogic = coingeckoId ?
bal => api.add(coingeckoId, bal / (10 ** decimals), { skipChain: true }) :
bal => api.add(use, bal);
es.push((async () => {
const balances = await api.multiCall({
abi: 'erc20:balanceOf',
Expand All @@ -62,14 +65,29 @@ function turtleTreasuryExports(config, treasuryNFTs) {
})),
permitFailure: true
});
balances.filter(b => b !== '0' && !!b).forEach(bal => api.add(use, bal));
balances.filter(b => b !== '0' && !!b).map(bal => Number(bal)).forEach(balanceLogic);
})());
});
await Promise.allSettled(es);
}

const xRexAddr = tokens.linea.xREX;
const xRexStakedBalances = await api.multiCall({
abi: 'function balanceOf(address) view returns (uint256)',
calls: treasuryMultisigs.map(owner => ({ params: [owner] })),
target: '0xedd7cbc9c47547d0b552d5bc2be76135f49c15b1', // VoteModule staking contract
permitFailure: true,
});
xRexStakedBalances.filter(b => b && b !== '0').map(bal => Number(bal)).forEach(balance => {
const xRexMapping = tokenMapping.linea[xRexAddr];
if (xRexMapping)
api.add(xRexMapping.coingeckoId, balance / (10 ** xRexMapping.decimals), { skipChain: true });
else
api.add(xRexAddr, balance);
});

await sumTokens2({ ...api, api, ...tvlConfig });
if (treasuryNFTs[chain]?.length > 0) await sumPositions(api, treasuryNFTs[chain]);
if (treasuryNFTs[chain]?.length > 0) await sumNFTs(api, treasuryNFTs[chain]);
};
exportObj[chain] = { tvl };
}
Expand Down
Loading