Authenticators validate governance actions (proposals, votes, updates) before they are executed on-chain. The SDK provides authenticators for both EVM and Starknet networks.
Overview
Authenticators are responsible for:
Creating authenticated contract calls
Validating signatures
Encoding authentication data
Supporting different signature schemes
Getting Authenticators
Authenticators are retrieved based on network configuration:
import { clients } from '@snapshot-labs/sx' ;
// For EVM networks
const evmAuthenticator = clients . evm . getAuthenticator (
authenticatorAddress ,
networkConfig
);
// For Starknet
const starknetAuthenticator = clients . starknet . getAuthenticator (
authenticatorAddress ,
networkConfig
);
EVM Authenticators
Vanilla Authenticator
Direct transaction-based authentication without signatures:
import { createVanillaAuthenticator } from '@snapshot-labs/sx/authenticators/evm' ;
const authenticator = createVanillaAuthenticator ();
Use case : When users submit transactions directly from their wallets.
EthSig Authenticator
Ethereum signature-based authentication using EIP-712:
import { createEthSigAuthenticator } from '@snapshot-labs/sx/authenticators/evm' ;
const authenticator = createEthSigAuthenticator ( 'ethSig' );
// or
const authenticatorV2 = createEthSigAuthenticator ( 'ethSigV2' );
const call = authenticator . createCall (
envelope , // Contains signature data
selector , // Function selector
calldata // Function arguments
);
ethSigV2 is an updated version with improved gas efficiency and security features.
Use case : Off-chain signing for gasless voting via relayers.
EthTx Authenticator
Transaction-based authentication with additional validation:
import { createEthTxAuthenticator } from '@snapshot-labs/sx/authenticators/evm' ;
const authenticator = createEthTxAuthenticator ();
Use case : When you need transaction-level validation beyond vanilla authentication.
Starknet Authenticators
Vanilla Authenticator
Direct transaction authentication for Starknet:
import { createVanillaAuthenticator } from '@snapshot-labs/sx/authenticators/starknet' ;
const authenticator = createVanillaAuthenticator ();
EthSig Authenticator
Ethereum signature authentication on Starknet:
import { createEthSigAuthenticator } from '@snapshot-labs/sx/authenticators/starknet' ;
const authenticator = createEthSigAuthenticator ();
// Create a propose call
const call = authenticator . createProposeCall ( envelope , {
author: '0x...' ,
metadataUri: 'ipfs://...' ,
executionStrategy: {
address: '0x...' ,
params: []
},
strategiesParams: []
});
// Create a vote call
const voteCall = authenticator . createVoteCall ( envelope , {
voter: '0x...' ,
proposalId: 1 ,
choice: 1 ,
votingStrategies: [],
metadataUri: ''
});
// Create an update proposal call
const updateCall = authenticator . createUpdateProposalCall ( envelope , {
author: '0x...' ,
proposalId: 1 ,
executionStrategy: {
address: '0x...' ,
params: []
},
metadataUri: 'ipfs://...'
});
Use case : Cross-chain governance where Ethereum signatures are verified on Starknet.
EthTx Authenticator
Ethereum transaction verification on Starknet:
import { createEthTxAuthenticator } from '@snapshot-labs/sx/authenticators/starknet' ;
const authenticator = createEthTxAuthenticator ();
Use case : Verifying Ethereum L1 transactions on Starknet L2.
StarkSig Authenticator
Native Starknet signature authentication:
import { createStarkSigAuthenticator } from '@snapshot-labs/sx/authenticators/starknet' ;
const authenticator = createStarkSigAuthenticator ();
Use case : When using Starknet wallets and signature schemes.
StarkTx Authenticator
Starknet transaction-based authentication:
import { createStarkTxAuthenticator } from '@snapshot-labs/sx/authenticators/starknet' ;
const authenticator = createStarkTxAuthenticator ();
Authenticator Types
Authenticators implement specific interfaces based on the network:
EVM Authenticator Interface
interface Authenticator {
type : 'vanilla' | 'ethSig' | 'ethSigV2' | 'ethTx' ;
createCall (
envelope : Envelope < Propose | UpdateProposal | Vote >,
selector : string ,
calldata : string []
) : Call ;
}
Starknet Authenticator Interface
interface Authenticator {
type : 'vanilla' | 'ethSig' | 'ethTx' | 'starkSig' | 'starkTx' ;
createProposeCall ( envelope : Envelope < Propose >, args : ProposeCallArgs ) : Call ;
createVoteCall ( envelope : Envelope < Vote >, args : VoteCallArgs ) : Call ;
createUpdateProposalCall ( envelope : Envelope < UpdateProposal >, args : UpdateProposalCallArgs ) : Call ;
}
Signature Envelopes
Authenticators use envelopes that contain both the action data and signature:
interface Envelope < T > {
data : T ;
signatureData ?: {
signature : string ; // The actual signature
message : {
salt : string ; // Nonce/salt for replay protection
// ... other message fields
};
};
}
Common Patterns
Gasless Voting with EthSig
// 1. User signs message off-chain
const signature = await signer . signTypedData ( domain , types , message );
// 2. Create envelope with signature
const envelope = {
data: voteData ,
signatureData: {
signature ,
message: { salt: '0x00' }
}
};
// 3. Authenticator creates the call
const authenticator = createEthSigAuthenticator ( 'ethSig' );
const call = authenticator . createCall ( envelope , selector , calldata );
// 4. Relayer submits the transaction
Direct Transaction with Vanilla
// 1. Create envelope without signature
const envelope = {
data: proposeData
};
// 2. Authenticator creates the call
const authenticator = createVanillaAuthenticator ();
const call = authenticator . createCall ( envelope , selector , calldata );
// 3. User submits transaction directly
Error Handling
Authenticators throw errors when required data is missing:
try {
const call = authenticator . createCall ( envelope , selector , calldata );
} catch ( error ) {
if ( error . message . includes ( 'signatureData is required' )) {
// Handle missing signature
}
}
Always ensure the envelope contains the required signatureData when using signature-based authenticators (EthSig, StarkSig, etc.).
Security Considerations
Replay Protection Use unique salts in signature messages to prevent replay attacks
Signature Verification Authenticators verify signatures on-chain before executing actions
Network Matching Ensure authenticators match the target network (EVM vs Starknet)
Type Safety Use TypeScript to catch type mismatches at compile time
Utils Encoding and signature utilities
Strategies Voting power calculation
Executors Execution strategies