From 3dfee009c490117c220a3f09e817f399d9478925 Mon Sep 17 00:00:00 2001 From: sumomoliu Date: Thu, 6 Apr 2023 14:49:02 +0800 Subject: [PATCH 1/3] Add IntegralDAO strategy --- src/strategies/index.ts | 2 + src/strategies/integral-dao/examples.json | 41 +++++++++++++ src/strategies/integral-dao/index.ts | 70 +++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 src/strategies/integral-dao/examples.json create mode 100644 src/strategies/integral-dao/index.ts diff --git a/src/strategies/index.ts b/src/strategies/index.ts index 8942c8f8f..1722709d8 100644 --- a/src/strategies/index.ts +++ b/src/strategies/index.ts @@ -175,6 +175,7 @@ import * as rnbwBalance from './rnbw-balance'; import * as celerSgnDelegation from './celer-sgn-delegation'; import * as balancerDelegation from './balancer-delegation'; import * as infinityProtocolPools from './infinityprotocol-liquidity-pools'; +import * as IntegralDAO from './integral-dao'; import * as aaveGovernancePower from './aave-governance-power'; import * as cake from './cake'; import * as aks from './aks'; @@ -620,6 +621,7 @@ const strategies = { 'celer-sgn-delegation': celerSgnDelegation, 'balancer-delegation': balancerDelegation, 'infinityprotocol-liquidity-pools': infinityProtocolPools, + 'integral-dao': IntegralDAO, 'aave-governance-power': aaveGovernancePower, cake, aks, diff --git a/src/strategies/integral-dao/examples.json b/src/strategies/integral-dao/examples.json new file mode 100644 index 000000000..8f4a99a53 --- /dev/null +++ b/src/strategies/integral-dao/examples.json @@ -0,0 +1,41 @@ +[ + { + "name": "Integral vote weighting strategy", + "strategy": { + "name": "integral-dao", + "params": { + "symbol": "ITGR", + "contractAddresses": [ + "0xd502f487e1841fdc805130e13eae80c61186bc98", + "0x36bD665392236b20bd42e161f02Bf0ae1d9441Ff", + "0xFFc0EAC1a1aE79C697607229Aca43Ef422625a40" + ], + "decimals": 18, + "pageSize": 100 + } + }, + "network": "1", + "addresses": [ + "0x39c6f54b47c1ccb896221eb5e4e24765108cf145", + "0xa3f2d88fb722d4f2a082edbf98354b81dc34829e", + "0xd5a71e5170ab8213862b324c5c10d17f2356bab3", + "0x3dadf003afcc96d404041d8ae711b94f8c68c6a5", + "0x1a3f00a013670becaf3e51b5db8c0a530b5bf08f", + "0x80b5da500b832ae5fca7514079375cc70ddbd20e", + "0xd1b040469c053df278004cfccc0e352c5e0032b1", + "0x013f107eb48401b1a58607d7bb37127ce075002c", + "0x6b174b2f42dae970fed64cfa61cd0b993d59ef66", + "0x02b2d6a3298a4b20aa4f7a0a57e920e9fc9ad864", + "0x502d629728b9c461726beee240f89c5d82c5f1c5", + "0x384f28360caabd007e27c872b95e63302bf2492f", + "0x6b879dd45cf492b0950e4ac94f2657d811341169", + "0x671e53a32573ab447796bbc6b98b9c166f960fe8", + "0xaef031994435202aa92e1c1f3289d07a89b8ae54", + "0x5bbe5c40af27dbe17adb4cf24a4793d4dbff5614", + "0x430a5965bcee916b7629353be63f0ba9f9fdb18b", + "0xc16f2313e360c53803f728bbd3a798048f656c52", + "0x8f49f0eb2b30ef269dc22b44bdead34c81887e7b" + ], + "snapshot": 12511580 + } +] diff --git a/src/strategies/integral-dao/index.ts b/src/strategies/integral-dao/index.ts new file mode 100644 index 000000000..3d8bbd612 --- /dev/null +++ b/src/strategies/integral-dao/index.ts @@ -0,0 +1,70 @@ +import { BigNumberish } from '@ethersproject/bignumber'; +import { formatUnits } from '@ethersproject/units'; +import { Multicaller } from '../../utils'; + +export const author = 'ken'; +export const version = '0.1.0'; + +const abi = [ + 'function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96)', + 'function getCurrentVotes(address account) external view returns (uint96)' +]; + +async function getVotes( + multi: any, + addresses: string[], + contractAddress: string, + decimals: number, + blockTag: string | number +) { + if (blockTag === 'latest') { + addresses.forEach((address) => { + multi.call(address, contractAddress, 'getCurrentVotes', [address]); + }); + } else { + addresses.forEach((address) => { + multi.call(address, contractAddress, 'getPriorVotes', [ + address, + blockTag + ]); + }); + } + const result: Record = await multi.execute(); + return Object.fromEntries( + Object.entries(result).map(([address, balance]) => [ + address, + parseFloat(formatUnits(balance, decimals)) + ]) + ); +} + +export async function strategy( + space, + network, + provider, + addresses, + options, + snapshot +): Promise> { + const blockTag = typeof snapshot === 'number' ? snapshot : 'latest'; + const results = await Promise.all( + options.contractAddresses.map((contractAddress) => + getVotes( + new Multicaller(network, provider, abi, { blockTag }), + addresses, + contractAddress, + options.decimals, + blockTag + ) + ) + ); + + return results.slice(1).reduce((acc, result) => { + Object.keys(result).forEach((address) => { + if (acc[address]) { + acc[address] += result[address]; + } + }); + return acc; + }, results[0]); +} From 1de68d98781c69d6c3139597f90bb7e307704af7 Mon Sep 17 00:00:00 2001 From: sumomoliu Date: Sun, 9 Apr 2023 21:51:05 +0800 Subject: [PATCH 2/3] Fixed not latest blockTag --- src/strategies/integral-dao/examples.json | 12 +++--------- src/strategies/integral-dao/index.ts | 22 +++++----------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/strategies/integral-dao/examples.json b/src/strategies/integral-dao/examples.json index 8f4a99a53..d128b2258 100644 --- a/src/strategies/integral-dao/examples.json +++ b/src/strategies/integral-dao/examples.json @@ -16,17 +16,11 @@ }, "network": "1", "addresses": [ - "0x39c6f54b47c1ccb896221eb5e4e24765108cf145", - "0xa3f2d88fb722d4f2a082edbf98354b81dc34829e", - "0xd5a71e5170ab8213862b324c5c10d17f2356bab3", - "0x3dadf003afcc96d404041d8ae711b94f8c68c6a5", - "0x1a3f00a013670becaf3e51b5db8c0a530b5bf08f", - "0x80b5da500b832ae5fca7514079375cc70ddbd20e", - "0xd1b040469c053df278004cfccc0e352c5e0032b1", + "0x39C6F54b47c1CCB896221EB5e4e24765108Cf145", "0x013f107eb48401b1a58607d7bb37127ce075002c", "0x6b174b2f42dae970fed64cfa61cd0b993d59ef66", "0x02b2d6a3298a4b20aa4f7a0a57e920e9fc9ad864", - "0x502d629728b9c461726beee240f89c5d82c5f1c5", + "0xD222674ee29F588Fad1633E850b513b64b0350a9", "0x384f28360caabd007e27c872b95e63302bf2492f", "0x6b879dd45cf492b0950e4ac94f2657d811341169", "0x671e53a32573ab447796bbc6b98b9c166f960fe8", @@ -36,6 +30,6 @@ "0xc16f2313e360c53803f728bbd3a798048f656c52", "0x8f49f0eb2b30ef269dc22b44bdead34c81887e7b" ], - "snapshot": 12511580 + "snapshot": 13569183 } ] diff --git a/src/strategies/integral-dao/index.ts b/src/strategies/integral-dao/index.ts index 3d8bbd612..96e769f80 100644 --- a/src/strategies/integral-dao/index.ts +++ b/src/strategies/integral-dao/index.ts @@ -6,7 +6,6 @@ export const author = 'ken'; export const version = '0.1.0'; const abi = [ - 'function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96)', 'function getCurrentVotes(address account) external view returns (uint96)' ]; @@ -14,21 +13,11 @@ async function getVotes( multi: any, addresses: string[], contractAddress: string, - decimals: number, - blockTag: string | number + decimals: number ) { - if (blockTag === 'latest') { - addresses.forEach((address) => { - multi.call(address, contractAddress, 'getCurrentVotes', [address]); - }); - } else { - addresses.forEach((address) => { - multi.call(address, contractAddress, 'getPriorVotes', [ - address, - blockTag - ]); - }); - } + addresses.forEach((address) => { + multi.call(address, contractAddress, 'getCurrentVotes', [address]); + }); const result: Record = await multi.execute(); return Object.fromEntries( Object.entries(result).map(([address, balance]) => [ @@ -53,8 +42,7 @@ export async function strategy( new Multicaller(network, provider, abi, { blockTag }), addresses, contractAddress, - options.decimals, - blockTag + options.decimals ) ) ); From e51deb3c3ff75393eef876fa9acc16f471afa696 Mon Sep 17 00:00:00 2001 From: sumomoliu Date: Mon, 17 Apr 2023 02:00:34 +0800 Subject: [PATCH 3/3] Add contract size limit --- src/strategies/integral-dao/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/strategies/integral-dao/index.ts b/src/strategies/integral-dao/index.ts index 96e769f80..7615579f9 100644 --- a/src/strategies/integral-dao/index.ts +++ b/src/strategies/integral-dao/index.ts @@ -36,6 +36,9 @@ export async function strategy( snapshot ): Promise> { const blockTag = typeof snapshot === 'number' ? snapshot : 'latest'; + if (options.contractAddresses.length > 5) { + throw new Error('Contract number exceed limit 5'); + } const results = await Promise.all( options.contractAddresses.map((contractAddress) => getVotes(