Skip to main content
Voting strategies determine how voting power is calculated for proposals. The SDK provides built-in strategies for token-based voting, whitelists, cross-chain proofs, and custom validation logic.

Overview

Strategies are organized by network type:
  • EVM strategies: For Ethereum and EVM-compatible chains
  • Starknet strategies: For Starknet L2
  • Offchain strategies: For gasless, offchain governance

Getting Strategies

Strategies are retrieved based on network configuration:
import { getEvmStrategy, getStarknetStrategy, getOffchainStrategy } from '@snapshot-labs/sx';

// EVM strategy
const evmStrategy = getEvmStrategy(
  strategyAddress,
  networkConfig
);

// Starknet strategy
const starknetStrategy = getStarknetStrategy(
  strategyAddress,
  networkConfig
);

// Offchain strategy
const offchainStrategy = getOffchainStrategy(
  strategyName
);

EVM Strategies

Vanilla Strategy

Simple strategy that returns a fixed voting power:
import { createVanillaStrategy } from '@snapshot-labs/sx/strategies/evm';

const strategy = createVanillaStrategy();
Use case: Testing or simple one-person-one-vote scenarios.

OpenZeppelin Votes (OZ Votes)

Voting power based on ERC20Votes or ERC721Votes tokens:
import { createOzVotesStrategy } from '@snapshot-labs/sx/strategies/evm';

const strategy = createOzVotesStrategy();

const params = await strategy.getParams(
  'vote',
  strategyConfig,
  signerAddress,
  metadata,
  voteData,
  config
);
Use case: DAOs using OpenZeppelin’s governance tokens with built-in voting power tracking.
This strategy reads voting power from tokens implementing the IVotes interface with getPastVotes() or getPastTotalSupply().

Compound Strategy

Voting power based on Compound-style governance tokens:
import { createCompStrategy } from '@snapshot-labs/sx/strategies/evm';

const strategy = createCompStrategy();
Use case: DAOs using Compound’s governance token standard with delegation.

Merkle Whitelist

Voting power based on a pre-defined whitelist stored in a merkle tree:
import { createMerkleWhitelist } from '@snapshot-labs/sx/strategies/evm';

const strategy = createMerkleWhitelist();
Use case: Governance restricted to specific addresses with predetermined voting power.

ApeGas Strategy

Specialized strategy for ApeCoin DAO with delegation support:
import { createApeGasStrategy } from '@snapshot-labs/sx/strategies/evm';

const strategy = createApeGasStrategy();
Use case: ApeCoin DAO governance with delegate.cash integration.

Starknet Strategies

Vanilla Strategy

Basic Starknet strategy:
import { createVanillaStrategy } from '@snapshot-labs/sx/strategies/starknet';

const strategy = createVanillaStrategy();

ERC20 Votes

Starknet ERC20 token voting:
import { createErc20VotesStrategy } from '@snapshot-labs/sx/strategies/starknet';

const strategy = createErc20VotesStrategy();
Use case: Voting power based on Starknet ERC20 token balances.

Merkle Whitelist

Whitelist-based voting on Starknet:
import { createMerkleWhitelistStrategy } from '@snapshot-labs/sx/strategies/starknet';

const strategy = createMerkleWhitelistStrategy();

OZ Votes Storage Proof

Cross-chain voting using Ethereum storage proofs verified on Starknet:
import { createOzVotesStorageProofStrategy } from '@snapshot-labs/sx/strategies/starknet';

const strategy = createOzVotesStorageProofStrategy(params);
Use case: L1 token holders voting on L2 proposals without bridging tokens.
This strategy uses Herodotus storage proofs to verify Ethereum state on Starknet, enabling secure cross-chain governance.

EVM Slot Value

Read arbitrary EVM storage slot values on Starknet:
import { createEvmSlotValueStrategy } from '@snapshot-labs/sx/strategies/starknet';

const strategy = createEvmSlotValueStrategy();
Use case: Custom voting power calculations based on any Ethereum storage value.

Offchain Strategies

Only Members

Restrict proposals/votes to space members:
import { createOnlyMembersStrategy } from '@snapshot-labs/sx/strategies/offchain';

const strategy = createOnlyMembersStrategy();

Remote VP (Voting Power)

Calculate voting power using remote APIs:
import { createRemoteVpStrategy } from '@snapshot-labs/sx/strategies/offchain';

