diff --git a/src/strategies/index.ts b/src/strategies/index.ts index 680d52253..54bf7a274 100644 --- a/src/strategies/index.ts +++ b/src/strategies/index.ts @@ -480,6 +480,7 @@ import * as dappcomposerGetVotingUnits from './dappcomposer-getvotingunits'; import * as erc20BalanceOfSaevo from './erc20-balance-of-saevo'; import * as apecoinStaking from './apecoin-staking'; import * as shroomyVotingPower from './shroomy-voting-power'; +import * as pufferGetPastVotes from './puffer-getpastvotes'; const strategies = { 'shroomy-voting-power': shroomyVotingPower, @@ -971,7 +972,8 @@ const strategies = { realt, 'superfluid-vesting': superfluidVesting, synapse, - 'dappcomposer-getvotingunits': dappcomposerGetVotingUnits + 'dappcomposer-getvotingunits': dappcomposerGetVotingUnits, + 'puffer-getpastvotes': pufferGetPastVotes }; Object.keys(strategies).forEach(function (strategyName) { diff --git a/src/strategies/puffer-getpastvotes/README.md b/src/strategies/puffer-getpastvotes/README.md new file mode 100644 index 000000000..6266c7d13 --- /dev/null +++ b/src/strategies/puffer-getpastvotes/README.md @@ -0,0 +1,5 @@ +# Puffer Governance: Voting + +In Puffer, the voting power is calculated using the amount of `$vlPUFFER` delegated to user at the end of the previous period. + +This strategy is used to get the voting power at the end of the previous period. \ No newline at end of file diff --git a/src/strategies/puffer-getpastvotes/examples.json b/src/strategies/puffer-getpastvotes/examples.json new file mode 100644 index 000000000..ef64a943a --- /dev/null +++ b/src/strategies/puffer-getpastvotes/examples.json @@ -0,0 +1,19 @@ +[ + { + "name": "vlPUFFER Example", + "strategy": { + "name": "puffer-getpastvotes", + "params": { + "address": "0xcD1adFB7Ae5E08F7494cdE2EA6666CeF5cc4804c", + "decimals": 18 + } + }, + "network": "11155111", + "addresses": [ + "0xe19cBAAa2e546f8C6175892190d1f26279d19995", + "0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0", + "0x65d2dd7A66a2733a36559fE900A236280A05FBD6" + ], + "snapshot": 8310195 + } +] diff --git a/src/strategies/puffer-getpastvotes/index.ts b/src/strategies/puffer-getpastvotes/index.ts new file mode 100644 index 000000000..c04316e79 --- /dev/null +++ b/src/strategies/puffer-getpastvotes/index.ts @@ -0,0 +1,51 @@ +import { BigNumberish } from '@ethersproject/bignumber'; +import { formatUnits } from '@ethersproject/units'; +import { Multicaller } from '../../utils'; + +export const author = 'bxmmm1'; +export const version = '0.1.0'; + +const abi = [ + 'function getPastVotes(address account, uint256 timepoint) view returns (uint256)' +]; + +export async function strategy( + _space, + network, + provider, + addresses, + options +): Promise> { + // We want to use `getPastVotes` because of the delegation happening on the contract + // We want to use the past timestamp to get the votes at the start of the previous week + + // Calculate the timestamp at the end of the most recent complete 7-day period + // This ensures alignment with contract's 7-day voting periods + const SECONDS_PER_WEEK = 7 * 24 * 60 * 60; + // Get the current timestamp in seconds + const currentTimestampInSeconds = Math.floor(Date.now() / 1000); + // Calculate the current period based on the current timestamp + const currentPeriod = Math.floor( + currentTimestampInSeconds / SECONDS_PER_WEEK + ); + // Calculate the timestamp at the end of the previous period + const previousPeriodEnd = currentPeriod * SECONDS_PER_WEEK - 1; + + const multi = new Multicaller(network, provider, abi); + + addresses.forEach((address) => + multi.call(address, options.address, 'getPastVotes', [ + address, + previousPeriodEnd.toString() + ]) + ); + + const result: Record = await multi.execute(); + + return Object.fromEntries( + Object.entries(result).map(([address, balance]) => [ + address, + parseFloat(formatUnits(balance, options.decimals)) + ]) + ); +} diff --git a/src/strategies/puffer-getpastvotes/schema.json b/src/strategies/puffer-getpastvotes/schema.json new file mode 100644 index 000000000..78af53673 --- /dev/null +++ b/src/strategies/puffer-getpastvotes/schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/Strategy", + "definitions": { + "Strategy": { + "title": "Strategy", + "type": "object", + "properties": { + "address": { + "type": "string", + "title": "Contract address", + "examples": ["e.g. 0xcD1adFB7Ae5E08F7494cdE2EA6666CeF5cc4804c"], + "pattern": "^0x[a-fA-F0-9]{40}$", + "minLength": 42, + "maxLength": 42 + }, + "decimals": { + "type": "number", + "title": "Decimals", + "examples": ["e.g. 18"], + "minimum": 0 + } + }, + "required": ["address", "decimals"], + "additionalProperties": false + } + } +} diff --git a/src/strategies/shroomy-voting-power/index.ts b/src/strategies/shroomy-voting-power/index.ts index dca51963c..581b85a45 100644 --- a/src/strategies/shroomy-voting-power/index.ts +++ b/src/strategies/shroomy-voting-power/index.ts @@ -44,7 +44,7 @@ export async function strategy( ) ); } - + const powers = await multicaller.execute(); addresses.forEach((address) => {