Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.

Commit 9e320f6

Browse files
committed
fix: only process addresses from relevant protocols
1 parent cd892cb commit 9e320f6

7 files changed

Lines changed: 392 additions & 112 deletions

File tree

src/utils.ts

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,7 @@ function validateProtocols(protocols: Protocol[]): void {
122122
* Formats addresses according to the specified blockchain protocols.
123123
*
124124
* This function takes a list of addresses and formats them according to the provided
125-
* protocols. It prioritizes EVM formatting when multiple protocols are specified and
126-
* an address is valid for both. If EVM formatting fails but Starknet is supported,
127-
* it falls back to Starknet formatting. Throws an error if any address cannot be
128-
* formatted according to the specified protocols.
125+
* protocols.
129126
*
130127
* @param addresses - Array of blockchain addresses to format
131128
* @param protocols - Array of protocol names to validate against. Defaults to ['evm'].
@@ -140,20 +137,14 @@ export function getFormattedAddressesByProtocol(
140137
validateProtocols(protocols);
141138

142139
return addresses.map((address) => {
143-
if (protocols.includes('evm')) {
140+
if (protocols.includes('evm') && address.length === 42) {
144141
try {
145142
return snapshot.utils.getFormattedAddress(address, 'evm');
146-
} catch (e) {
147-
// Continue to starknet if evm formatting fails and starknet is supported
148-
}
149-
}
150-
151-
if (protocols.includes('starknet')) {
143+
} catch (e) {}
144+
} else if (protocols.includes('starknet') && address.length === 66) {
152145
try {
153146
return snapshot.utils.getFormattedAddress(address, 'starknet');
154-
} catch (e) {
155-
// Address format not supported by any protocol
156-
}
147+
} catch (e) {}
157148
}
158149

159150
throw new Error(
@@ -162,6 +153,46 @@ export function getFormattedAddressesByProtocol(
162153
});
163154
}
164155

156+
/**
157+
* Filters addresses by the specified protocols.
158+
*
159+
* This function takes a list of addresses and filters them based on the provided
160+
* protocols. It checks if each address matches the expected format for EVM or
161+
* Starknet protocols
162+
*
163+
* This function DOES NOT format/validate the addresses, and may return invalid addresses
164+
*
165+
* @param addresses - Array of addresses to filter
166+
* @param protocols - Array of protocol names to validate against. Defaults to ['evm'].
167+
* Valid protocols are 'evm' and 'starknet'.
168+
*
169+
* @returns Array of addresses that match the specified protocols
170+
*/
171+
export function getAddressesByProtocol(
172+
addresses: string[],
173+
protocols: Protocol[] = ['evm']
174+
): string[] {
175+
validateProtocols(protocols);
176+
177+
return addresses.filter((address) => {
178+
if (protocols.includes('evm') && /^0x[a-fA-F0-9]{40}$/.test(address)) {
179+
return true;
180+
}
181+
if (protocols.includes('starknet') && /^0x[a-fA-F0-9]{64}$/.test(address)) {
182+
return true;
183+
}
184+
return false;
185+
});
186+
}
187+
188+
export function validateAddress(address: string): void {
189+
try {
190+
getFormattedAddressesByProtocol([address], ['evm', 'starknet']);
191+
} catch {
192+
throw new Error('invalid address');
193+
}
194+
}
195+
165196
export const {
166197
multicall,
167198
Multicaller,
@@ -181,6 +212,7 @@ export default {
181212
getScoresDirect,
182213
customFetch,
183214
getFormattedAddressesByProtocol,
215+
getAddressesByProtocol,
184216
multicall,
185217
Multicaller,
186218
subgraphRequest,

src/utils/vp.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ import { formatBytes32String } from '@ethersproject/strings';
22
import { getAddress } from '@ethersproject/address';
33
import subgraphs from '@snapshot-labs/snapshot.js/src/delegationSubgraphs.json';
44
import {
5+
getAddressesByProtocol,
56
getFormattedAddressesByProtocol,
67
getProvider,
78
getSnapshots,
89
Multicaller,
9-
subgraphRequest
10+
subgraphRequest,
11+
validateAddress
1012
} from '../utils';
1113
import _strategies from '../strategies';
1214
import { Score, Snapshot, VotingPower } from '../types';
13-
import { DEFAULT_SUPPORTED_PROTOCOLS } from '../constants';
1415

1516
const DELEGATION_CONTRACT = '0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446';
1617
const EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000';
@@ -30,6 +31,12 @@ export async function getVp(
3031
space: string,
3132
delegation?: boolean
3233
): Promise<VotingPower> {
34+
if (strategies.some((s) => !_strategies[s.name])) {
35+
throw new Error('invalid strategies');
36+
}
37+
// Ensure that the address is either a valid EVM address or Starknet address
38+
validateAddress(address);
39+
3340
const networks = [...new Set(strategies.map((s) => s.network || network))];
3441
const snapshots = await getSnapshots(
3542
network,
@@ -49,6 +56,7 @@ export async function getVp(
4956
const p: Score[] = strategies.map((strategy) => {
5057
const n = strategy.network || network;
5158
let addresses = [address];
59+
const supportedProtocols = _strategies[strategy.name].supportedProtocols;
5260

5361
if (delegation) {
5462
addresses = delegations[n].in;
@@ -57,11 +65,11 @@ export async function getVp(
5765
if (addresses.length === 0) return {};
5866
}
5967

60-
addresses = getFormattedAddressesByProtocol(
61-
addresses,
62-
_strategies[strategy.name].supportedProtocols ??
63-
DEFAULT_SUPPORTED_PROTOCOLS
64-
);
68+
addresses = getAddressesByProtocol(addresses, supportedProtocols);
69+
addresses = getFormattedAddressesByProtocol(addresses, supportedProtocols);
70+
71+
if (addresses.length === 0) return {};
72+
6573
return _strategies[strategy.name].strategy(
6674
space,
6775
n,
@@ -76,18 +84,17 @@ export async function getVp(
7684
const vpByStrategy = scores.map((score, i) => {
7785
const n = strategies[i].network || network;
7886
let addresses = [address];
87+
const supportedProtocols =
88+
_strategies[strategies[i].name].supportedProtocols;
7989

8090
if (delegation) {
8191
addresses = delegations[n].in;
8292
if (!delegations[n].out) addresses.push(address);
8393
addresses = [...new Set(addresses)];
8494
}
8595

86-
addresses = getFormattedAddressesByProtocol(
87-
addresses,
88-
_strategies[strategies[i].name].supportedProtocols ??
89-
DEFAULT_SUPPORTED_PROTOCOLS
90-
);
96+
addresses = getAddressesByProtocol(addresses, supportedProtocols);
97+
addresses = getFormattedAddressesByProtocol(addresses, supportedProtocols);
9198
return addresses.reduce((a, b) => a + (score[b] || 0), 0);
9299
});
93100
const vp = vpByStrategy.reduce((a, b) => a + b, 0);

test/__snapshots__/vp.test.ts.snap

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`VP Calculation Integration Tests getVp() should calculate VP for EVM address on mixed protocol 1`] = `
4+
{
5+
"vp": 10.998985610441185,
6+
"vp_by_strategy": [
7+
1,
8+
9.998985610441185,
9+
],
10+
"vp_state": "final",
11+
}
12+
`;
13+
14+
exports[`VP Calculation Integration Tests getVp() should calculate VP for Starknet address on evm protocol 1`] = `
15+
{
16+
"vp": 0,
17+
"vp_by_strategy": [
18+
0,
19+
],
20+
"vp_state": "final",
21+
}
22+
`;
23+
24+
exports[`VP Calculation Integration Tests getVp() should calculate VP for Starknet address on mixed protocol 1`] = `
25+
{
26+
"vp": 1,
27+
"vp_by_strategy": [
28+
1,
29+
0,
30+
],
31+
"vp_state": "final",
32+
}
33+
`;
34+
35+
exports[`VP Calculation Integration Tests getVp() should calculate VP with delegation enabled 1`] = `
36+
{
37+
"vp": 10.077130335431244,
38+
"vp_by_strategy": [
39+
0,
40+
10.028706352441185,
41+
0,
42+
0.04842398299005922,
43+
],
44+
"vp_state": "final",
45+
}
46+
`;
47+
48+
exports[`VP Calculation Integration Tests getVp() should calculate VP without delegation 1`] = `
49+
{
50+
"vp": 21.55404462002206,
51+
"vp_by_strategy": [
52+
0,
53+
9.998985610441185,
54+
11.506635026590818,
55+
0.04842398299005922,
56+
],
57+
"vp_state": "final",
58+
}
59+
`;

0 commit comments

Comments
 (0)