diff --git a/src/strategies/dextf-staked-in-vaults/README.md b/src/strategies/dextf-staked-in-vaults/README.md new file mode 100644 index 000000000..08c2686a2 --- /dev/null +++ b/src/strategies/dextf-staked-in-vaults/README.md @@ -0,0 +1,42 @@ +# Multiple contract call strategy + +This strategy allows users to call the 'balanceOf' function across multiple DEXTF contracts (vaults) and performs summation over the results. By calling 'balanceOf', DEXTF vaults return the amount of $DEXTF staked by the user in that vault. This strategy will make a single multicall which will retrieve all users' staked balances in all of DEXTF vaults. + +## Example + +The space config will look like this: + +```JSON +{ + "strategies": [ + ["dextf-staked-in-vaults", { + // vault contracts across which token balance needs to be calculated + "contractAddresses": [ + "0x42a05787584ec09dDDe46f8CE6a715c93049ee88" + ], + // scoreMultiplier can be used to increase users' scores by a certain magnitude + "scoreMultiplier": 1, + // ABI for balanceOf method + "methodABI_1": { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + }], + ] +} +``` diff --git a/src/strategies/dextf-staked-in-vaults/examples.json b/src/strategies/dextf-staked-in-vaults/examples.json new file mode 100644 index 000000000..3a2697c59 --- /dev/null +++ b/src/strategies/dextf-staked-in-vaults/examples.json @@ -0,0 +1,35 @@ +[ + { + "name": "Example query", + "strategy": { + "name": "dextf-staked-in-vaults", + "params": { + "name": "DEXTF Vaults", + "contractAddresses": ["0x42a05787584ec09dDDe46f8CE6a715c93049ee88"], + "scoreMultiplier": 1, + "methodABI": { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + } + }, + "network": "1", + "addresses": ["0x75527f00EC786dCCd6CEa82C9B90C81781C42E92"], + "snapshot": 13230652 + } +] diff --git a/src/strategies/dextf-staked-in-vaults/index.ts b/src/strategies/dextf-staked-in-vaults/index.ts new file mode 100644 index 000000000..a81f0339e --- /dev/null +++ b/src/strategies/dextf-staked-in-vaults/index.ts @@ -0,0 +1,61 @@ +import { formatUnits } from '@ethersproject/units'; +import { multicall } from '../../utils'; + +export const author = 'dextf'; +export const version = '1.0.0'; + +function chunk(array, chunkSize) { + const tempArray: any[] = []; + for (let i = 0, len = array.length; i < len; i += chunkSize) + tempArray.push(array.slice(i, i + chunkSize)); + return tempArray; +} + +export async function strategy( + space, + network, + provider, + addresses, + options, + snapshot +) { + const blockTag = typeof snapshot === 'number' ? snapshot : 'latest'; + let callData: [any, string, [any]][] = []; + addresses.map((userAddress: any) => { + options.contractAddresses.map((vaultAddress: any) => { + callData.push([vaultAddress, options.methodABI.name, [userAddress]]); + }); + }); + callData = [...chunk(callData, 2000)]; // chunking the callData into multiple arrays of 2000 requests + let response: any[] = []; + for (let i = 0; i < callData.length; i++) { + const tempArray = await multicall( + network, + provider, + [options.methodABI], + callData[i], + { blockTag } + ); + response.push(...tempArray); + } + if (options.contractAddresses.length > 1) { + // grouping all balances of a particular address together + const result: any = []; + response = [].concat.apply([], response); + for (let i = addresses.length; i > 0; i--) { + result.push(response.splice(0, Math.ceil(response.length / i))); + } + // performing summation over all balances of the user + response = []; + result.map((item, index) => { + let sum = 0; + result[index].map((element) => { + sum = sum + parseFloat(formatUnits(element.toString(), 18)); + }); + response.push(sum); + }); + } + return Object.fromEntries( + response.map((value, i) => [addresses[i], options.scoreMultiplier * value]) + ); +} diff --git a/src/strategies/index.ts b/src/strategies/index.ts index 9a5ed64e5..709aad147 100644 --- a/src/strategies/index.ts +++ b/src/strategies/index.ts @@ -6,6 +6,7 @@ import * as balancerErc20InternalBalanceOf from './balancer-erc20-internal-balan import * as sunder from './sunder'; import * as balancerSmartPool from './balancer-smart-pool'; import * as contractCall from './contract-call'; +import * as dextfVaults from './dextf-staked-in-vaults'; import * as dfynFarms from './dfyn-staked-in-farms'; import * as dfynVaults from './dfyn-staked-in-vaults'; import * as ensDomainsOwned from './ens-domains-owned'; @@ -152,6 +153,7 @@ const strategies = { 'balancer-erc20-internal-balance-of': balancerErc20InternalBalanceOf, 'erc20-received': erc20Received, 'contract-call': contractCall, + 'dextf-staked-in-vaults': dextfVaults, 'dfyn-staked-in-farms': dfynFarms, 'dfyn-staked-in-vaults': dfynVaults, 'eth-received': ethReceived,