const strategy = createRemoteVpStrategy();
Use case: Complex voting power calculations using Snapshot’s voting power engine.

Remote Validate

Validate voters using predefined validation schemes:
import { createRemoteValidateStrategy } from '@snapshot-labs/sx/strategies/offchain';

const strategy = createRemoteValidateStrategy('basic');
// or
const passportStrategy = createRemoteValidateStrategy('passport-gated');
const arbitrumStrategy = createRemoteValidateStrategy('arbitrum');
const karmaStrategy = createRemoteValidateStrategy('karma-eas-attestation');
Supported validators:
  • any: Allow anyone
  • basic: Basic validation
  • passport-gated: Gitcoin Passport gating
  • arbitrum: Arbitrum-specific validation
  • karma-eas-attestation: Karma EAS attestation validation

Strategy Parameters

Strategies can accept configuration parameters:
interface StrategyConfig {
  address: string;      // Strategy contract address
  index: number;        // Strategy index in the space
  params?: string[];    // Strategy-specific parameters
  metadata?: any;       // Additional metadata
}

Getting Strategy Parameters

import { getStrategiesWithParams } from '@snapshot-labs/sx/strategies/evm';

const strategiesWithParams = await getStrategiesWithParams(
  'vote',              // 'propose' or 'vote'
  strategiesConfigs,
  signerAddress,
  voteData,
  clientConfig
);

Strategy Interface

All strategies implement a common interface:
interface Strategy {
  getParams(
    call: 'propose' | 'vote',
    strategyConfig: StrategyConfig,
    signerAddress: string,
    metadata: any,
    data: Propose | Vote,
    config: ClientConfig
  ): Promise<string[]>;
}

Multi-Strategy Voting

Spaces can combine multiple strategies:
const strategies = [
  {
    address: '0xOzVotesStrategy...',
    index: 0,
    params: ['0xTokenAddress...', '0']
  },
  {
    address: '0xWhitelistStrategy...',
    index: 1,
    params: [merkleRoot]
  }
];

const totalVotingPower = strategies.reduce(
  (sum, strategy) => sum + strategyVotingPower(strategy),
  0n
);
When using multiple strategies, ensure they don’t conflict (e.g., different token balances counting towards the same vote).

Custom Strategies

Create custom strategies by implementing the strategy interface:
function createCustomStrategy(): Strategy {
  return {
    async getParams(call, strategyConfig, signerAddress, metadata, data, config) {
      // Custom logic to calculate and return strategy parameters
      const votingPower = await calculateVotingPower(signerAddress);
      return [votingPower.toString()];
    }
  };
}

Storage Proofs

Some strategies use storage proofs for cross-chain verification:
import { storageProofs } from '@snapshot-labs/sx';

// Generate storage proof for L1 token balance
const proof = await storageProofs.generateProof(
  tokenAddress,
  userAddress,
  blockNumber
);

Common Patterns

Token-Based Voting

// 1. Configure token strategy
const strategyConfig = {
  address: ozVotesStrategyAddress,
  index: 0,
  params: [tokenAddress, '0'] // token address and slot index
};

// 2. Get voting parameters
const params = await strategy.getParams(
  'vote',
  strategyConfig,
  voterAddress,
  null,
  voteData,
  config
);

// 3. Submit vote with parameters

Whitelist Voting

import { merkle } from '@snapshot-labs/sx';

// 1. Generate merkle tree
const entries = [
  '0xAddress1:1000',
  '0xAddress2:2000'
];
const tree = await merkle.generateMerkleTree(entries);
const root = tree[0];

// 2. Deploy or update strategy with root
const strategyConfig = {
  address: whitelistStrategyAddress,
  index: 0,
  params: [root]
};

// 3. Generate proof for voter
const proof = merkle.generateMerkleProof(tree, voterIndex);

Best Practices

Choose Appropriate Strategy

Select strategies that match your governance model and token standard

Test Parameters

Validate strategy parameters before deployment

Consider Gas Costs

Some strategies (storage proofs) have higher gas costs

Snapshot Timing

Ensure voting power snapshots are taken at the right block

Utils

Merkle tree and storage proof utilities

Authenticators

Authentication methods

Executors

Execution strategies

Build docs developers (and LLMs) love