From f4226ab3e2a9a86aa3f1056c73712ff58bf1bb26 Mon Sep 17 00:00:00 2001 From: 0xmDreamy <0xmDreamy@proton.me> Date: Tue, 14 Nov 2023 16:58:03 +0100 Subject: [PATCH] feat(abracadabra): Add support for Kava cauldrons --- .../abracadabra/abis/FeeCollectable.json | 112 ++++++++++++++++++ src/adaptors/abracadabra/cauldrons.js | 62 +++++++++- 2 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 src/adaptors/abracadabra/abis/FeeCollectable.json diff --git a/src/adaptors/abracadabra/abis/FeeCollectable.json b/src/adaptors/abracadabra/abis/FeeCollectable.json new file mode 100644 index 0000000000..d4a7cb5f37 --- /dev/null +++ b/src/adaptors/abracadabra/abis/FeeCollectable.json @@ -0,0 +1,112 @@ +[ + { + "inputs": [], + "name": "ErrInvalidFeeBips", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "ErrInvalidFeeOperator", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousFeeCollector", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "previousFeeAmount", + "type": "uint16" + }, + { + "indexed": true, + "internalType": "address", + "name": "feeCollector", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "feeAmount", + "type": "uint16" + } + ], + "name": "LogFeeParametersChanged", + "type": "event" + }, + { + "inputs": [], + "name": "feeBips", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeCollector", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isFeeOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeCollector", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_feeBips", + "type": "uint16" + } + ], + "name": "setFeeParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/adaptors/abracadabra/cauldrons.js b/src/adaptors/abracadabra/cauldrons.js index 1ec46e6431..200a1d77fd 100644 --- a/src/adaptors/abracadabra/cauldrons.js +++ b/src/adaptors/abracadabra/cauldrons.js @@ -10,6 +10,7 @@ const CAULDRON_V2_ABI = require('./abis/CauldronV2.json'); const BENTOBOX_V1_ABI = require('./abis/BentoBoxV1.json'); const INTEREST_STRATEGY = require('./abis/InterestStrategy.json'); const BASE_STARGATE_LP_STRATEGY = require('./abis/BaseStargateLPStrategy.json'); +const FEE_COLLECTABLE_STRATEGY = require('./abis/FeeCollectable.json'); const MIM_COINGECKO_ID = 'magic-internet-money'; @@ -166,6 +167,17 @@ const POOLS = { { version: 3, address: '0x68f498c230015254aff0e1eb6f85da558dff2362' }, ], }, + kava: { + marketLensAddress: '0x2d50927A6E87E517946591A137b765fAba018E70', + cauldrons: [ + { version: 4, address: '0x3CFf6F628Ebc88e167640966E67314Cf6466E6A8' }, // MIM/USDT Curve LP + { + version: 4, + address: '0x895731a0C3836a5534561268F15EBA377218651D', + collateralPoolId: '246ee0b2-434e-44dd-90a7-a728deaf1597', + }, // Stargate USDT + ] + }, }; const NEGATIVE_INTEREST_STRATEGIES = { @@ -182,6 +194,12 @@ const BASE_STARGATE_LP_STRATEGIES = { ], }; +const FEE_COLLECTABLE_STRATEGIES = { + kava: [ + '0x30D525cbB79D2baaE7637eA748631a6360Ce7c16' + ] +} + const getMarketLensDetailsForCauldrons = ( chain, marketLensAddress, @@ -453,6 +471,37 @@ const getBaseStargateLpStrategyFees = (baseStargateLpStrategies) => ) ).then(Object.fromEntries); +const getFeeCollectableStrategyFees = (feeCollectableStrategies) => + Promise.all( + Object.entries(feeCollectableStrategies).map( + async ([chain, chainFeeCollectableStrategies]) => [ + chain, + await sdk.api.abi + .multiCall({ + abi: FEE_COLLECTABLE_STRATEGY.find( + ({ name }) => name === 'feeBips' + ), + calls: chainFeeCollectableStrategies.map( + (feeCollectableStrategy) => ({ + target: feeCollectableStrategy, + }) + ), + chain, + requery: true, + }) + .then((call) => + Object.fromEntries( + call.output.map((x, i) => [ + chainFeeCollectableStrategies[i].toLowerCase(), + x.output / 10000, + ]) + ) + ), + ] + ) + ).then(Object.fromEntries); + + const getDetailsFromCollaterals = (collaterals, abi) => Promise.all( Object.entries(collaterals).map(async ([chain, chainCollaterals]) => { @@ -539,7 +588,7 @@ const getApy = async () => { bentoboxes, strategies, negativeInterestStrategyApys, - baseStargateLpStrategyFees, + strategyFees, symbols, decimals, pricesObj, @@ -552,7 +601,10 @@ const getApy = async () => { ([collaterals, bentoboxes]) => getStrategies(collaterals, bentoboxes) ), getNegativeInterestStrategyApy(NEGATIVE_INTEREST_STRATEGIES), - getBaseStargateLpStrategyFees(BASE_STARGATE_LP_STRATEGIES), + Promise.all([ + getBaseStargateLpStrategyFees(BASE_STARGATE_LP_STRATEGIES), + getFeeCollectableStrategyFees(FEE_COLLECTABLE_STRATEGIES), + ]).then((strategyFeesArr) => _.merge({}, ...strategyFeesArr)), collateralsPromise.then((collaterals) => getDetailsFromCollaterals(collaterals, 'erc20:symbol') ), @@ -601,7 +653,7 @@ const getApy = async () => { negativeInterestStrategyApys, [chain, strategy] ); - const baseStargateLpStrategyFee = _.get(baseStargateLpStrategyFees, [ + const strategyFee = _.get(strategyFees, [ chain, strategy, ]); @@ -609,12 +661,12 @@ const getApy = async () => { collateral.apyBase = (targetPercentage / 100) * -negativeInterestStrategyApy; } else if ( - baseStargateLpStrategyFee !== undefined && + strategyFee !== undefined && collateralApy !== undefined ) { collateral.apyBase = ((collateralApy.apy * targetPercentage) / 100) * - baseStargateLpStrategyFee; + (1 - strategyFee); } } else { // No strategy to consider, so just use the apy from the pool if one exists.