Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions src/strategies/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
import * as prlInSpRL2Balance from './prl-in-sprl2-balance';
import * as edenOnlineOverride from './eden-online-override';

Expand Down Expand Up @@ -974,6 +975,7 @@ const strategies = {
'superfluid-vesting': superfluidVesting,
synapse,
'dappcomposer-getvotingunits': dappcomposerGetVotingUnits,
'puffer-getpastvotes': pufferGetPastVotes,
'prl-in-sprl2-balance': prlInSpRL2Balance,
'eden-online-override': edenOnlineOverride
};
Expand Down
5 changes: 5 additions & 0 deletions src/strategies/puffer-getpastvotes/README.md
Original file line number Diff line number Diff line change
@@ -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.
19 changes: 19 additions & 0 deletions src/strategies/puffer-getpastvotes/examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[
{
"name": "vlPUFFER Example",
"strategy": {
"name": "puffer-getpastvotes",
"params": {
"address": "0xcD1adFB7Ae5E08F7494cdE2EA6666CeF5cc4804c",
"decimals": 18
}
},
"network": "11155111",
"addresses": [
"0xe19cBAAa2e546f8C6175892190d1f26279d19995",
"0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0",
"0x65d2dd7A66a2733a36559fE900A236280A05FBD6"
],
"snapshot": 8422135
}
]
67 changes: 67 additions & 0 deletions src/strategies/puffer-getpastvotes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
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,
snapshot
): Promise<Record<string, number>> {
const blockTag = typeof snapshot === 'number' ? snapshot : 'latest';

// Create a multicaller for the block tag, either past / present
const multi = new Multicaller(network, provider, abi, { blockTag });

// Figure out the current block number
let blockNumber = blockTag;

// If the block tag is not the latest block, use the block tag as blockNumber
if (blockTag === 'latest') {
blockNumber = await provider.getBlockNumber();
}

// Fetch that block to figure out the block timestamp (current interval block timestamp)
const block = await provider.getBlock(blockNumber);

// 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 currentIntervalBlockTimestampInSeconds = block.timestamp;

// Calculate the current period based on the current timestamp
const currentPeriod = Math.floor(
currentIntervalBlockTimestampInSeconds / SECONDS_PER_WEEK
);
// Calculate the timestamp at the end of the previous period
const previousPeriodEnd = currentPeriod * SECONDS_PER_WEEK - 1;

addresses.forEach((address) =>
multi.call(address, options.address, 'getPastVotes', [
address,
previousPeriodEnd.toString()
])
);

const result: Record<string, BigNumberish> = await multi.execute();

return Object.fromEntries(
Object.entries(result).map(([address, balance]) => [
address,
parseFloat(formatUnits(balance, options.decimals))
])
);
}
28 changes: 28 additions & 0 deletions src/strategies/puffer-getpastvotes/schema.json
Original file line number Diff line number Diff line change
@@ -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
}
}
}
Loading