# Identify integrator activity Source: https://docs.snapshot.box/developer-guides/identify-integrator-activity To help integrators track and identify activity originating from their applications, Snapshot supports an optional `app` parameter. This parameter can be included when users cast votes or create proposals, allowing you to tag these actions with your application's identifier. ### **Using `app` with Snapshot.js** If you're integrating Snapshot's voting and proposal functionalities directly into your platform using [Snapshot.js](https://github.com/snapshot-labs/snapshot.js), you can include the `app` parameter in your function calls: ```javascript theme={null} import { Web3Provider } from '@ethersproject/providers'; const web3 = new Web3Provider(window.ethereum); const [account] = await web3.listAccounts(); const receipt = await client.vote(web3, account, { space: 'yam.eth', proposal: '0x21ea31e896ec5b5a49a3653e51e787ee834aaf953263144ab936ed756f36609f', type: 'single-choice', choice: 1, reason: 'Choice 1 makes a lot of sense', app: 'yourappname' }); ``` ### **Adding `app` to Snapshot URLs** For platforms that redirect users to Snapshot, you can append the `app` parameter to the URL. This tags the action with your application's identifier when the user interacts on Snapshot. **URL format:** ``` https://snapshot.box/#/{network}:{space}/proposal/{proposalId}?app={yourappname} ``` **Example:** ``` https://snapshot.box/#/s:ens.eth/proposal/0xfa54ff2b55f0495c96ec2d8645241bcff48ca6afe1f4925fb51f29c4667252df?app=boardroom ``` **Parameter requirements** * **Format:** Lowercase alphanumeric string * **Maximum length:** 24 characters * **Purpose:** The `app` parameter will be stored with the vote or proposal data on Snapshot. This enables you to identify and analyze activities originating from your application. By using the `app` parameter, you can seamlessly integrate Snapshot into your platform while maintaining clear visibility over user interactions related to your application. # Add a network Source: https://docs.snapshot.box/developer-guides/networks To add a new network to Snapshot, you need to subscribe to the Network plan. The Network plan is tailored for projects seeking to integrate their EVM compatible chain network in Snapshot. This plan facilitates governance across your networks by supporting both a mainnet and a testnet network. ### **How to get started** Refer to [https://snapshot.box/#/network](https://snapshot.box/#/network) # Create a validation strategy Source: https://docs.snapshot.box/developer-guides/validation-strategy Create a validation strategy and use it in your own space To add your own voting validation strategy on Snapshot you need to fork the **score-api** repository and create a pull request. [https://github.com/snapshot-labs/score-api](https://github.com/snapshot-labs/score-api) ### 1. Navigate to the **`src\validations.`** ```bash theme={null} └── src └── validations └── basic ``` ### 2. Create a copy of the **`basic`** strategy folder and rename it to the name of your voting validation. ### 3. Customize the logic of your voting validation. If you are not sure about the `Validation` class, have a look at its definition: [https://github.com/snapshot-labs/score-api/blob/master/src/strategies/validations/validation.ts](https://github.com/snapshot-labs/score-api/blob/master/src/strategies/validations/validation.ts) The validation name has to be included in the[ `index.ts`](https://github.com/snapshot-labs/score-api/blob/master/src/strategies/validations/index.ts) in the `validationClasses` variable. ### 4. Test your validation To make sure your validation passes all tests, run: ```javascript theme={null} npm run test --validation= // replace ``` ### 4. Make sure you pass the checklist Have a look here on the requirements for adding a new validation strategy and make sure you fulfill the points in the checklist: [https://github.com/snapshot-labs/score-api#checklist-for-adding-a-new-strategy](https://github.com/snapshot-labs/score-api#checklist-for-adding-a-new-strategy) ### 5. Create a pull request The team will then review your PR and after it's approved and merged it will be available to choose in your space settings. # Create a voting strategy Source: https://docs.snapshot.box/developer-guides/voting-strategy Learn how to create a new custom voting strategy. If you can't find a strategy that fits your the needs of your space you can create a new custom one. Follow the steps below to learn how to do that: ### **1. Fork the score-api repository** Create a fork of the score-api repository: [https://github.com/snapshot-labs/score-api](https://github.com/snapshot-labs/score-api) ### **2. Duplicate the `erc20-balance-of` strategy folder** Navigate to `src/strategies/strategies` directory, duplicate the `erc20-balance-of` directory and rename it to the chosen name for your new strategy. ```bash theme={null} └── src └── strategies └── strategies └── erc20-balance-of ``` ### **3. Write the logic for your strategy** There are several files you need to edit: #### a. `index.ts` This file defines the logic for calculation of the voting power. As an example, the `erc20-balance-of` is taking as parameters `space`, `network`, `provider`, `addresses`, `options` and `snapshot` in order to be able to retrieve the balances of the token specified in the `options` parameter for the provided addresses: ```typescript theme={null} import { BigNumberish } from '@ethersproject/bignumber'; import { formatUnits } from '@ethersproject/units'; import { Multicaller } from '../../utils'; export const author = 'bonustrack'; export const version = '0.1.1'; const abi = [ 'function balanceOf(address account) external view returns (uint256)' ]; export async function strategy( space, network, provider, addresses, options, snapshot ): Promise> { const blockTag = typeof snapshot === 'number' ? snapshot : 'latest'; const multi = new Multicaller(network, provider, abi, { blockTag }); addresses.forEach((address) => multi.call(address, options.address, 'balanceOf', [address]) ); const result: Record = await multi.execute(); return Object.fromEntries( Object.entries(result).map(([address, balance]) => [ address, parseFloat(formatUnits(balance, options.decimals)) ]) ); } ``` #### b. `schema.json` Describe the structure of your strategy by editing the `properties`, `required` and `additionalProperties` key-value pairs according to the logic from `index.ts` file: ```json theme={null} { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/Strategy", "definitions": { "Strategy": { "title": "Strategy", "type": "object", "properties": { "symbol": { "type": "string", "title": "Symbol", "examples": ["e.g. UNI"], "maxLength": 16 }, "address": { "type": "string", "title": "Contract address", "examples": ["e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"], "pattern": "^0x[a-fA-F0-9]{40}$", "minLength": 42, "maxLength": 42 }, "decimals": { "type": "number", "title": "Decimals", "examples": ["e.g. 18"] } }, "required": ["address", "decimals"], "additionalProperties": false } } } ``` #### d. `./score-api/src/strategies/strategies/index.ts` Import and declare you new strategy in the [`index.ts`](https://github.com/snapshot-labs/score-api/blob/master/src/strategies/strategies/index.ts) file: ```typescript theme={null} import * as yourStrategyName from './your-strategy-name'; ``` #### d. `examples.json` Provide an example for the custom strategy setup which will be displayed on [https://snapshot.box](https://snapshot.box) on the strategy's details page. Make sure to **include all the parameters you defined** above and a list of addresses to test against: ```json theme={null} [ { "name": "Example query", "strategy": { "name": "erc20-balance-of", "params": { "address": "0x6b175474e89094c44da98b954eedeac495271d0f", "symbol": "DAI", "decimals": 18 } }, "network": "1", "addresses": [ "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11", "0xeF8305E140ac520225DAf050e2f71d5fBcC543e7", "0x1E1A51E25f2816335cA436D65e9Af7694BE232ad", "0x1F717Ce8ff07597ee7c408b5623dF40AaAf1787C", "0x1c7a9275F2BD5a260A9c31069F77d53473b8ae2e", "0x1d5E65a087eBc3d03a294412E46CE5D6882969f4", "0x1f254336E5c46639A851b9CfC165697150a6c327", "0x2ec3F80BeDA63Ede96BA20375032CDD3aAfb3030", "0x4AcBcA6BE2f8D2540bBF4CA77E45dA0A4a095Fa2", "0x4F3D348a6D09837Ae7961B1E0cEe2cc118cec777", "0x6D7f23A509E212Ba7773EC1b2505d1A134f54fbe", "0x07a1f6fc89223c5ebD4e4ddaE89Ac97629856A0f", "0x8d5F05270da470e015b67Ab5042BDbE2D2FEFB48", "0x8d07D225a769b7Af3A923481E1FdF49180e6A265", "0x8f60501dE5b9b01F9EAf1214dbE1924aA97F7fd0", "0x9B8e8dD9151260c21CB6D7cc59067cd8DF306D58", "0x17ea92D6FfbAA1c7F6B117c1E9D0c88ABdc8b84C", "0x38C0039247A31F3939baE65e953612125cB88268" ], "snapshot": 11437846 } ] ``` #### e. `README.md` Write the description of how the strategy works and provide an example of the setup. It will be displayed on the strategy's details page. ``` This is the most common strategy, it returns the balances of the voters for a specific ERC20 token. Here is an example of parameters: { "address": "0x6b175474e89094c44da98b954eedeac495271d0f", "symbol": "DAI", "decimals": 18 } ``` ### **4. Test the strategy locally** Once you saved all the files run the below command with the name of your new strategy: ```javascript theme={null} npm run test:strategy --strategy= // replace ``` It will trigger the tests which you can find in [this file](https://github.com/snapshot-labs/score-api/blob/master/test/strategies/unit/strategy.test.ts). If you get any errors read them carefully as they should point directly to the problem. ### **5. Review the checklist** Ensure you meet the requirements for adding a new strategy by reviewing the checklist for adding a new strategy which can be found on [this documentation](https://github.com/snapshot-labs/score-api/blob/master/STRATEGIES.md#checklist-for-new-strategies) ### **6. Create a pull request** Create a Pull Request with the above changes on the original [score-api](https://github.com/snapshot-labs/score-api/) repo. The review can take the team up to 72 hours, so please be patient 🙏 After the PR has been merged, you will need to wait for the release of a new version of [Snapshot](https://snapshot.box) which can take a couple of days. Once it's deployed you can move on to the next step. ### 7. Try it out! Head to the strategy's details page and click **Playground** button. Follow the instructions from [#testing-a-voting-strategy](/user-guides/voting-strategies#testing-a-voting-strategy) to see if it works as you intended. Congrats, you've just added a new custom voting strategy. # Build with Snapshot Source: https://docs.snapshot.box/developers/index Integrate governance into your apps using Snapshot's APIs, SDKs, and protocol. Snapshot provides a complete set of tools for developers to integrate decentralized governance into their applications. Whether you're querying voting data, building custom strategies, or deploying fully onchain governance, you'll find everything you need here. JavaScript client library for interacting with Snapshot: create proposals, cast votes, and manage spaces. Query spaces, proposals, votes, and more with Snapshot's public GraphQL API. Fully onchain governance protocol deployed on Ethereum and Starknet. Create custom voting and validation strategies to tailor governance to your needs. Subscribe to proposal and voting events in real-time to keep your app in sync. ### Quick links * [GitHub](https://github.com/snapshot-labs) * [Discord](https://discord.snapshot.org) * [Snapshot.js on npm](https://www.npmjs.com/package/@snapshot-labs/snapshot.js) # FAQ Source: https://docs.snapshot.box/faq Frequently asked questions about Snapshot. ## General A snapshot is a record of the blockchain's state at a specific block number. It shows exactly who owned which tokens at that precise moment. By doing this, voting rights are based on actual holdings fixed at the time of a proposal. Without a snapshot, a user could vote, transfer their tokens to another account they control, and vote again, effectively double spending their voting power. This process of locking the data at a single point in time to prevent such abuse is what gives Snapshot its name. Yes, Snapshot itself is free to use and does not charge any fees for setting up a space, creating proposals, casting votes, or executing decisions. However, to create a space, you need an ENS domain, which you must purchase from [ens.domains](https://ens.domains). While Snapshot's core features are offchain and do not require gas fees, deploying a Snapshot X space may involve paying gas fees. If you decide to sponsor gas costs for users on Snapshot X, you will also need to cover those fees. Despite these extra costs arising from external factors, Snapshot itself remains free. Yes, Snapshot is fully open source under the MIT license, meaning anyone can see how it's built and contribute to its development. All code repositories are available on [GitHub](https://github.com/snapshot-labs). Snapshot facilitates gasless voting through the use of offchain signed messages. This approach allows users to participate in governance without the need for onchain transactions, avoiding gas fees while ensuring verifiability. No. Snapshot uses the universal web3 login: you need to have a wallet account like MetaMask or Coinbase to connect to Snapshot. Snapshot maintains several mirror sites to ensure you can always access the platform: * **Primary domain:** [snapshot.box](https://snapshot.box) * **Alternative mirrors:** * [snapshot.org](https://snapshot.org) (Netlify hosting) * [snapshot.eth.limo](https://snapshot.eth.limo) (Fleek with IPFS) All mirrors display identical content. Your votes, proposals, and data remain synchronized across every domain. You can also host Snapshot yourself, the full source code is available at [github.com/snapshot-labs/sx-monorepo](https://github.com/snapshot-labs/sx-monorepo). Yes. The message you sign in your wallet to cast a vote doesn't affect your holdings or web3 identity. Some spaces may be flagged with a warning badge if we suspect them to be fake, but there is no risk to your funds associated with signing a Snapshot vote. Read more about [badges and warnings](/user-guides/spaces/badges-and-warnings). Yes. Limiting the number of followed spaces to 25 is one of our anti-scam and anti-spam measures. Wait for around 10 minutes and try again. If the error persists, open the console panel (right click > `Inspect` > `Console` tab), take a screenshot, and contact our support on [Help Center](/faq/support-and-feedback) with the error details and what action you were trying to perform. The reason behind this error is that the time configured on your device isn't accurate. [Refer here to troubleshoot](https://github.com/snapshot-labs/snapshot/discussions/769#discussioncomment-1400619). ## Voting You need to connect to Snapshot with your wallet and fulfil the requirements defined by the voting strategies used by a specific space. For example, you might be required to hold a specific amount of the organization's token. You can see the voting strategies directly on a proposal's page in the **Information** section. If your voting power is `0`, it's most likely because you did not hold the required tokens at the time of proposal creation. Tokens acquired after the proposal was created are not taken into account. If you are eligible to vote, select your choice(s) and confirm your vote. You will be asked to sign a message which doesn't create any gas fees or affect your holdings. That's it! No. Your eligibility to vote depends on the voting strategies defined by the space and usually requires holding the organization's token. Some spaces allow anyone to vote, however this is a rare case. Read more about [voting strategies](/user-guides/voting-strategies). Yes, you can change your vote as long as the voting period is still active. Simply cast a new vote on the same proposal, and it will overwrite your previous vote. Yes. You can find more details in [Using Safe multi-sig](/user-guides/using-safe-multi-sig). Make sure that your wallet is on the same network as the Space. Go to the Space page > Settings > Strategies to check what the Space's network is. Yes, apart from proposals using shielded voting. You can add a short explanation when casting a vote. You can remove your delegations by going to [snapshot.box/#/delegate](https://snapshot.box/#/delegate) and clicking the remove button for the delegations you wish to remove. If you want to override your delegate's vote on a proposal using the delegation strategy, you can simply cast your own vote and it will override the delegate's vote. If the delegation happened onchain, head to the delegation portal of the project you're looking for and redelegate there. Go to the proposal page and click the download icon to get a CSV file. You can open it directly in Excel or import it into Google Sheets. This issue is related to either space settings or the failure of the external infrastructure that Snapshot relies on. Wait 15 minutes and try again. If the error persists, please contact our support on [Help Center](/faq/support-and-feedback) with the URL of the proposal and the error message. This is related to either space settings or a failure of external infrastructure. Wait 15 minutes and try again. If the error persists, contact our support on [Help Center](/faq/support-and-feedback) with the proposal URL and the error message. No. Snapshot calculates the voting power at the time of proposal creation. If the token was not in your wallet before the proposal was created, it will not be counted. ## Proposals It depends on the space settings. Spaces can set up a validation strategy which defines who is eligible to create a proposal, for example you need to hold at least 1 ETH. Moreover, spaces can specify a list of users who can create proposals by listing their wallet addresses. Read more about [proposal validation](/user-guides/validation-strategies). Each proposal's description is limited to **10,000 characters**. An address can have up to **10 active proposals** across spaces at any time. Verified spaces can create up to **10 proposals daily** and **50 monthly**, unverified spaces are limited to **3 daily** and **15 monthly**, while flagged spaces can only create **1 daily** and **5 monthly**. With the [Snapshot Pro](/user-guides/spaces/pro) plan, the character limit increases to **50,000 characters**, and proposal creation limits expand to **100 proposals per day** and **500 per month**. Yes, using Snapshot's API or SDK, you can automate proposal submissions. Check the [developer documentation](/tools/snapshot-js) for specific methods and requirements. If a proposal does not reach the required quorum, it is considered as not passed. However, the outcome depends on the governance rules of the specific project. Some projects might still consider the proposal for further discussion, while others might require resubmission with modifications. Due to an increased amount of scam attacks on Snapshot, shortened URLs are not allowed in the proposal description. Make sure you provide a full URL. Yes. Have a look at the [Quadratic Voting](/proposals/voting-types) system which reduces the impact of large token holders. Due to multiple spam attacks on Snapshot, all spaces are required to set up a Proposal Validation. Head to [validation strategies](/user-guides/validation-strategies#how-to-use-validation-strategies) to learn how. You can submit your request by following the process described in the [token verification](/v1-interface/token-verification) section. ## Voting strategies A voting strategy is a set of conditions used to calculate a user's voting power. Strategies enable Snapshot to calculate the final result of voting on a given proposal. Read more in our [voting strategies](/user-guides/voting-strategies) documentation. You can use the playground on Snapshot available from any strategy's detail page by clicking the **Playground** button. You need to set up a Basic voting validation which allows you to select a specific strategy and define the minimum threshold required. Learn more in [validation strategies](/user-guides/validation-strategies). There are a few common reasons: * **No required assets.** You don't hold the tokens or meet the criteria required by the space's voting strategies. * **Delegation required.** For tokens using ERC-20 Votes (EIP-5805), you must delegate your tokens — to yourself or another address — before they count as voting power. * **Snapshotted at proposal start.** Voting power is taken at the time the proposal was created. Tokens acquired after that point don't count for that proposal. You can also check [this discussion](https://github.com/snapshot-labs/snapshot/discussions/767) for further reasons. If the space is using the delegation strategy and the address which delegated its voting power to you casts a vote, your total voting power is reduced by the delegation you received. Example (using the `delegation` strategy): * B has voting power of 20 of its own * A has voting power of 10 and delegates it to B * B now has voting power of 30 * If A does not vote, B's voting power is 30 * If A does vote, B's voting power is 20 (30 reduced by 10) You can use the [ticket](https://snapshot.box/#/strategy/ticket) strategy. It's a two step process: **1. Voting validation:** Set up a `Basic` voting validation in the space settings. Define the `strategies` for the tokens and the `minScore` required for voters to be eligible. **2. Voting strategy:** Use the [ticket](https://snapshot.box/#/strategy/ticket) strategy to give voting power equal to `1` to any user who passed the voting validation. You can use sub-spaces on Snapshot. This allows you to link different spaces and set different settings for each of them. Learn more in [sub-spaces](/user-guides/spaces/sub-spaces). Yes. You can create an issue on [snapshot-labs/score-api](https://github.com/snapshot-labs/score-api/issues) and then post it in the [#developers](https://discord.com/channels/707079246388133940/747050056422785055) channel on Discord. ## Space settings Yes. Navigate to [app.safe.global](https://app.safe.global) and select Snapshot in the `Apps` tab. Your multisig address will connect to Snapshot and allow you to create spaces, proposals and vote. If you are still a controller of the space you can apply to delete your space or migrate it to another one with a different ENS. Learn more in [migrate or delete](/user-guides/spaces/migrate-or-delete). Yes, you can do it in the space settings. Do not confuse it with changing the `ID` or the ENS domain: for that, you need to migrate the space. Learn more in [migrate or delete](/user-guides/spaces/migrate-or-delete). There is a list of requirements you have to meet. Learn more in [get verified](/user-guides/spaces/get-verified). The process can take up to 72 hours. Verification status is valid as long as the space meets all requirements. Make sure you meet all requirements defined in [get verified](/user-guides/spaces/get-verified#how-to-get-your-space-verified) and contact our support on [Help Center](/faq/support-and-feedback) to regain the space verification. You cannot invalidate existing votes. However you can delete the proposal (if you are an admin of the space or the proposal's creator), change the space settings, and recreate the proposal from scratch. Yes, you can customize the appearance by setting a custom skin, which allows you to change the colors of your space. This feature is available for spaces using custom domains. If your space is using only a ticket Voting Strategy, you are required to set a Voting Validation to minimize the risk of spam votes. Learn how to set it up in [validation strategies](/user-guides/validation-strategies#voting-validation-in-space-settings). Deleting a space does not release its attached ENS name, so you cannot create a new space with the same ENS name. If you wish to retain a similar domain, you could create a new space under a subdomain of your previous ENS name. ## Quorum A proposal passes if it has more "For" votes than "Against" votes, and the total of "For" plus "Abstain" plus "Against" votes reaches or exceeds the quorum. All votes, whether in favor, against, or abstaining, count toward meeting the required participation level. Once that level is met, the proposal's success depends on having a clear majority of "For" votes over "Against". A proposal passes if it meets two conditions: it must have more "For" votes than "Against" votes, and the total of "For" plus "Abstain" votes must reach or exceed a set quorum. In other words, there needs to be enough participation and a clear majority in favor for the proposal to succeed. ## Networks Snapshot supports EVM-compatible networks. To add a new network, you need to subscribe to the network plan. Once subscribed, Snapshot will take care of adding your network to the platform. For more details, visit [snapshot.box/#/network](https://snapshot.box/#/network). For non-EVM networks, please contact the Snapshot team directly. Snapshot supports many networks. Some have full support ("premium") while others have limited support ("non-premium"). Premium networks include: Ethereum, Anime, APECHAIN, Avalanche, Base, Blast, BNB Chain, Cyber, Fraxtal, Gnosis Chain, Horizen EON, Immutable zkEVM, Ink, Kava, Linea, Manta Network, Mantle Network, Merlin Chain, Metis, opBNB, Optimism, peaq, Sei, Shibarium, SNAXchain, Sonic, Story, Vana, and zk.Link. If you want to upgrade a network from non-premium to premium, follow the instructions at [snapshot.box/#/network](https://snapshot.box/#/network). ## Wallet compatibility Yes, Snapshot supports EIP-1271, enabling smart contract wallets to participate directly in governance. EIP-1271 allows smart contracts to implement their own method for signature verification. If you manage a smart contract account, you can use it to create proposals or vote on Snapshot. Make sure your smart contract account is on the same base network as the Snapshot space you want to interact with. Yes, Snapshot supports EIP-6492, a standard for undeployed smart contract wallets (counterfactual wallets). EIP-6492 provides a standardized method to verify signatures from smart contract wallets before they are deployed onchain, enabling users to participate in governance without initially deploying their wallet contracts. A release of the MetaMask Chrome extension (version 12.15.1) introduced a bug affecting message signing. The MetaMask team fixed the problem in version 12.15.2. Please ensure your extension is updated: 1. Open your MetaMask Chrome extension 2. Click on the top-right three-dot menu > Settings > **About** 3. If the version is **12.15.2 or higher**, you're good to go 4. To update manually: go to `chrome://extensions`, find MetaMask, enable **Developer mode**, and click **Update** ## Migrations UMA has announced that they are ending support for oSnap on **December 15, 2025**. After this date, oSnap will no longer execute transactions from your DAO's Safe treasury. If your DAO relies on oSnap, you must take action before this deadline. You can either migrate to [Snapshot X](/snapshot-x/user-guides/create-a-space) (recommended for fully onchain governance) or to [SafeSnap](/v1-interface/plugins/safesnap-reality) (for optimistic execution similar to oSnap). The "delegation" strategy is being replaced by "with-delegation" (effective August 15, 2025). The key difference is that "delegation" works like liquid democracy where a delegator can reclaim power by voting, while "with-delegation" combines both delegated and own voting power and requires explicit undelegation. To migrate, replace your standalone voting strategies and "delegation" strategy with a single "with-delegation" strategy. The "multichain" strategy is being deprecated (effective August 15, 2025). Since Snapshot now has native multichain support, you should add each strategy individually with the appropriate network, then delete the old "multichain" strategy. You must migrate before August 2025 or you won't be able to create new proposals. ## Support and feedback **Basic support** (free, available to everyone): * Live chat accessible from any page in the Snapshot app * Average reply time under 5 minutes * Email follow-ups and community Discord **Premium support** (for Premium networks or Snapshot Pro spaces): * All basic support features * Dedicated Telegram group with direct access to the technical team * Prioritized feature development If you've discovered a vulnerability or security issue, please send an email to **[security@snapshot.org](mailto:security@snapshot.org)** with as much information as possible. Share your suggestions and upvote existing feature requests at [snapshot.canny.io/feature-requests](https://snapshot.canny.io/feature-requests). Please fill out the [partnership form](https://tally.so/r/w2axeK) and we'll get in touch with you soon. Before reporting, browse through this FAQ and our documentation. If you still have an issue, contact our support on [Help Center](/faq/support-and-feedback) with the following details: * Detailed description of the issue (what action were you trying to perform, what error did you get) * Screenshots of the error * Applicable URLs (proposal or space URL) ## Developers You can find the networks' IDs here: [snapshot-relayer check.ts](https://github.com/snapshot-labs/snapshot-relayer/blob/master/src/check.ts#L9) No, it's not needed. Yes. You can use [testnet.snapshot.box](https://testnet.snapshot.box) with an ENS domain on Sepolia Testnet. Snapshot uses IPFS to pin the receipts of the votes. Read more in the [IPFS case study](https://blog.ipfs.tech/2022-08-25-snapshot-ipfs-case-study/). Yes, however we encourage everyone to apply for a key as the limits for keyless access are much lower. Learn more in [API keys](/tools/api/api-keys). Yes. Without an API Key: 100 requests per minute. With an API Key: 2 million requests per month. Learn how to apply in [API keys](/tools/api/api-keys). Have a look at our [webhooks documentation](/tools/webhooks). Browse existing staking strategies at [snapshot.box](https://snapshot.box/#/?type=strategies\&q=stake). If none work for you, you can use the `erc20-balance-of` strategy if your contract has a `balanceOf` method, or the `contract-call` strategy if the balance method has a different name. Yes. If it's not supported yet you can create a custom voting strategy. Learn more in [voting strategy development](/developer-guides/voting-strategy). It usually takes around 72 hours. Once the PR is merged, you will also have to wait for a new release which can take another couple of days. # Snapshot Help Center Source: https://docs.snapshot.box/index ## What is Snapshot? Snapshot is a voting platform that allows DAOs, DeFi protocols, and NFT communities to vote easily and without gas fees. It supports flexible voting strategies, multiple voting systems, and fully customizable governance, all offchain and open source. ## Browse by topic Create and manage your organization's governance space. Create proposals and cast votes on decisions. Configure how voting power is calculated. Fully onchain governance on EVM and Starknet. Delegation, Safe voting, notifications, and more. Answers to the most common questions. # Edit a proposal Source: https://docs.snapshot.box/proposals/edit-a-proposal Learn how to edit a proposal before the voting period starts. If you're the author of a proposal on Snapshot, you can edit it while it's still in the **pending phase**, before the voting period starts. Look for the three-dot menu next to the proposal title to make your edits. Once the voting period has started, the proposal can no longer be edited. # Voting types Source: https://docs.snapshot.box/proposals/voting-types Learn more about the different voting schemes on Snapshot. Snapshot supports a number of different voting types and we plan to support many more in the future. If you would like to request a new voting type, please open a [feature request](https://snapshot.canny.io/feature-requests). ## What is a voting type? Voting type defines how users can cast their votes and how the final result is calculated. Do not mistake it with the voting strategy though - a [voting strategy](/user-guides/voting-strategies) is used to calculate the **individual voting power** of a user while the voting type calculates the **outcome of the proposal**. Voting type is defined in the space settings or at the level of an individual proposal (unless it has been already defined in the space settings) and can allow the users to: * Choose only **one option**, [#single-choice-voting](#single-choice-voting) * Spread their votes over **multiple options**, [#weighted-voting](#weighted-voting) * **Approve** a certain number of options, [#approval-voting](#approval-voting) * Spread their votes over multiple options using the [**quadratic voting**](https://en.wikipedia.org/wiki/Quadratic_voting) **formula**, [#quadratic-voting](#quadratic-voting) * Rank the different choices in their **order of preference**, [#ranked-choice-voting-instant-runoff-voting](#ranked-choice-voting-instant-runoff-voting) * **Abstain** from voting while still participating in quorum, [#basic-voting](#basic-voting) Let's have a look at each voting type in the next section. ## Voting types ### Single choice voting Each user can select only one option. The results will reflect these votes as percentages of the total voting power of all voting participants cast on the specific choice. Ideal for choosing one option from many. **Pros**: Most simple and common voting type which is easy to set up and use.\ **Cons**: Voters can pick only one option. [**Try it yourself**](https://snapshot.box/#/s:pistachiodao.eth/proposal/0x02c3fcd64e86157d07c88e5a715ac08f57655917f8bfd5be30a99092136511ec) ### Weighted voting Each user can spread their voting power across any number of choices, from one to all. Their voting power will be divided between their chosen options according to how much weight they attribute to each option by increasing or decreasing the voting power fraction. **Pros**: Allows voters to express support for more than one option and specify how much they support each of them.\ **Cons**: Requires more time and adds complexity to the voting process. This voting method was first introduced by Float Protocol with [Scattershot](https://github.com/FloatProtocol/scattershot) (a fork of Snapshot). [**Try it yourself**](https://snapshot.box/#/s:pistachiodao.eth/proposal/0xf93f1ac80e22cc930b1eef1d20bd34671ccc33b88b04695479c9de364451d77f) ### Approval voting Each user can select (*approve*) any number of choices, each selected choice will receive equal voting power, i.e. if user selects two choices, each choice will receive the total voting power of the user. **Pros**: Ask for approval of several decisions in a single proposal.\ **Cons**: There is no way to manifest *how much* you support each choice. It’s a simple yes or no. [**Try it yourself**](https://snapshot.box/#/s:pistachiodao.eth/proposal/0x08c3bd2960700525770a1d634f8599ba967e55fcc05b6c1649d984d88253769d) ### Quadratic voting Snapshot's Quadratic Voting (QV) type goes beyond the conventional approach of simply calculating the square root of each voter's voting power. It presents a more nuanced and democratic framework for decision-making. One of the main features of our QV type is its **emphasis on the number of individual voters** rather than the size of their voting power. By doing so, it ensures that every voice counts, thereby enhancing collective decision-making and preventing power concentration. Additionally, Snapshot's QV type provides voters with the flexibility to **distribute their voting power across multiple choices**. This feature allows for a more precise representation of a voter's diverse opinions, all without any additional cost. Drawing key principles from the Quadratic Funding model, our QV type **fosters greater participation and effectively balances influence**. It represents a significant advancement over simpler voting mechanisms that rely on basic square root calculations of voting power. #### **Let's have a look at an example:** Let's consider there are 3 voters and two choices, A and B: * Alice with 9 tokens * Bob with 4 tokens * Maria with 1 token * John with 1 token Here's how they allocate their tokens: * Alice allocates all her 9 tokens to A * Bob allocates all his 4 tokens to B * Maria allocates her 1 token to B * John allocates his 1 token to B This results in: * A having 9 tokens * B having 6 tokens Now, let's calculate the individual square root contributions for each choice: * A: the square root of Alice's 9 tokens is √9 = 3. * B: the square root of Bob's 4 tokens is √4 = 2, the square root of Maria's 1 token is √1 = 1, and the square root of John's 1 token is √1 = 1. Next, we add up the square root contributions for each choice and square the result: * A: we square the 3, so A gets 3^2 = 9. * B: we add 2, 1, and 1, giving us 4, and square it, so B gets 4^2 = 16. The total amount of tokens is 9 + 16 = 25. So the percentages for each choice are: * A: 9 / 25 = 36% * B: 16 / 25 = 64% As a last step, we match these percentages with the total voting power of 14 tokens: * A: 36% of 15 = 5.4 tokens * B: 64% of 15 = 9.6 tokens All in all, you don't have to understand each step of the calculation. Yet, it should give you an idea of how Alice with 9 tokens was not able to push through his choice despite having the majority of Voting Power in the group as our QV model emphasizes the **number of individual contributors** rather than the amount contributed. This voting type may encourage whales to create multiple wallets and split their holdings. It is important to also implement a [validation strategy](/user-guides/validation-strategies) providing Sybil resistance. **Pros**: Dilutes the whales' voting power in favor of smaller holders. Individuals will matter more than the number of tokens.\ **Cons**: This voting type needs to be accompanied by a [Sybil-resistance mechanism](/user-guides/validation-strategies) that prevents whales from splitting funds across different wallets. [**Try it yourself**](https://snapshot.box/#/s:pistachiodao.eth/proposal/0x21f64875abbca71762a980efae43ab62b546d54f19a208d0e61a5d7cee571a35) ### Ranked choice voting (Instant Runoff Voting) Each user has to rank all choices in a desired order. In the **first step** votes are counted for each voter's number one choice. If a choice receives more than 50% votes (cast on number one choices of each user), that choice wins. The result will show the percentages reflecting how users voted for their **first choice only**. In the **second step** if the first-choice candidate doesn't get over 50% of the total votes the choice with the **fewest** number one votes is **eliminated**. Voters who had chosen the defeated choice as number one now have their number two choice **counted as their number one** choice. The process continues over multiple rounds until a choice has more than half (> 50%) of the total votes. For more details, read [this discussion](https://github.com/snapshot-labs/snapshot/discussions/1624). Some options will show up as if they had **not received any votes** because they were **eliminated** in the ranked-choice voting process. **Pros**: Favors the option with the strongest support and reduces wasted votes.\ **Cons**: Complex to understand. Will only determine one winner, doesn’t work well to select 2 or more winning options. [**Try it yourself**](https://snapshot.box/#/s:pistachiodao.eth/proposal/0x5003da0f03e718b461e53fe10a998b60172e2e108472153282fcef781c300f23) ### Basic voting Each user can select one of three options: `For`, `Against`, `Abstain`. The votes cast on the `Abstain` choice are counted in calculating if the necessary quorum has been reached for a proposal to pass. **Pros**: Results are easy to interpret and hard to contest.\ **Cons**: Choices are predefined and cannot be edited. [**Try it yourself**](https://snapshot.box/#/s:pistachiodao.eth/proposal/0x38c654c0f81b63ea1839ec3b221fad6ecba474aa0c4e8b4e8bc957f70100e753) # Overview Source: https://docs.snapshot.box/snapshot-x/overview Snapshot X is a fully onchain voting protocol. Use these docs to learn how to create spaces, submit proposals, cast votes, and integrate with the protocol. **Non-technical documentation for the platform.** Go here if you want to create a space, proposal or cast a vote. **Technical documentation for Snapshot X protocol.** Go here if you want to understand the protocol architecture. **Overview of the services built for a better UX when interacting with the protocol.** Go here if you want to integrate Snapshot X in your platform. ## What is Snapshot X? **Snapshot X** is an onchain voting protocol that utilizes modular smart contracts for all operations, offering censorship resistance, onchain voting power computation, and trustless proposal execution. The difference with the original [Snapshot](https://snapshot.box) is that Snapshot X is **fully onchain**. What this means is: * **The protocol is censorship resistant**: Anyone can cast a vote. The protocol runs without any reliance on offchain or centralized services which have the power to censor votes. \[1] * **Voting power is computed onchain**: The voting logic is fully onchain and auditable so you can be sure of the logic used to compute voting power and decide on the outcome of proposals. * **The execution is trustless**: Proposal transactions are automatically executed following the passing of a proposal. Say you create a new proposal which, if it passes, will transfer 1 ETH to `vitalik.eth`. If the proposal passes, the 1 ETH will automatically get sent to `vitalik.eth`, without any further human action needed. Snapshot can be found on EVM-chains and on Starknet. Both the [EVM implementation](https://github.com/snapshot-labs/sx-evm) and the [Cairo implementation](https://github.com/snapshot-labs/sx-starknet) are open source. The Starknet's specific details can be found on [this dedicated page](/snapshot-x/protocol/starknet-specifics). If anything in these docs is unclear or you would like more detail, do not hesitate to reach out on [Discord](https://discord.snapshot.org). \[1] We note that there are in fact offchain services (eg the relayer Mana) built for use with Snapshot X, but these are not mandatory and therefore cannot lead to censorship. # Audits Source: https://docs.snapshot.box/snapshot-x/protocol/audits Snapshot X has completed a full audit with [ChainSecurity](https://chainsecurity.com) and [OpenZeppelin](https://openzeppelin.com). | Scope | Company | Date | Report | | ------------------- | ----------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------- | | Snapshot X EVM | [ChainSecurity](https://www.chainsecurity.com/) | 03-07-23 | [Download](https://github.com/snapshot-labs/sx-evm/blob/main/audits/ChainSecurity_Snapshot_Snapshot_X_audit.pdf) | | Snapshot X Starknet | [OpenZeppelin](https://www.openzeppelin.com/) | 10-31-23 | [Download](https://github.com/snapshot-labs/sx-starknet/blob/develop/audits/OpenZeppelin-SnapshotX-Audit.pdf) | | Snapshot X EVM | [Cairo Security Clan](https://cairosecurityclan.com/) | 16-06-25 | [Download](https://github.com/snapshot-labs/sx-evm/blob/main/audits/CSC_SnapshotX_audit.pdf) | # Authenticators Source: https://docs.snapshot.box/snapshot-x/protocol/authenticators Authenticators are the contracts in charge of **authenticating users** to create proposals and cast votes. **All proposal creation, proposal update, and vote transactions must be sent to the relevant DAO's space contract via an authenticator.** DAOs are free to write their own custom authenticators that suit their own needs however we provide the following approaches: ### Ethereum signature authenticator Will authenticate a user based on a message signed by an Ethereum private key. Users create an EIP712 signature for the transaction which is checked for validity in this contract. ```solidity theme={null} function authenticate( uint8 v, bytes32 r, bytes32 s, uint256 salt, address target, bytes4 functionSelector, bytes calldata data ) external; ``` * `v`,`r`,`s`: ECDSA Signature * `salt` : The salt used in the signature to prevention replays (only required for proposal creation and updating). * `target`: The destination space contract. * `functionSelector`: The function selector of the desired action. * `data`: The ABI encoded transaction payload for the action. Refer to the [Space actions](/snapshot-x/protocol/space-actions) section for more information on the payload contents. This can work in conjunction with a meta transaction relayer to allow proposal creation or vote costs to be sponsored by the DAO, providing a free end user experience. ### Ethereum transaction authenticator Will authenticate a user by checking if the caller address corresponds to the `author` or `voter` address. ```solidity theme={null} function authenticate(address target, bytes4 functionSelector, bytes calldata data) external; ``` * `target`: The destination space contract. * `functionSelector`: The function selector of the desired action. * `data`: The ABI encoded transaction payload for the action. Refer to the [Space actions](/snapshot-x/protocol/space-actions) section for more information on the payload contents. The core use case for this authenticator is to allow **smart contract accounts such as multisigs to use Snapshot X** as they have no way to generate a signature and therefore cannot authenticate via signature verification. ### And more! Our modular approach here allows spaces to **authenticate users via other authentication methods without any changes to the space contract**. Please note, that if you wanted to add sybil resistance to your governance process, this should not be handled by Authenticators, but by [Proposal validations](/snapshot-x/protocol/proposal-validations) or [Voting strategies](/snapshot-x/protocol/voting-strategies). # Execution strategies Source: https://docs.snapshot.box/snapshot-x/protocol/execution-strategies Execution Strategies have two key roles: 1. **Determining the status of a proposal at any time**, 2. **Executing the payload of a proposal if it has been accepted**. Each proposal should have an Execution strategy set when it is created. This consists of a strategy contract address, along with an execution payload. This page provides more details on the Execution strategies along with the implementations that we offer. ## Proposal status Every execution strategy should have a public view function `getProposalStatus` with the following interface: ```solidity theme={null} function getProposalStatus( Proposal memory proposal, uint256 votesFor, uint256 votesAgainst, uint256 votesAbstain ) external view returns (ProposalStatus); ``` This function takes the proposal state as input and returns the proposal status defined by a `ProposalStatus` enum. This enum contains all of the possible states the proposal can be in: ```solidity theme={null} enum ProposalStatus { VotingDelay, VotingPeriod, VotingPeriodAccepted, Accepted, Executed, Rejected, Cancelled } ``` Note that because of having separate `minVotingDuration` and `maxVotingDuration` , we have two separate statuses for inside the voting period: `VotingPeriod` and `VotingPeriodAccepted`. Abstracting status functionality outside of the space contract allows far greater flexibility in governance mechanisms since users can define their own logic on exactly how the status is determined. We provide the following implementations: ### [Simple Quorum](https://github.com/snapshot-labs/sx-evm/blob/main/src/execution-strategies/SimpleQuorumExecutionStrategy.sol) A proposal is accepted if `FOR` votes exceed `AGAINST` votes and the total votes (`FOR` + `AGAINST` + `ABSTAIN` ) exceed the `quorum`. Has a single parameter `quorum` which is set when the strategy is deployed. This is the standard approach that we expect to be used most often. ### [Optimistic Quorum](https://github.com/snapshot-labs/sx-evm/blob/main/src/execution-strategies/OptimisticQuorumExecutionStrategy.sol) A proposal is rejected if `AGAINST` votes exceed the `quorum`, otherwise, it is accepted. It has a single parameter `quorum` that is set when the strategy is deployed. This approach unlocks **optimistic governance mechanisms** where proposals are assumed to be accepted unless DAO members choose otherwise by voting against. This can lead to a far higher level of governance efficiency as it reduces the number of onchain transactions for 'non-controversial' proposals. ### [Emergency Quorum](https://github.com/snapshot-labs/sx-evm/blob/main/src/execution-strategies/EmergencyQuorumExecutionStrategy.sol) It has two parameters: `quorum` and `emergencyQuorum`, where `emergencyQuorum` should be set greater than `quorum`. If the total votes are less than `emergencyQuorum`, then the proposal status is computed in the same way as Simple Quorum with the `quorum` parameter. However if the higher `emergencyQuorum` is met, then the `minVotingDuration` is **ignored** and a proposal can be **executed early.** This can be useful for emergency actions in response to critical events such as hacks, where one can expect much higher participation in the governance vote than during normal processes, and therefore a 'tradeoff' between proposal duration and proposal participation can be made. ## Proposal execution If the proposal status is `Accepted` (or `VotingPeriodAccepted`) the Execution strategy should then execute the proposal payload. We provide the following payload executor implementations: ### [Safe module (Zodiac)](https://github.com/snapshot-labs/sx-evm/blob/main/src/execution-strategies/AvatarExecutionStrategy.sol) An execution strategy that allows proposals to execute transactions from a specified `target` [Avatar](https://github.com/gnosis/zodiac/blob/master/contracts/interfaces/IAvatar.sol) contract, the most popular one being a Safe. To use this strategy in a proposal, you must whitelist the space in the strategy, this can either be done at deployment or using the `enableSpace` function. The proposal payload should consist of an ABI encoded array of type `MetaTransaction[]` with the following format: ```solidity theme={null} struct MetaTransaction { address to; uint256 value; bytes data; Enum.Operation operation; uint256 salt; } ``` ### [Timelock](https://github.com/snapshot-labs/sx-evm/blob/main/src/execution-strategies/timelocks/TimelockExecutionStrategy.sol) An execution strategy that is itself a Timelock contract. A `timelockDelay` is specified when the Timelock is deployed. When a proposal with this strategy is executed, the proposal transactions are queued in the Timelock for `timelockDelay` seconds before they can be executed. The proposal payload should consist of an ABI encoded array of type `MetaTransaction[]` with the following format: ```solidity theme={null} struct MetaTransaction { address to; uint256 value; bytes data; Enum.Operation operation; uint256 salt; } ``` There is also an optional `vetoGuardian` role that has the power **to `veto` a queued proposal.** ### And more! Feel free to create your own Execution strategies! The interface of a strategy can be found [here](https://github.com/snapshot-labs/sx-evm/blob/main/src/interfaces/IExecutionStrategy.sol). # Overview Source: https://docs.snapshot.box/snapshot-x/protocol/overview Snapshot X's main contract is the **Space** contract. Proposals are created, votes are cast, and all of the proposal state is stored here. Beyond this however, the majority of the protocol functionality has been abstracted out of the Space contract. These abstractions consist of: * [Who can create a proposal](/snapshot-x/protocol/proposal-validations). * [How users are authenticated](/snapshot-x/protocol/authenticators). * [How the voting power is determined](/snapshot-x/protocol/voting-strategies). * [How a proposal passes and how it's being executed](/snapshot-x/protocol/execution-strategies). This approach allows a far higher degree of modularity and customisability than what would be possible if all of this logic was handled directly by the Space contract itself. Creating a space on Snapshot X is **like creating a new character in a game**. First you need to select an armour to protect your character, then you need to decide on a weapon (spear, sword, bow). Finally, you need to choose a mount for your character to get him to travel from town to town faster. With that analogy in mind, think about the **Space** contract like the character, and the [**Authenticators**](/snapshot-x/protocol/authenticators), [**Proposal validation strategies**](/snapshot-x/protocol/proposal-validations), [**Voting strategies**](/snapshot-x/protocol/voting-strategies)**,** and [**Execution strategies**](/snapshot-x/protocol/execution-strategies) like the different add-ons you need to decide on. We refer to them collectively as **Snapshot X Modules**. Let's go over those briefly: **Authenticators** \ Determine how the participants can be *authenticated* to create a proposal or cast a vote. In general this will be some kind of signature or transaction caller verification. **Proposal validation strategies**\ Determine how an author is validated to create a proposal. A common approach is checking that the author exceeds a certain threshold proposition power calculated through a set of strategies. **Voting strategies**\ Determine how the voting power is computed. Voting strategies are custom contracts that allow you to determine how you compute the voting power of each participant in the vote. Arbitrary logic can be implemented here to create complex and expressive governance mechanisms. The most common way of voting is voting with your tokens (1 token = 1 voting power, so if you have 100 tokens you get a total voting power of 100). This is a voting strategy. But you could imagine other voting strategies: for example, only give voting power to the owners of a specific NFT. Or maybe use a quadratic model, where users only get the square root of their token balance (to minimise the power of whales). **Execution strategies**\ Have two key roles: 1\) Determine the *status* of a proposal at any time during its lifetime. 2\) Determine *what should happen* once a proposal passes. This latter role will generally consist of executing a set of transactions linked to the proposal. The strategy can control which contracts are authorised to execute the transactions or alternatively execute them directly itself. This modularity allows anyone to extend the basic protocol to suit their requirements. We provide a set of pre-built and audited modules but **we invite you to write your own!** ## So what does the flow look like? The full usage flow looks like this: 1. A DAO deploys a **Space** contract and defines space settings along with a set of authenticators, voting strategies, and a proposal validation strategy. 2. A user can create a **proposal** in the **Space** via a whitelisted authenticator. The proposal validation strategy is queried to check that the user is eligible to create the proposal. \ To create a proposal, the proposer has to specify an execution strategy contract along with an execution payload that will contain the encoded set of transactions inside the proposal. 3. Users can vote on the proposal by authenticating through one of the whitelisted authenticator contracts. 4. Once the voting period has ended, anyone can execute the proposal permissionlessly. This will forward the execution payload to the execution strategy and execute the transactions included. The below diagram showcases an example of how the contracts that make up Snapshot X fit together along with various actions users can take to create proposals, vote, execute proposals, and update settings. [https://whimsical.com/snapshot-x-evm-onchain-architecture-M3d8bU1V2Z7r6kbVUM9g2w](https://whimsical.com/snapshot-x-evm-onchain-architecture-M3d8bU1V2Z7r6kbVUM9g2w) If you are planning to integrate Snapshot X into your own product, head to [SX.js](/snapshot-x/services/sx-js) section to learn about our SDK. # Proposal validations Source: https://docs.snapshot.box/snapshot-x/protocol/proposal-validations **Proposal validation strategy is used to determine whether a particular `author` is allowed to create a proposal.** Each Space has to set a proposal validation strategy which consists of an address and a set of `params` that are stored in the space. These strategies should have the following interface: ```solidity theme={null} function validate(address author, bytes calldata params, bytes calldata userParams) external returns (bool); ``` * `author`: The author of the proposal. * `params`: Parameter array set in the space contract that is the same for every user of the Strategy. * `userParams`: Parameter array submitted by the `author` when they create a proposal, and can therefore be different for each user. There is no requirement to use either of these parameter arrays in your strategy, in which case you can just pass an empty array. DAOs are free to write their own custom strategies that suit their own needs however we provide the following approaches: ### Proposition power A strategy that validates an `author` to create a proposal if their `propositionPower` calculated from a set of Voting strategies exceeds a `proposalThreshold` value. It means that if the proposal threshold is set to `5`, the author needs to have at least `5` Proposition power to create a proposal. This strategy uses the same logic as [Voting strategies](/snapshot-x/protocol/voting-strategies), so refer to that section for more information. When calling this strategy, `params` should be: ```solidity theme={null} uint256 proposalThreshold = ... Strategy[] allowedStrategies ... params = abi.encode(proposalThreshold, allowedStrategies); ``` `userParams` should contain the indexed strategies that the `author` has power with: ```solidity theme={null} IndexedStrategy[] userStrategies = ... userParams = abi.encode(userStrategies); ``` ### Active proposal limiter A strategy that validates an `author` to create a proposal if the `author` has not exceeded a limit of `maxActiveProposals`. Each time an `author` creates a proposal, a counter is incremented up to a limit of `maxActiveProposals`. After this point, no more proposals can be created until a `cooldown` period has elapsed since the most recent proposal they created. Using this strategy can help to prevent proposal creation spam in your space. ### And more! These strategies can be combined and extended to provide flexible Proposal validation mechanisms. The interface for Proposal validation strategies can be found [here](https://github.com/snapshot-labs/sx-evm/tree/main/src/proposal-validations). # Space actions Source: https://docs.snapshot.box/snapshot-x/protocol/space-actions [Space](https://github.com/snapshot-labs/sx-starknet/blob/develop/starknet/src/space/space.cairo) is the core contract: it's in charge of tracking proposals, votes, and general settings. In this section we will go into detail on how to deploy a space, and the various user actions that can take place. ### Deploying a space Space should be deployed via the **Proxy Factory contract**, which emits deployment events that will get indexed by the [SX-API](/snapshot-x/services/api). To reduce deployment costs and to enable upgradability, we use ERC-1967 proxies and follow Open Zeppelin's [UUPS Upgradability pattern](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable) on the space contract implementation. After deploying the proxy you should call the `initialize` function with the initial set of Space settings. ```solidity theme={null} function initialize( address owner, uint32 votingDelay, uint32 minVotingDuration, uint32 maxVotingDuration, Strategy memory proposalValidationStrategy, string memory proposalValidationStrategyMetadataURI, string memory daoURI, string memory metadataURI, Strategy[] memory votingStrategies, string[] memory votingStrategyMetadataURIs, address[] memory authenticators ) external; ``` * `owner`: The address of the account that controls the Space contract. This account will have permissions to update space settings, cancel a proposal, and authorize an upgrade to the implementation. If you would like to remove this trust assumption, the owner can be renounced. Refer to the [Space controller actions](/snapshot-x/protocol/space-controller-actions) section for more information. * `votingDelay`: The delay between when a proposal is created, and when the voting starts. A value of 0 means that as soon as the proposal is created anyone can vote whilst a value of 3600 means that voting will start 3600 seconds after the proposal is created. * `minVotingDuration`: The minimum duration of the voting period. It is **impossible to execute a proposal before** **this period** has elapsed. * `maxVotingDuration`: The maximum duration of the voting period, it is **impossible to cast a vote after this period** has passed. The `minVotingDuration` must be less than or equal to this value. * `proposalValidationStrategy`: A strategy that validates whether an author can create a proposal. The strategy consists of a contract address where the strategy lives, along with a set of parameters that configure it for the particular usage. More information in the [Proposal validation strategy](/snapshot-x/protocol/proposal-validations) section. * `proposalValidationStrategyMetadataURI`: A metadata URI corresponding to the `proposalValidationStrategy`. * `daoURI`: A metadata URI as defined in ERC-4824. * `metadataURI`: The metadata URI for the space (its name, description, social tags and treasury address). * `votingStrategies`: An array of voting strategies selected for the space. The voting power of each user will be calculated as the sum of voting powers returned for each strategy in the list for that user. More information in the [Voting strategies](/snapshot-x/protocol/voting-strategies) section. * `votingStrategyMetadataURIs`: An array of metadata URIs corresponding to the `votingStrategies` array. * `authenticators`: An array of whitelisted authenticators. These are the ways in which a user can authenticate themselves in order to vote or propose. More information in the [Authenticators](/snapshot-x/protocol/authenticators) section. Each DAO on Snapshot X will have at least one space, however a DAO might choose to have multiple spaces if they want to create different rules for individual proposals. As an example one space can use an Ethereum signature as an authentication, another an Ethereum transaction. ### Creating a proposal Once a space has been created, users can create new proposals by calling the `propose` method. Inside `propose`, the Proposal Validation Strategy is called to validate `author` upon creating a proposal. ```solidity theme={null} function propose( address author, string calldata metadataURI, Strategy calldata executionStrategy, bytes calldata userProposalValidationParams ) external; ``` * `author`: The address of the proposal author. * `metadataURI`: The metadata URI of the proposal. * `executionStrategy`: The execution strategy that should be used to execute a proposal if it is accepted. The strategy consists of a contract address where the strategy lives, along with an encoded execution payload. More information in the [Execution strategies](/snapshot-x/protocol/execution-strategies) section. * `userProposalValidationParams`: An array of parameters that will be passed to the Proposal Validation Strategy for the Space. Since the proposal is created via an authenticator, the exact external interface for creating a proposal will depend on the interface of the chosen authenticator. ### Updating a proposal Provided that the `votingDelay` has not elapsed yet, the proposal `author` can update the proposal metadata and execution strategy. This allows mistakes in the initial proposal to be fixed. ```solidity theme={null} function updateProposal( address author, uint256 proposalId, Strategy calldata executionStrategy, string calldata metadataURI ) external; ``` * `author`: The address of the proposal author. * `proposalId`: The unique ID of the proposal in the space. IDs are assigned incrementally to proposals based on when the proposal was created. * `executionStrategy`: The updated execution strategy that should be used to execute a proposal if it is accepted. The strategy consists of a contract address where the strategy lives, along with an encoded execution payload. More information in the [Execution strategies](/snapshot-x/protocol/execution-strategies) section. * `metadataURI`: The updated metadata URI of the proposal. Since the proposal is updated via an authenticator, the exact external interface for updating a proposal will depend on the interface of the chosen authenticator. ### Casting a vote Once a proposal has been created, and the `votingDelay` has elapsed, users can then vote for the proposal. ```solidity theme={null} function vote( address voterAddress, uint256 proposalId, Choice choice, IndexedStrategy[] calldata userVotingStrategies, string calldata metadataURI ) external; ``` * `voter`: The address of the voter. * `proposalId`: The unique ID of the proposal in the space. IDs are assigned incrementally to proposals based on when the proposal was created. * `choice`: The vote choice: `FOR`, `AGAINST`, or `ABSTAIN`. * `userVotingStrategies`: An array of voting strategies that should be iterated through to calculate the voter's voting power. The strategies in this array must be whitelisted by the space however there is no requirement to pass all of the whitelisted strategies. This could be useful when a user knows that they only have voting power on a subset of the whitelisted strategies and therefore can save gas by only passing strategies that they know they have non zero voting power on. * `metadataURI`: The metadata URI for the vote. Since the vote is cast via an authenticator, the exact external interface for casting a vote will depend on the interface of the chosen authenticator. ### Execute a proposal Calling the `execute` function on the space will call the execution strategy with the proposal state along with the execution payload. The execution strategy will then use the proposal state to compute the status of the proposal. If the proposal status is deemed to be `Accepted,` then the payload will be automatically executed by the strategy. If the proposal status is not `Accepted` (or `VotingPeriodAccepted`), then the transaction will revert. Note that there is no caller authentication on `execute`, simply call the`execute` method on the Space contract directly: ```solidity theme={null} function execute(uint256 proposalId, bytes calldata executionPayload) external; ``` * `proposalId`: The ID of the proposal. * `executionPayload`: The payload of the execution. This must be the same as the payload passed when a proposal was created. We require the payload to be resubmitted because we don't store it inside the proposal state, instead, we just store its hash. ### Querying the proposal status We provide the following view function to access the proposal status at any time. ```solidity theme={null} function getProposalStatus(uint256 proposalId) external view returns (ProposalStatus proposalStatus); ``` The status of a proposal is actually defined by the chosen Execution strategy rather than the space itself, therefore this query actually makes an internal call to the Execution strategy of the proposal. Refer to the [Execution strategies](/snapshot-x/protocol/execution-strategies) section for more information. * `proposalId`: The ID of the proposal to query. * `voter`: The address of the voter to query. * `proposal`: The proposal state struct object, defined [here](https://github.com/snapshot-labs/sx-evm/blob/aaed4d0dd2ad915e05fb7bad094f587fed113f7b/src/types.sol#L8). * `proposalStatus`: The status of a proposal at the timestamp when queried. This function will send an internal call to the `getProposalStatus` method on the Execution strategy. Refer to the [Execution strategies](/snapshot-x/protocol/execution-strategies) section for more information. ### ERC-4824: Decentralized Autonomous Organizations The Space contract implements ERC-4824 which is a standard URI and JSON schema for DAOs, focusing on relating onchain and offchain representations of membership and proposals. More information can be found [here](https://ethereum-magicians.org/t/erc-4824-decentralized-autonomous-organizations/8362). The standard adds a `daoURI` string to the space settings which can be queried using the following interface: ```solidity theme={null} interface EIP4824 { function daoURI() external view returns (string _daoURI); } ``` # Space controller actions Source: https://docs.snapshot.box/snapshot-x/protocol/space-controller-actions In this section we will go over the actions that can be made by the Space Controller. Note that we use Open Zeppelin's [`OwnableUpgradable`](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/access/OwnableUpgradeable.sol) module to gate access to this functions, and therefore at the contract level we use the term `owner` instead of `controller`. ### Cancel a proposal A proposal can be cancelled as long as it has not already been executed. ```solidity theme={null} function cancel(uint256 proposalId) external; ``` * `proposalId`: The ID of the proposal This can be used to prevent damage from malicious or broken proposals. ### Update space settings All Space settings can be updated using the `updateSettings` function: ```solidity theme={null} function updateSettings(UpdateSettingsInput calldata input) external; struct UpdateSettingsInput { uint32 minVotingDuration; uint32 maxVotingDuration; uint32 votingDelay; string metadataURI; string daoURI; Strategy proposalValidationStrategy; string proposalValidationStrategyMetadataURI; address[] authenticatorsToAdd; address[] authenticatorsToRemove; Strategy[] votingStrategiesToAdd; string[] votingStrategyMetadataURIsToAdd; uint8[] votingStrategiesToRemove; } ``` A single entrypoint is used instead of separate ones for each value so that a single transaction can be used to update a large number of settings. This improves the UX while also preventing undesired behaviour that may arise if proposals are created half way though the settings update process. If one does not want to update a certain value, then the following placeholder values can be used in the function call (arrays can just be left empty): ```solidity theme={null} /// @dev Evaluates to: `0xf2cda9b13ed04e585461605c0d6e804933ca828111bd94d4e6a96c75e8b048ba`. bytes32 NO_UPDATE_HASH = keccak256(abi.encodePacked("No update")); /// @dev Evaluates to: `0xf2cda9b13ed04e585461605c0d6e804933ca8281`. address NO_UPDATE_ADDRESS = address(bytes20(keccak256(abi.encodePacked("No update")))); /// @dev Evaluates to: `0xf2cda9b1`. uint32 NO_UPDATE_UINT32 = uint32(bytes4(keccak256(abi.encodePacked("No update")))); Strategy NO_UPDATE_STRATEGY = Strategy(NO_UPDATE_ADDRESS, new bytes(0)); ``` Note that Space setting updates will not affect the functioning of ongoing proposals at the time of the settings update since we store the necessary settings data inside the state of each proposal. ### Upgrade implementation A Space contract's implementation can be upgraded to a new version using the following methods: ```solidity theme={null} function upgradeTo(address newImplementation) external; function upgradeToAndCall(address newImplementation, bytes memory data) external; ``` * `newImplementation`: The address of the new space implementation. * `data`: A encoded function call to initialize the new implementation. Refer to [Open Zeppelin's UUPS guide](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable) for more information. ### Manage ownership ```solidity theme={null} function transferOwnership(address newOwner) external; function renounceOwnership() external; ``` The `owner` can be transferred to a new address or renounced entirely. # Starknet specifics Source: https://docs.snapshot.box/snapshot-x/protocol/starknet-specifics ### What's special here? Starknet having its own language (Cairo) and being a ZK Rollup, there are some Starknet specific details. The Snapshot X Starknet implementation allows DAOs to govern their L1 DAO trustlessly, with very little fees and no user friction. Indeed, users do not have to bridge their tokens, nor do they need to create and install a Starknet wallet. This is all handled seamlessly by the Snapshot X protocol by taking advantage of the existing native bridge, some storage proofs, and a transaction relayer. ### Overview This diagram represents the flow of a proposal that will get executed on L1, with voters using their regular EVM account to vote.\\ [https://whimsical.com/storageproofs-7kjLqMvsR3okzFgMrad9Fu](https://whimsical.com/storageproofs-7kjLqMvsR3okzFgMrad9Fu) ### Storage proofs In a nutshell, storage proofs are cryptographic proofs that a user had this token or that NFT in their wallet at a specific moment in time. We use them to compute the voting power of any user at the moment the proposal started, without the user having to bridge their tokens. This technology developed in collaboration with [Herodotus](https://herodotus.dev/), allows for a trustless balance verification that we can use to compute the voting power of users. The exact code for verifying a storage value can be found [here](https://github.com/snapshot-labs/sx-starknet/blob/develop/starknet/src/utils/single_slot_proof.cairo). 1. A user creates a proposal. The space registers it and [stores the start timestamp](https://github.com/snapshot-labs/sx-starknet/blob/03041771ba701a6ce0d5a95b4ead290add115348/starknet/src/space/space.cairo#L259). 2. When the proposal starts, the space caches the block number on L1 that corresponds to the stored `start timestamp`. To do that, we use [Herodotus' timestamp remapper contract](https://docs.herodotus.dev/herodotus-docs/protocol-design/timestamp-to-block-number-mapper). 3. Later on, when a user vote, he provides a storage proof of his balance at the block cached by the space. The space then provides the `storage_proof`, the `block_number`, and the `l1_contract_address` to [Herodotus' Facts Registry](https://docs.herodotus.dev/herodotus-docs/developers/contract-addresses) for verification. 4. If the verification succeeds, the space can safely accept the vote, the `voting_power` of the user having been correctly proven and verified. For OpenZeppelin ERC20Votes tokens, the function `get_past_votes` is reproduced in [this voting strategy](https://github.com/snapshot-labs/sx-starknet/blob/03041771ba701a6ce0d5a95b4ead290add115348/starknet/src/voting_strategies/oz_votes_storage_proof.cairo#L29) by proving two values: we first verify the checkpoint `c` containing the number of delegated power ; and then verify that the checkpoint `c + 1` is empty (ensuring that `c` was indeed the latest checkpoint). As a last detail, the `Checkpoint` structure got changed by OpenZeppelin to a Checkpoint 208, so we [also support this version](https://github.com/snapshot-labs/sx-starknet/blob/develop/starknet/src/voting_strategies/oz_votes_trace_208_storage_proof.cairo). ### Transaction relayer In order to avoid the overhead of installing and managing a Starknet account, we ask users to sign their vote with their Ethereum wallet, and then simply relay the transaction on the Starknet network using our transaction relayer [Mana](/snapshot-x/services/mana). Once the transaction is relayed, and by leveraging the modularity of our authenticators system, a [special authenticator](https://github.com/snapshot-labs/sx-starknet/blob/develop/starknet/src/authenticators/eth_sig.cairo) verifies the provided signature and lets the vote be counted in! But who pays for the relaying fees? It is expected that DAOs who want to provide their users with this ease of vote would be the paying those fees, which should be minimal anyway! ### L1 execution Once the proposal has ended, and if the proposal has been accepted, then the transaction can be broadcast back to our [L1 Avatar Execution Strategy](https://github.com/snapshot-labs/sx-starknet/blob/develop/ethereum/src/execution-strategies/L1AvatarExecutionStrategy.sol) contract. This module works hand in hand with Zodiac's Avatar (e.g a Safe), and allows the transactions attached to the proposal to be executed directly on the avatar! # Voting strategies Source: https://docs.snapshot.box/snapshot-x/protocol/voting-strategies Voting strategies are the contracts used to **determine the voting power (VP) of users**. Voting strategies can be created in a **permissionless** way, however, to use one, one must whitelist the strategy in the space contract for your DAO. The most common example is using the ERC-20 token balance of a user to determine their voting power. But you could imagine other voting strategies: owning a specific NFT, owning NFT of collection X and another NFT of collection Y, having participated in protocol XYZ... the possibilities are endless! We are fans of the [Turing Complete Governance](https://baby.mirror.xyz/O7a922A-9zT4C4UwssRExkftdHywJ-13sR2rxQ-t__k), the concept of a governance system with arbitrary programmability. This will allow complex and expressive mechanisms of coordination to be seamlessly integrated into governance decisions. Snapshot X reaches this standard, and we are excited to see what people build! **All voting strategies must have the following** [**interface**](https://github.com/snapshot-labs/sx-evm/blob/main/src/interfaces/IVotingStrategy.sol)**:** ```solidity theme={null} function getVotingPower( uint32 blockNumber, address voterAddress, bytes calldata params, bytes calldata userParams ) external returns (uint256); ``` `getVotingPower` is called internally by the space contract when a vote is cast. `timestamp` is the snapshot at which voting power is calculated for all users. We use a **timestamp rather than a block number** to better enable multi-chain applications since a timestamp is universal to all chains. There are two sets of parameters for each voting strategy, `params` and `userParams`. * `params` are set in the space contract and are the same for every user who calls that strategy in the space, they act as configuration parameters for a strategy. An example here is a token contract address that will be queried, or a constant scaling factor that should be applied to the VP returned for every user. * `userParams` are submitted by users when they create a proposal or cast a vote, and can therefore be different for each user. An example here is storage proof. There is no requirement to use either of these parameter arrays in your strategy, in which case you can just pass an empty array. When a user casts a vote, the array of whitelisted Voting strategies will be iterated through and `getVotingPower` will be called on each. The VP of the user will be the aggregate of the voting power from each strategy. The aggregate Voting power for all users is also stored inside a `Uint256`, therefore when writing or selecting voting strategies, it is **important to consider the likelihood of overflow**. DAOs are free to write their own custom strategies that suit their own needs however we provide the following approaches: ### [Compound Style Checkpoint Token](https://github.com/snapshot-labs/sx-evm/blob/main/src/voting-strategies/CompVotingStrategy.sol) A strategy that allows delegated balances of Compound style checkpoint tokens to be used as Voting power. To use this strategy, your token must have the following interface exposed: ```solidity theme={null} function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96); ``` When calling this strategy, `params` should be: ```solidity theme={null} params = abi.encodePacked(tokenAddress) ``` `userParams` is not needed. ### [OpenZeppelin Style Checkpoint Token](https://github.com/snapshot-labs/sx-evm/blob/main/src/voting-strategies/OZVotesVotingStrategy.sol) A strategy that allows delegated balances of OpenZeppelin style checkpoint tokens to be used as Voting power. To use this strategy, your token must have the following interface exposed: ```solidity theme={null} function getPastVotes(address account, uint256 blockNumber) external view returns (uint256); ``` When calling this strategy, `params` should be: ```solidity theme={null} params = abi.encodePacked(tokenAddress) ``` `userParams` is not needed. ### [Whitelist](https://github.com/snapshot-labs/sx-evm/blob/main/src/voting-strategies/WhitelistVotingStrategy.sol) A strategy that returns a specified Voting power for addresses that are within a whitelist, and zero otherwise. Having a customisable VP for each user allows more fine-grained control than enforcing a VP of 1 for everyone - which can still be achieved by just setting the value to 1 for each member of the list. Each member of the whitelist should be represented as the struct: ```solidity theme={null} struct Member { address addr; uint256 vp; } ``` When calling this strategy, `params` should then be an ABI encoded array of type `Member[]` where the members are sorted into ascending order based on their `addr`. ``` Member[] members = ... params = abi.encode(members) ``` `userParams` is not needed. ### And more! Feel free to create your own strategies! We hope that the flexibility of the system will unlock a new era of programmable onchain governance. The interface of a strategy can be found [here](https://github.com/snapshot-labs/sx-evm/blob/main/src/interfaces/IVotingStrategy.sol). # API Source: https://docs.snapshot.box/snapshot-x/services/api The API indexes Snapshot X data. Specifically, it monitors events emitted by spaces and space factories so that votes, proposals, and the deployment of new spaces can be tracked. Anyone can run the API. It uses [Checkpoint](https://checkpoint.box) and support multiple chains. #### GitHub [https://github.com/snapshot-labs/sx-monorepo/tree/master/apps/api](https://github.com/snapshot-labs/sx-monorepo/tree/master/apps/api) #### Public APIs Mainnets: [https://api.snapshot.box](https://api.snapshot.box/)\ Testnets: [https://testnet-api.snapshot.box](https://testnet-api.snapshot.box/) # Overview Source: https://docs.snapshot.box/snapshot-x/services/architecture **Snapshot X** is a fully onchain voting protocol deployed on EVM chains and Starknet. It consists of modular smart contracts that handle proposal creation, voting, and execution without reliance on any centralized service. Key properties: * **Censorship resistant:** the protocol runs entirely onchain with no centralized dependencies. * **Onchain voting power:** voting logic is fully onchain and auditable. * **Trustless execution:** proposal transactions are automatically executed when a proposal passes. Both the [EVM implementation](https://github.com/snapshot-labs/sx-evm) and the [Starknet implementation](https://github.com/snapshot-labs/sx-starknet) are open source. ## Services To enhance the user experience of interacting with the protocol, Snapshot Labs provides a number of additional offchain services. All are fully open source and completely optional - they do not introduce any censorship concerns. * [**API**](/snapshot-x/services/api): A fast indexer for all protocol data. * [**SX.js**](/snapshot-x/services/sx-js): A TypeScript SDK for building integrations with the protocol. * [**UI**](/snapshot-x/services/ui): An interface for interacting with the protocol. * [**Mana**](/snapshot-x/services/mana): A meta-transaction relayer that sponsors proposal creation and vote costs. # Mana Source: https://docs.snapshot.box/snapshot-x/services/mana Mana is a meta-transaction relayer that allows users to interact with Snapshot X without paying gas fees. This service works in conjunction with signature based Snapshot X [authenticators](/snapshot-x/protocol/authenticators). Users sign a meta transaction in the SX UI and then the relayer submits each encoded transaction along with its signature to the signature authenticator. If the signature is valid, then the transaction will be forwarded to the relevant space contract. The system included a mechanism that allows DAOs to fund the transactions sent by the relayer, enabling the free end user experience. However importantly, users can directly interact with Snapshot X and therefore do not rely on trusting the relayer to not censor votes. Additionally, Anyone can run a relayer if they want to take over the sponsoring of transactions. Note that currently Mana only supports proposal creation, proposal updates, and vote casting transactions. It does not currently support proposal execution or space controller actions. #### GitHub [https://github.com/snapshot-labs/sx-monorepo/tree/master/apps/mana](https://github.com/snapshot-labs/sx-monorepo/tree/master/apps/mana) #### Public API [https://mana.box](https://mana.box) # SX.js Source: https://docs.snapshot.box/snapshot-x/services/sx-js SX.js is the official Typescript SDK to interact with Snapshot X. The SDK includes a client for Mana, the meta transaction relayer. #### GitHub [https://github.com/snapshot-labs/sx-monorepo/tree/master/packages/sx.js](https://github.com/snapshot-labs/sx-monorepo/tree/master/packages/sx.js) ## Quick start ### Installation Install the latest version of the beta release: ```bash theme={null} npm install @snapshot-labs/sx@beta ``` ```bash theme={null} yarn add @snapshot-labs/sx@beta ``` ```bash theme={null} bun add @snapshot-labs/sx@beta ``` ### Configuration #### Clients Everything happens thanks to the `clients` objects. Depending on the specific Space or Proposal setup, you may need to use a Transaction or Signature Client. This quick guide demonstrates how to easily set all of them up, both for Ethereum and StarkNet: ```typescript theme={null} import { clients, evmSepolia } from '@snapshot-labs/sx'; const clientConfig = { networkConfig: evmSepolia } const client = new clients.EthereumTx(clientConfig); const ethSigClient = new clients.EthereumSig(clientConfig); ``` ```typescript theme={null} import { clients } from '@snapshot-labs/sx'; import { Provider, constants } from 'starknet'; const ethUrl = 'https://rpc.snapshot.org/1'; const manaUrl = 'https://mana.pizza'; const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_SEPOLIA } }); const clientConfig = { starkProvider, manaUrl, ethUrl }; const client = new clients.StarkNetTx(clientConfig); const starkSigClient = new clients.StarkNetSig(clientConfig); ``` To learn more about StarkNet's `Provider` object, have a look [here](https://www.starknetjs.com/docs/guides/connect_network). ## Usage Make sure to use the right client for your use case. The examples below use Sepolia network and its config is imported from the `sx.js` package. ### Cast a vote ```typescript theme={null} import { clients, evmSepolia } from '@snapshot-labs/sx'; import type { Web3Provider } from '@ethersproject/providers'; const clientConfig = { networkConfig: evmSepolia } const client = new clients.EthereumTx(clientConfig); const web3 = new Web3Provider(window.ethereum); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', strategies: [ { address: '0xc1245c5dca7885c73e32294140f1e5d30688c202', index: 0 } ], proposal: 7, choice: 1, metadataUri: '' }; const receipt = await client.vote({ signer: web3.getSigner(), envelope: { data } }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients, evmSepolia } from '@snapshot-labs/sx'; import type { Web3Provider } from '@ethersproject/providers'; const clientConfig = { networkConfig: evmSepolia } const ethSigClient = new clients.EthereumSig(clientConfig); const web3 = new Web3Provider(window.ethereum); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', strategies: [ { address: '0xc1245c5dca7885c73e32294140f1e5d30688c202', index: 0 } ], proposal: 7, choice: 1, metadataUri: '' }; const receipt = await ethSigClient.vote({ signer: web3.getSigner(), data }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients } from '@snapshot-labs/sx'; import { Provider, constants } from 'starknet'; const web3 = window.starknet.provider; const ethUrl = 'https://rpc.snapshot.org/1'; const manaUrl = 'https://mana.pizza'; const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_SEPOLIA } }); const clientConfig = { starkProvider, manaUrl, ethUrl }; const client = new clients.StarkNetTx(clientConfig); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', strategies: [ { address: '0xc1245c5dca7885c73e32294140f1e5d30688c202', index: 0 } ], proposal: 7, choice: 1, metadataUri: '' }; const receipt = await client.vote(web3.provider.account, { data }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients } from '@snapshot-labs/sx'; import { Provider, constants } from 'starknet'; const web3 = window.starknet.provider; const ethUrl = 'https://rpc.snapshot.org/1'; const manaUrl = 'https://mana.pizza'; const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_SEPOLIA } }); const clientConfig = { starkProvider, manaUrl, ethUrl }; const client = new clients.StarkNetSig(clientConfig); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', strategies: [ { address: '0xc1245c5dca7885c73e32294140f1e5d30688c202', index: 0 } ], proposal: 7, choice: 1, metadataUri: '' }; const envelope = await client.vote({ signer: web3.provider.account, data }); const receipt = await client.send(envelope); console.log('Receipt', receipt); ``` ### Create a proposal ```typescript theme={null} import { clients, evmSepolia } from '@snapshot-labs/sx'; import type { Web3Provider } from '@ethersproject/providers'; const clientConfig = { networkConfig: evmSepolia } const client = new clients.EthereumTx(clientConfig); const web3 = new Web3Provider(window.ethereum); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', strategies: [ { address: '0xc1245c5dca7885c73e32294140f1e5d30688c202', index: 0 } ], executionStrategy: { addr: '0x0000000000000000000000000000000000000000', params: '0x' }, metadataUri: '' }; const receipt = await client.propose({ signer: web3.getSigner(), envelope: { data } }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients, evmSepolia } from '@snapshot-labs/sx'; import type { Web3Provider } from '@ethersproject/providers'; const clientConfig = { networkConfig: evmSepolia } const client = new clients.EthereumSig(clientConfig); const web3 = new Web3Provider(window.ethereum); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', strategies: [ { address: '0xc1245c5dca7885c73e32294140f1e5d30688c202', index: 0 } ], executionStrategy: { addr: '0x0000000000000000000000000000000000000000', params: '0x' }, metadataUri: '' }; const receipt = await ethSigClient.propose({ signer: web3.getSigner(), data }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients } from '@snapshot-labs/sx'; import { Provider, constants } from 'starknet'; const web3 = window.starknet.provider; const ethUrl = 'https://rpc.snapshot.org/1'; const manaUrl = 'https://mana.pizza'; const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_SEPOLIA } }); const clientConfig = { starkProvider, manaUrl, ethUrl }; const client = new clients.StarkNetTx(clientConfig); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', strategies: [ { address: '0xc1245c5dca7885c73e32294140f1e5d30688c202', index: 0 } ], executionStrategy: { addr: '0x0000000000000000000000000000000000000000', params: '0x' }, metadataUri: '' }; const receipt = await client.propose(web3.provider.account, { data }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients } from '@snapshot-labs/sx'; import { Provider, constants } from 'starknet'; const web3 = window.starknet.provider; const ethUrl = 'https://rpc.snapshot.org/1'; const manaUrl = 'https://mana.pizza'; const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_SEPOLIA } }); const clientConfig = { starkProvider, manaUrl, ethUrl }; const client = new clients.StarkNetSig(clientConfig); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', strategies: [ { address: '0xc1245c5dca7885c73e32294140f1e5d30688c202', index: 0 } ], executionStrategy: { addr: '0x0000000000000000000000000000000000000000', params: '0x' }, metadataUri: '' }; const envelope = await client.propose({ signer: web3.provider.account, data }); const receipt = await client.send(envelope); console.log('Receipt', receipt); ``` ### Update a proposal ```typescript theme={null} import { clients, evmSepolia } from '@snapshot-labs/sx'; import type { Web3Provider } from '@ethersproject/providers'; const clientConfig = { networkConfig: evmSepolia } const client = new clients.EthereumTx(clientConfig); const web3 = new Web3Provider(window.ethereum); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', proposal: 1, // proposalId authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', executionStrategy: { addr: '0x0000000000000000000000000000000000000000', params: '0x' }, metadataUri: '' }; const receipt = await client.updateProposal({ signer: web3.getSigner(), envelope: { data } }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients, evmSepolia } from '@snapshot-labs/sx'; import type { Web3Provider } from '@ethersproject/providers'; const clientConfig = { networkConfig: evmSepolia } const client = new clients.EthereumSig(clientConfig); const web3 = new Web3Provider(window.ethereum); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', proposal: 1, // proposalId authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', executionStrategy: { addr: '0x0000000000000000000000000000000000000000', params: '0x' }, metadataUri: '' }; const receipt = await ethSigClient.updateProposal({ signer: web3.getSigner(), envelope: { data } }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients } from '@snapshot-labs/sx'; import { Provider, constants } from 'starknet'; const web3 = window.starknet.provider; const ethUrl = 'https://rpc.snapshot.org/1'; const manaUrl = 'https://mana.pizza'; const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_SEPOLIA } }); const clientConfig = { starkProvider, manaUrl, ethUrl }; const client = new clients.StarkNetTx(clientConfig); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', proposal: 1, // proposalId authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', executionStrategy: { addr: '0x0000000000000000000000000000000000000000', params: '0x' }, metadataUri: '' }; const receipt = await client.updateProposal(web3.provider.account, { data }); console.log('Receipt', receipt); ``` ```typescript theme={null} import { clients } from '@snapshot-labs/sx'; import { Provider, constants } from 'starknet'; const web3 = window.starknet.provider; const ethUrl = 'https://rpc.snapshot.org/1'; const manaUrl = 'https://mana.pizza'; const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_SEPOLIA } }); const clientConfig = { starkProvider, manaUrl, ethUrl }; const client = new clients.StarkNetSig(clientConfig); const data = { space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941', proposal: 1, // proposalId authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1', executionStrategy: { addr: '0x0000000000000000000000000000000000000000', params: '0x' }, metadataUri: '' }; const envelope = await client.updateProposal({ signer: web3.provider.account, data }); const receipt = await client.send(envelope); console.log('Receipt', receipt); ``` ### Get voting power Address' voting power depends on the strategy used. Below you can see an example of getting voting power for whitelist Voting strategy on Starknet. ```typescript theme={null} import { starknetSepolia1, getStarknetStrategy, } from '@snapshot-labs/sx'; const clientConfig = { starkProvider, ethUrl, networkConfig: starknetSepolia1 }; const address = '0xe3ca14dcb7862116bbbe4331a9927c6693b141aa8936bb76e2bdfa4b551a52'; const voterAddress = '0x556B14CbdA79A36dC33FcD461a04A5BCb5dC2A70'; const strategyMetadata = { "tree": [ { "type": 1, "address": "0x556B14CbdA79A36dC33FcD461a04A5BCb5dC2A70", "votingPower": "10" } ] } const timestamp = 1703090187 const strategyParams = [ "0xe3ca14dcb7862116bbbe4331a9927c6693b141aa8936bb76e2bdfa4b551a52" ] const strategy = getStarknetStrategy(address, clientConfig.networkConfig); const vp = await strategy.getVotingPower( address, voterAddress, strategyMetadata, timestamp, strategyParams, clientConfig ); ``` More details coming soon. # UI Source: https://docs.snapshot.box/snapshot-x/services/ui The UI is the official interface for Snapshot X. #### GitHub [https://github.com/snapshot-labs/sx-monorepo/tree/master/apps/ui](https://github.com/snapshot-labs/sx-monorepo/tree/master/apps/ui) #### UI [https://snapshot.box](https://snapshot.box/) # Create a space Source: https://docs.snapshot.box/snapshot-x/user-guides/create-a-space Learn how to create a new space for your organization. To create a new space on Snapshot X: * For mainnet networks, visit: [snapshot.box/#/create/snapshot-x](https://snapshot.box/#/create/snapshot-x) * For testnet networks, visit: [testnet.snapshot.box/#/create/snapshot-x](https://testnet.snapshot.box/#/create/snapshot-x) Follow the steps below: ## 1. Organization's details Provide the profile information like `name`, `description`, social links or handles and `treasury`. In order to set your Treasury select the network first. **Treasury** is the address of your organisation's main account. ## 2. Select network Choose the network for your organisation. At the moment Snapshot X works with Ethereum. Starknet implementation is coming soon. ## 3. Voting strategies Voting Strategies calculate the **Voting Power** of each user. If you are not familiar with what a Voting Strategy is, head to [voting strategies](/snapshot-x/protocol/voting-strategies) to learn more. Select a Voting Strategy from the list of available options and provide the required details. For example for the **Delegated Compound Token** you have to provide the token contract address, its decimals and the symbol: ## 4. Authenticators Choose how users will be authenticated in order to create a proposal or cast a vote. If you are not familiar with what Authenticators are, head to [authenticators](/snapshot-x/protocol/authenticators) to learn more. The two authenticators provided by Snapshot X are: #### Ethereum signature It will authenticate a user based on a message signed by an Ethereum private key. #### Ethereum transaction Users have to submit a transaction on Ethereum. Authentication is proving that the sender's address is valid. ## 5. Proposal validation Proposal Validation is setting **requirements** that user needs to meet in order to **create a new proposal.** If you are not familiar with what a Proposal Validation is, head to [proposal validations](/snapshot-x/protocol/proposal-validations) to learn more. Define the minimum Voting Power required to create a new proposal. We highly recommend setting a high threshold to avoid scam proposals. Once you have defined the required Voting Power, you can then select the Voting Strategies which will be used to calculate the voting power of proposal creators and assess the eligibility to create a new one: ## 6. Execution Execution Strategies have two key roles: 1. determining **the status** of a proposal at any time, 2. and **executing the payload** of a proposal if it has been accepted. If you are not familiar with what Execution Strategies are, head to [execution strategies](/snapshot-x/protocol/execution-strategies) to learn more. When selecting the execution strategy you have to provide a **quorum**, the minimum number of votes required for a proposal to pass. ### Execution strategies Currently Snapshot X provides two Execution Strategies: #### Avatar -> ideal solution for treasuries on [Safe](https://safe.global/) -> executes transactions on an [Avatar contract](https://github.com/gnosis/zodiac/blob/master/contracts/interfaces/IAvatar.sol) -> uses simple quorum Avatar contract is any contract which implements the `IAvatar` interface. **Safe** is an example of an Avatar contract. To set the Avatar Execution Strategy up fully you have to enable it on your Safe account after you have created your space. **Follow this guide to complete the setup:** [Safe execution setup](/snapshot-x/user-guides/safe-execution-setup) #### Timelock -> adds additional **security layer** to review or cancel transactions before they get executed -> executes transactions after a delay specified in **seconds** -> uses simple quorum When a proposal with this strategy is executed, the proposal transactions are queued in the Timelock for `timelockDelay` seconds before they can be executed. ### 7. Voting Customize the setup for voting which will affect **all proposals** in your space: * **Voting delay:** The delay between when a proposal is created, and when the voting starts. A value of 0 means that as soon as the proposal is created anyone can vote while a value of 3600 means that voting will start 3600 seconds after the proposal is created. * **Minimum voting duration:** The minimum duration of the voting period. It is **impossible to execute a proposal before** **this period** has elapsed. * **Maximum voting duration:** The maximum duration of the voting period, it is **impossible to cast a vote after this period** has passed. The **`minimum voting duration`** must be less than or equal to this value. We highly recommend implementing a Voting Delay to allow more time to review proposal's content and identify malicious proposals before voting starts. ### 7. Controller Space controller is a user that has a **full control over the space settings.** The address can differ from your own, you can for example set a multisig account as the controller. ### 8. Sign transaction(s) Click **Create** and sign transaction(s) in your wallet. You will have to sign multiple transactions, each for individual contracts to be deployed: * Space contract * Execution strategy contracts - each space has its execution strategy deployed as an individual contract Your space is now created. # Gasless voting Source: https://docs.snapshot.box/snapshot-x/user-guides/gasless-voting To enable gasless voting and proposals on a Snapshot X space, first add the **Ethereum signature authenticator** (or the **Starknet signature authenticator** if your space uses Starknet). When you create a Snapshot X space, a dedicated wallet is automatically generated to facilitate gasless interactions. You can find the address of this dedicated wallet in the **Authenticator** page within your space settings. To activate gasless voting and proposal submissions, simply top up this wallet with ETH (or the relevant gas token). If the wallet balance drops below **0.01 ETH**, the gasless functionality will be disabled. ## What is Mana? Mana is a meta-transaction relayer that enables gasless governance on Snapshot X. Instead of requiring users to pay gas fees for proposals and votes, Mana sponsors those fees by accepting signed messages and broadcasting them onchain. This eliminates the need for users to hold or spend ETH for governance actions, making participation more accessible. The source code is available at [github.com/snapshot-labs/sx-monorepo/tree/master/apps/mana](https://github.com/snapshot-labs/sx-monorepo/tree/master/apps/mana). # Proposals Source: https://docs.snapshot.box/snapshot-x/user-guides/proposals Learn what a proposal is and how to create one. ## What is a proposal? Proposal is the key element of the voting system. It presents a change suggestion related to a specific organization and enables eligible users to cast their vote. Voting power for each user is calculated on the basis of the voting strategies selected in the space settings. Each proposal has the same voting system which provides three choices: **accept**, **reject**, **abstain**. ## Who can create a proposal? Users who: * authenticate themselves via Authenticators whitelisted by the space, * and are eligible according to the [Proposal validation strategy](#user-content-fn-2) selected by the space. ## Create a proposal ### 1. Open space settings. Head to the space which you wish to create your proposal for. Make sure the connected wallet is **where you hold the tokens relevant** to the specific space. ### 2. Click the New proposal icon Click the new proposal icon in the top right corner: ### 3. Provide proposal details Provide the necessary details - title, description and discussion link if there is one. ### 4. Choose the execution strategy Select the [Execution strategy](#user-content-fn-3) you would like to use: ### 5. Specify transaction details Define what should happen if the proposal passes by choosing one of the execution options: A modal will open with the **transaction details** to fill in: ### 6. Publish your proposal Click `Publish` and authenticate yourself via your wallet. Depending on the space settings you will have to sign a gasless Ethereum message and/or sign a transaction to confirm your action. When you create a proposal by default the **timestamp** will be populated with the latest block synced from our node. The voting power of each user will be calculated for the **state of the blockchain at this specific timestamp**. It means that if user acquires required tokens **after** the proposal has been created, they will not be taken into account for their voting power calculation. ### 7. Give it a minute.. Wait for the transaction to succeed. You can see it's pending in the top right corner, just next to your avatar: Once the icon with the pending transaction disappears, you can reload the page to view your proposal. Your proposal has been created. ### Executing proposals Once the proposal has reached a quorum and passed, anyone can execute the transactions specified for it by clicking the **Execute transactions** button: # Safe execution setup Source: https://docs.snapshot.box/snapshot-x/user-guides/safe-execution-setup If you added the Safe execution strategy to your space you have to enable it on your Safe account after creating the space. ## 1. Copy the address of your Safe execution Head to your space settings and scroll down to the bottom of the page and click the Safe address on the right side of the screen. A new tab will open on the Etherscan explorer. **Copy the address of the contract:** ## 2. Open Safe dashboard of your Treasury account Click the `App` tab in the sidebar to open the list of available Safe applications. ## 3. Select the Zodiac app ## 4. Add your Safe execution strategy contract Click on `Custom Module.` Paste the contract's address you copied in the first step in the `Module Address` field. As a last step you will have to sign a transaction. Your proposals can now be executed. # Storage proofs Source: https://docs.snapshot.box/snapshot-x/user-guides/storage-proofs Storage proofs are a way to verify data from one blockchain on another blockchain without accessing the entire state. Snapshot X collaborates with Herodotus to integrate storage proofs into its voting strategies on Starknet. This integration allows Snapshot X to calculate voting power based on data from Ethereum mainnet or Sepolia testnet contracts. Here's how it works: 1. A block hash from Ethereum (L1) is sent to Starknet (L2) 2. Using this block hash, the state of any contract from L1 can be verified on L2 at that specific block 3. The voting strategy accesses and verifies data (like token balances) from the Ethereum contract 4. Voting power is then calculated using the verified data This approach enables secure cross-chain governance, combining Ethereum's security with Starknet's scalability. It allows projects to use Ethereum data for voting on Starknet efficiently and securely. Currently, this feature is only available on Starknet. ### Learn more * [Herodotus: Proving Ethereum's State Using Storage Proofs on Starknet](https://www.herodotus.dev/) * [Storage Proofs | Herodotus Docs](https://docs.herodotus.dev/) # Voting Source: https://docs.snapshot.box/snapshot-x/user-guides/voting Learn how you can cast a vote on a proposal. ## Who can vote on proposals? There are several aspects that define if you are eligible to vote on a specific proposal. ### Voting strategies Each space specifies their [Voting strategies](/snapshot-x/protocol/voting-strategies) in its settings. You can see the custom setup by opening the space settings. This setup can define if you are eligible to take part in the voting and what is your Voting Power calculated at the timestamp of proposal creation. One of the most common questions we receive on our support channels is **Why can't I vote?** More often than not the answer is - **you did not hold the sufficient amount of specified token at the time of proposal creation.** ## Cast a vote ### 1. Connect your wallet Click the `Connect wallet` button in the top right corner. Connect with the wallet provider where you **hold the tokens relevant for the space** you want to vote in. ### 2. Find the proposal Go to the space page on Snapshot. You can vote directly from this view or go to the proposal you are interested in to read more details before you vote. In the proposal page you can see your Voting Power. If it shows `0` it means you cannot vote on the selected proposal. ### 3. Vote! Select the option you want to vote for - **Accept, Reject, Abstain**. Depending on the space settings you will have to sign a gasless Ethereum message and/or sign a transaction to confirm your action. If you are using MetaMask you'll need to scroll to the end of the signature and click on the arrow down for the Sign button to become active. Voting on Snapshot doesn't affect your account or the funds that are associated to it. You will notice that a new icon has appeared in the top right corner, just next to your avatar: The number indicates the number of pending transactions. Once it disappeared you can reload to page to view your vote. You have successfully cast your vote. # Voting power Source: https://docs.snapshot.box/snapshot-x/user-guides/voting-power ## Why do I have 0 voting power? There are a few reasons why you might have 0 voting power on Snapshot: * **No required assets:** You might not hold the necessary assets or meet the criteria based on the voting strategies used by the space. Each space can have different requirements. * **Delegation required:** For some tokens (like those using ERC-20 Votes), you need to delegate your tokens to gain voting power. * **Proposal start requirements:** Voting power is determined at the time a proposal starts. If you didn't meet the requirements when the proposal started, you won't have voting power for that proposal. You can check your current voting power on the space's proposals page to see if you meet the criteria. ## Why do I need to wait for my voting power to be collected from Ethereum? If you see the message "Please allow a few minutes for the voting power to be collected from Ethereum," it means your space uses a voting strategy that requires data from another blockchain. This process takes about 10 to 15 minutes. During this time, the state is sent from the other chain to the current space chain, where your voting power is verified using storage proofs. Please be patient, and you'll soon be able to see your voting power and cast your vote. # Voting strategies Source: https://docs.snapshot.box/snapshot-x/user-guides/voting-strategies-sx Snapshot X provides several onchain voting strategies for calculating voting power. ## Whitelist The Whitelist strategy assigns specific voting power to chosen addresses. It uses a format of `address:voting_power` and a Merkle tree for onchain verification. Only the tree's root is stored onchain. During voting, users prove their inclusion in the list using Merkle proofs. This approach saves gas, allows easy updates, and provides precise control over voting power distribution. Example format: ``` 0x1234567890123456789012345678901234567890:100 0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:50 0x9876543210987654321098765432109876543210:75 ``` ## ERC-20 Votes (EIP-5805) The ERC-20 Votes strategy assigns voting power based on delegated token balances. It works with ERC-20 or ERC-721 tokens that implement the EIP-5805 Votes extension from OpenZeppelin. This strategy allows token holders to participate in governance by delegating their voting power, either to themselves or to other addresses. ## EVM slot value The EVM slot value strategy uses values stored in specific slots on an EVM chain as voting power. It retrieves data such as ERC-20 token balances or ERC-721 token ownership from Ethereum mainnet or Sepolia testnet and leverages storage proofs to verify data integrity on layer 2. Currently, this strategy is only available on Starknet. To set up this strategy: 1. Add the Ethereum mainnet or Sepolia testnet contract address 2. Find the storage slot where balances are stored using [storage.herodotus.dev](https://storage.herodotus.dev) 3. Enter the contract address and select the network 4. Locate the index where the balances are stored For example, for the ApeCoin (APE) ERC-20 token, the balances are stored in slot index 0. ## Vanilla The Vanilla strategy is a simple voting strategy used for testing purposes, available only on testnets. It assigns 1 voting power to each participant, regardless of their token holdings. ## OZ Votes storage proof The OZ Votes storage proof strategy uses delegated balances stored in specific slots on an EVM chain as voting power. This strategy focuses on verifying delegated voting power for tokens using ERC-20 Votes or ERC-721 Votes, utilizing the trace 224 or 208 format. It leverages storage proofs to ensure data integrity on layer 2. Currently, this strategy is only available on Starknet. To set up this strategy: 1. Add the Ethereum mainnet or Sepolia testnet contract address 2. Find the storage slot where delegated balances are stored using [storage.herodotus.dev](https://storage.herodotus.dev) 3. Enter the contract address and select the network 4. Locate the index where the delegated balances are stored For example, for the ENS ERC-20 token, the delegated balances are stored in slot index 7. If you need help setting up any voting strategy, contact our support team through the [Help Center](/faq/support-and-feedback). # API Source: https://docs.snapshot.box/tools/api You can use the Hub GraphQL API to create flexible queries for the data you need to integrate with Snapshot. There is a limit of 60 requests per minute with the API, to get higher limits please apply for an API Key by following this guide: [api-keys](/tools/api/api-keys) ## Hub GraphQL API: Explorer You can run queries on Snapshot data using a GraphQL Explorer. We have exposed an integrated development environment in the browser that includes docs, syntax highlighting, and validation errors. Click the link below to access the interface. [https://hub.snapshot.org/graphql](https://hub.snapshot.org/graphql) ## Endpoints Production hub ``` https://hub.snapshot.org/graphql ``` Demo hub ``` https://testnet.hub.snapshot.org/graphql ``` ## Queries ### Get a single space #### Arguments id `string` #### Example ```graphql theme={null} query { space(id: "yam.eth") { id name about network symbol members } } ``` ```javascript theme={null} { "data": { "space": { "id": "yam.eth", "name": "Yam Finance", "about": "", "network": "1", "symbol": "YAM", "members": [ "0x683A78bA1f6b25E29fbBC9Cd1BFA29A51520De84", "0x9Ebc8AD4011C7f559743Eb25705CCF5A9B58D0bc", "0xC3edCBe0F93a6258c3933e86fFaA3bcF12F8D695", "0xbdac5657eDd13F47C3DD924eAa36Cf1Ec49672cc", "0xEC3281124d4c2FCA8A88e3076C1E7749CfEcb7F2" ] } } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?query=query%20%7B%0A%20%20space\(id%3A%20%22yam.eth%22\)%20%7B%0A%20%20%20%20id%0A%20%20%20%20name%0A%20%20%20%20about%0A%20%20%20%20network%0A%20%20%20%20symbol%0A%20%20%20%20members%0A%20%20%7D%0A%7D) ### Get multiple spaces #### Arguments first `number`\ skip `number`\ where:\ \- id`string`\ \- id\_in`array`\ orderBy `string`\ orderDirection `asc` or `desc` #### Example ```graphql theme={null} query { spaces( first: 20, skip: 0, orderBy: "created", orderDirection: asc ) { id name about network symbol strategies { name params } admins members filters { minScore onlyMembers } plugins } } ``` ```javascript theme={null} { "data": { "spaces": [ { "id": "bonustrack.eth", "name": "Fabien", "about": "", "network": "1", "symbol": "TICKET", "strategies": [ { "name": "erc20-balance-of", "params": { "symbol": "DAI", "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F", "decimals": 18 } } ], "admins": [], "members": [ "0x24A12Fa313F57aF541d447c594072A992c605DCf" ], "filters": { "minScore": 0, "onlyMembers": false }, "plugins": { "quorum": { "total": 500, "strategy": "static" } } } ] } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?query=%0Aquery%20Spaces%20%7B%0A%20%20spaces\(%0A%20%20%20%20first%3A%2020%2C%0A%20%20%20%20skip%3A%200%2C%0A%20%20%20%20orderBy%3A%20%22created%22%2C%0A%20%20%20%20orderDirection%3A%20asc%0A%20%20\)%20%7B%0A%20%20%20%20id%0A%20%20%20%20name%0A%20%20%20%20about%0A%20%20%20%20network%0A%20%20%20%20symbol%0A%20%20%20%20strategies%20%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20params%0A%20%20%20%20%7D%0A%20%20%20%20admins%0A%20%20%20%20members%0A%20%20%20%20filters%20%7B%0A%20%20%20%20%20%20minScore%0A%20%20%20%20%20%20onlyMembers%0A%20%20%20%20%7D%0A%20%20%20%20plugins%0A%20%20%7D%0A%7D) ### Get a single proposal #### Arguments id `string`‌ #### Example ```graphql theme={null} query { proposal(id:"QmWbpCtwdLzxuLKnMW4Vv4MPFd2pdPX71YBKPasfZxqLUS") { id title body choices start end snapshot state author created scores scores_by_strategy scores_total scores_updated plugins network strategies { name network params } space { id name } } } ``` ```javascript theme={null} { "data": { "proposal": { "id": "QmWbpCtwdLzxuLKnMW4Vv4MPFd2pdPX71YBKPasfZxqLUS", "title": "Select Initial Umbrella Metapool", "body": "Eventually, we hope that anyone will be able to create a metapool and fund a protection market for their project, but right now we want to start small and pick one pool that we will debut as a beta launch for Umbrella that will help us gather information and insight into the state of the market. In the future we can have all of these and more. Here are the choices:\n### Option 1: BlueChips MetaPool\n\nYou might consider this the safest of the pools. It contains a collection of different “blue-chip projects” across multiple verticals that have proven track records and are considered industry leaders. These include:\n\n* (3) Bluechip protocols: MakerDAO, Compound, and Uniswap. These are commonly seen as the most battletested and trusted DeFi projects on Ethereum.\n* (2) Centralized exchanges: Coinbase and Binance. These are the most popular and generally considered to be most reputable exchanges around. *note: Payout occurs only if Safu funds or the exchange’s insurance do not cover losses.\n* (2) Hardware Wallet companies, Ledger and Trezor, including the Ledger Nano S and X, and the Trezor Model T and One. This would cover large scale exploits in their hardware or firmware and would not cover individual loss due to phishing or poor security.\n\n### Option 2: Hot New Projects MetaPool\n\nThis pool targets newer projects on Ethereum that are considered reputable and have high TVL but are less battle tested and therefore may be more risky. While they may be more risky, this may mean that there is more demand for coverage for them in the market. This list is preliminary but internal discussions considered including:\n\n * Alchemix\n* OHM\n* Liquity\n* FEI\n* Integral\n* Reflexer\n\n### Option 3: Integrated DegenV2 MetaPool\n\nThis last option focuses more closely on YAM products, specifically DegenV2 and the constituent protocols that it uses. This option would let us insure our own users and potentially test out our products in a more limited environment. The covered protocols would be:\n\n * UMA\n * Sushiswap/Uniswap depending on where our pools live\n * Any YAM contracts that are used\n * Any future contracts included in future versions of Degen.\n\n### Choose wisely!\n", "choices": [ "Option 1: BlueChips MetaPool", "Option 2: Hot New Projects MetaP", "Option 3: Integrated DegenV2 Met" ], "start": 1620676800, "end": 1620806400, "snapshot": "12408670", "state": "closed", "author": "0xEC3281124d4c2FCA8A88e3076C1E7749CfEcb7F2", "space": { "id": "yam.eth", "name": "Yam Finance" } } } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Proposal\&query=query%20Proposal%20%7B%0A%20%20proposal\(id%3A%22QmWbpCtwdLzxuLKnMW4Vv4MPFd2pdPX71YBKPasfZxqLUS%22\)%20%7B%0A%20%20%20%20id%0A%20%20%20%20title%0A%20%20%20%20body%0A%20%20%20%20choices%0A%20%20%20%20start%0A%20%20%20%20end%0A%20%20%20%20snapshot%0A%20%20%20%20state%0A%20%20%20%20author%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) ### Get proposals #### Arguments first `number`\ skip `number`\ where:\ \- id`string`\ \- id\_in`array`\ \- space:`string`\ \- space\_in:`array`\ \- author:`string`\ \- author\_in:`array`\ \- network: `string`\ \- network\_in: `array`\ \- state: `array`\ orderBy `string`\ orderDirection `asc` or `desc` #### Example ```graphql theme={null} query { proposals ( first: 20, skip: 0, where: { space_in: ["yam.eth"], state: "closed" }, orderBy: "created", orderDirection: desc ) { id title body choices start end snapshot state scores scores_by_strategy scores_total scores_updated author space { id name } } } ``` ```javascript theme={null} { "data": { "proposals": [ { "id": "QmWbpCtwdLzxuLKnMW4Vv4MPFd2pdPX71YBKPasfZxqLUS", "title": "Select Initial Umbrella Metapool", "body": "Eventually, we hope that anyone will be able to create a metapool and fund a protection market for their project, but right now we want to start small and pick one pool that we will debut as a beta launch for Umbrella that will help us gather information and insight into the state of the market. In the future we can have all of these and more. Here are the choices:\n### Option 1: BlueChips MetaPool\n\nYou might consider this the safest of the pools. It contains a collection of different “blue-chip projects” across multiple verticals that have proven track records and are considered industry leaders. These include:\n\n* (3) Bluechip protocols: MakerDAO, Compound, and Uniswap. These are commonly seen as the most battletested and trusted DeFi projects on Ethereum.\n* (2) Centralized exchanges: Coinbase and Binance. These are the most popular and generally considered to be most reputable exchanges around. *note: Payout occurs only if Safu funds or the exchange’s insurance do not cover losses.\n* (2) Hardware Wallet companies, Ledger and Trezor, including the Ledger Nano S and X, and the Trezor Model T and One. This would cover large scale exploits in their hardware or firmware and would not cover individual loss due to phishing or poor security.\n\n### Option 2: Hot New Projects MetaPool\n\nThis pool targets newer projects on Ethereum that are considered reputable and have high TVL but are less battle tested and therefore may be more risky. While they may be more risky, this may mean that there is more demand for coverage for them in the market. This list is preliminary but internal discussions considered including:\n\n * Alchemix\n* OHM\n* Liquity\n* FEI\n* Integral\n* Reflexer\n\n### Option 3: Integrated DegenV2 MetaPool\n\nThis last option focuses more closely on YAM products, specifically DegenV2 and the constituent protocols that it uses. This option would let us insure our own users and potentially test out our products in a more limited environment. The covered protocols would be:\n\n * UMA\n * Sushiswap/Uniswap depending on where our pools live\n * Any YAM contracts that are used\n * Any future contracts included in future versions of Degen.\n\n### Choose wisely!\n", "choices": [ "Option 1: BlueChips MetaPool", "Option 2: Hot New Projects MetaP", "Option 3: Integrated DegenV2 Met" ], "start": 1620676800, "end": 1620806400, "snapshot": "12408670", "state": "closed", "author": "0xEC3281124d4c2FCA8A88e3076C1E7749CfEcb7F2", "space": { "id": "yam.eth", "name": "Yam Finance" } }, ... ] } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Proposals\&query=query%20Proposals%20%7B%0A%20%20proposals%20\(%0A%20%20%20%20first%3A%2020%2C%0A%20%20%20%20skip%3A%200%2C%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20space_in%3A%20%5B%22yam.eth%22%5D%2C%0A%20%20%20%20%20%20state%3A%20%22closed%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20orderBy%3A%20%22created%22%2C%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20\)%20%7B%0A%20%20%20%20id%0A%20%20%20%20title%0A%20%20%20%20body%0A%20%20%20%20choices%0A%20%20%20%20start%0A%20%20%20%20end%0A%20%20%20%20snapshot%0A%20%20%20%20state%0A%20%20%20%20author%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) ### Get a single vote Choices are indexed 1-based. The first choice has index 1. #### Arguments id `string`‌ #### Example ```graphql theme={null} query { vote ( id: "QmeU7ct9Y4KLrh6F6mbT1eJNMkeQKMSnSujEfMCfbRLCMp" ) { id voter vp vp_by_strategy vp_state created proposal { id } choice space { id } } } ``` ```javascript theme={null} { "data": { "vote": { "id": "QmeU7ct9Y4KLrh6F6mbT1eJNMkeQKMSnSujEfMCfbRLCMp", "voter": "0x96176C25803Ce4cF046aa74895646D8514Ea1611", "created": 1621183227, "proposal": { "id": "QmPvbwguLfcVryzBRrbY4Pb9bCtxURagdv1XjhtFLf3wHj" }, "choice": 1, "space": { "id": "spookyswap.eth" } } } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Vote\&query=query%20Vote%20%7B%0A%20%20vote%20\(%0A%20%20%20%20id%3A%20%22QmeU7ct9Y4KLrh6F6mbT1eJNMkeQKMSnSujEfMCfbRLCMp%22%0A%20%20\)%20%7B%0A%20%20%20%20id%0A%20%20%20%20voter%0A%20%20%20%20created%0A%20%20%20%20proposal%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%20%20choice%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) ### Get votes Choices are indexed 1-based. The first choice has index 1. #### Arguments first `number`\ skip `number`\ where:\ \- id`string`\ \- id\_in`array`\ \- space:`string`\ \- space\_in:`array`\ \- voter:`string`\ \- voter\_in:`array`\ \- proposal: `string`\ \- proposal\_in: `array`\ orderBy `string`\ orderDirection `asc` or `desc` #### Example ```graphql theme={null} query { votes ( first: 1000 skip: 0 where: { proposal: "QmPvbwguLfcVryzBRrbY4Pb9bCtxURagdv1XjhtFLf3wHj" } orderBy: "created", orderDirection: desc ) { id voter vp vp_by_strategy vp_state created proposal { id } choice space { id } } } ``` ```javascript theme={null} { "data": { "votes": [ { "id": "QmeU7ct9Y4KLrh6F6mbT1eJNMkeQKMSnSujEfMCfbRLCMp", "voter": "0x96176C25803Ce4cF046aa74895646D8514Ea1611", "created": 1621183227, "proposal": { "id": "QmPvbwguLfcVryzBRrbY4Pb9bCtxURagdv1XjhtFLf3wHj" }, "choice": 1, "space": { "id": "spookyswap.eth" } }, { "id": "QmZ2CV86QH6Q6z7L6g7yJWS3HfgD9aQ3uTYYMXkMa5trHf", "voter": "0x2686EaD94C5042e56a41eDde6533711a4303CC52", "created": 1621181827, "proposal": { "id": "QmPvbwguLfcVryzBRrbY4Pb9bCtxURagdv1XjhtFLf3wHj" }, "choice": 1, "space": { "id": "spookyswap.eth" } }, ... ] } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Votes\&query=query%20Votes%20%7B%0A%20%20votes%20\(%0A%20%20%20%20first%3A%201000%0A%20%20%20%20skip%3A%200%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20proposal%3A%20%22QmPvbwguLfcVryzBRrbY4Pb9bCtxURagdv1XjhtFLf3wHj%22%0A%20%20%20%20%7D%0A%20%20%20%20orderBy%3A%20%22created%22%2C%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20\)%20%7B%0A%20%20%20%20id%0A%20%20%20%20voter%0A%20%20%20%20created%0A%20%20%20%20proposal%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%20%20choice%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A) ### Get voting power #### Arguments voter `string`\ space `string`\ proposal `string` #### Example ```graphql theme={null} query { vp ( voter: "0xeF8305E140ac520225DAf050e2f71d5fBcC543e7" space: "fabien.eth" proposal: "0x4903dd16990de740b7dc7effe1a0bc8bd49a510a04992bc30596c9a0d0f69455" ) { vp vp_by_strategy vp_state } } ``` ``` { "data": { "vp": { "vp": 1, "vp_by_strategy": [ 1 ], "vp_state": "final" } } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?query=query%20%7B%0A%20%20vp%20\(%0A%20%20%20%20voter%3A%20%220xeF8305E140ac520225DAf050e2f71d5fBcC543e7%22%0A%20%20%20%20space%3A%20%22fabien.eth%22%0A%20%20%20%20proposal%3A%20%220x4903dd16990de740b7dc7effe1a0bc8bd49a510a04992bc30596c9a0d0f69455%22%0A%20%20\)%20%7B%0A%20%20%20%20vp%0A%20%20%20%20vp_by_strategy%0A%20%20%20%20vp_state%0A%20%20%7D%20%0A%7D%0A) ### Get follows #### Arguments first `number`\ skip `number`\ where:\ \- id`string`\ \- id\_in`array`\ \- space:`string`\ \- space\_in:`array`\ \- follower:`string`\ \- follower\_in:`array`\ orderBy `string`\ orderDirection `asc` or `desc` #### Example ```graphql theme={null} query { follows( first: 10, where: { follower: "0xeF8305E140ac520225DAf050e2f71d5fBcC543e7" } ) { follower space { id } created } } ``` ```javascript theme={null} { "data": { "follows": [ { "follower": "0xeF8305E140ac520225DAf050e2f71d5fBcC543e7", "space": { "id": "gnosis.eth" }, "created": 1629732280 }, { "follower": "0xeF8305E140ac520225DAf050e2f71d5fBcC543e7", "space": { "id": "aavegotchi.eth" }, "created": 1629725098 }, { "follower": "0xeF8305E140ac520225DAf050e2f71d5fBcC543e7", "space": { "id": "yam.eth" }, "created": 1629723970 }, { "follower": "0xeF8305E140ac520225DAf050e2f71d5fBcC543e7", "space": { "id": "balancer.eth" }, "created": 1629723960 } ] } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?query=query%20%7B%0A%20%20follows\(%0A%20%20%20%20first%3A%2010%2C%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20follower%3A%20%220xeF8305E140ac520225DAf050e2f71d5fBcC543e7%22%0A%20%20%20%20%7D%0A%20%20\)%20%7B%0A%20%20%20%20follower%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%20%20created%0A%20%20%7D%0A%7D) ### Get users #### Arguments first `number`\ skip `number`\ where:\ \- id:`string`\ \- id\_in:`array`\ orderBy `string`\ orderDirection `asc` or `desc` #### Example ```graphql theme={null} query { users(first: 10, where: { id_in: ["0xF78108c9BBaF466dd96BE41be728Fe3220b37119"] }) { id name about avatar } } ``` ``` { "data": { "users": [ { "id": "0xF78108c9BBaF466dd96BE41be728Fe3220b37119", "name": "John Doe", "about": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Assumenda asperiores a quis accusamus tenetur sed", "avatar": "ipfs://QmNXTswsKJEHHEmGCgQKEAqbq3ib1eBCd4U8SRPgcuVJBX" } ] } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?query=query%20%7B%0A%20%20users\(first%3A%2010%2C%20where%3A%20%7B%20id_in%3A%20%5B%220xF78108c9BBaF466dd96BE41be728Fe3220b37119%22%5D%20%7D\)%20%7B%0A%20%20%20%20id%0A%20%20%20%20name%0A%20%20%20%20about%0A%20%20%20%20avatar%0A%20%20%7D%0A%7D%0A) ### Get roles #### Arguments first `number`\ skip `number`\ where:\ \- address:`string`\ orderBy `string`\ orderDirection `asc` or `desc` ```graphql theme={null} query { roles(where:{address:"0xE029Ef62e47E394BC852EFf633eB5aa4A223ECa6"}) { space permissions } } ``` ```graphql theme={null} { "data": { "roles": [ { "space": "fabien.eth", "permissions": [ "moderator" ] }, { "space": "zuzazuber.eth", "permissions": [ "moderator" ] } ] } } ``` Try on GraphiQL ### Aliases TBD ### Get messages Messages are all the actions (votes, proposals, space settings etc..) that was confirmed on Snapshot, it also include the order on which these actions were confirmed with the field "mci". These messages can be used to replay the whole Snapshot hub API. #### Arguments first `number`\ skip `number`\ where:\ \- timestamp`string`\ \- space`array`\ \- space\_in:`array`\ \- type:`string`\ \- type\_in:`string`\ orderBy `string`\ orderDirection `asc` or `desc` #### Example ```graphql theme={null} query { messages ( first: 20 where: { space: "ens.eth" } orderBy: "mci" orderDirection: desc ) { id address ipfs receipt type mci } } ``` ```javascript theme={null} { "data": { "messages": [ { "id": "0x7d99e11ffe3a333229bdcda59866bc5b66b0b7e5c4b5353862a3b8ccbfa26c83", "address": "0xdbB1740e424C41E935599634828f5E5c4dF23D43", "ipfs": "bafkreiduchkd35btpv3uttrg3f2kx3g52uh44tiruawip6xlgvjbcuo4w4", "receipt": "0xaa4d557085872ed82b8bfba5af4247650395eda46ed61672d940eabc74bcde67415db974361f4b24361565d2f9ee6ee636ae935a1dc830c207204ea29ad498741b", "type": "follow" "mci": 1345000 }, ... ] } } ``` Try on [GraphiQL](https://hub.snapshot.org/graphql?query=query%20%7B%0A%20%20messages%20\(%0A%20%20%20%20first%3A%2020%0A%20%20%20%20where%3A%20%7B%20space%3A%20%22ens.eth%22%20%7D%0A%20%20%20%20orderBy%3A%20%22timestamp%22%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20\)%20%7B%0A%20%20%20%20id%0A%20%20%20%20address%0A%20%20%20%20ipfs%0A%20%20%20%20receipt%0A%20%20%20%20type%0A%20%20%7D%0A%7D%0A) # API keys Source: https://docs.snapshot.box/tools/api/api-keys To obtain higher rate limits on the Hub API use, apply for an API Key. We want to ensure that we limit the risk of API downtime and provide a reliable and continuous service. Therefore we decided to implement API Keys to ensure that the requests come from genuine users. You can use **the same API key** for different Snapshot APIs. Limits are **counted individually** per each API Service. ## Limits **🔓 No API Key:** 100 requests per minute. **🔑 With the API Key:** 2 million requests per month. If you are getting **close to 2M requests a month** contact our support on [Help Center](/faq/support-and-feedback) ## How can I get an API Key? ### 1. Apply via the request form If you haven’t already please **fill in the below form** or submit it via [the direct link](https://tally.so/r/3laKWp). #### API Key Request Form [https://tally.so/r/3laKWp](https://tally.so/r/3laKWp) ### 2. Wait 72 hours We will review your submission and **whitelist the address** you provided in the form. Once whitelisted, you will **receive an email with your API key**. If you haven't received an email after 72 hours, please contact our support on [Help Center](/faq/support-and-feedback). ## How to structure the query with my key? The only change you need to make is to add the API Key in the headers of your request: ```bash theme={null} curl 'https://hub.snapshot.org/graphql?' \ -H 'content-type: application/json' \ -H 'x-api-key: ' \ --data-raw '{"query":"\n{\n space(id:\"snapshot.dcl.eth\"){\n id\n name\n members\n}\n}","variables":null}' \ --compressed ``` Alternatively, you can use the `apiKey` param in the query string with your key as a value: ```bash theme={null} curl 'https://hub.snapshot.org/graphql?apiKey=' \ -H 'content-type: application/json' \ --data-raw '{"query":"\n{\n space(id:\"snapshot.dcl.eth\"){\n id\n name\n members\n}\n}","variables":null}' \ --compressed ``` If you are using the GraphQL interface you need to provide your key in the `headers` tab: # Bots Source: https://docs.snapshot.box/tools/bots Setup a bot to receive Snapshot notifications. Snapshot has several bot integrations which can be set up for your organization in order to receive Snapshot specific notifications. Have a look at the list below to see what is currently possible: ### Snapshot Discord bot **For:** Discord\ **Status:** Ready\ **Install:** [Invite the Discord bot](https://discord.com/oauth2/authorize?client_id=892847850780762122\&permissions=83968\&scope=bot) Type `/` to see the commands (require administrator role) Need help? Contact our support on [Help Center](/faq/support-and-feedback). ### Domino **For:** Discord, Telegram, X, Email, Slack, Webhook, and many more custom automations\ **Status:** Ready\ **Install:** [https://domino.run/explore/apps/snapshot-tmkg6ni3l3r](https://domino.run/explore/apps/snapshot-tmkg6ni3l3r) If you would like to set up another bot integration, contact us on [Discord](https://discord.snapshot.org) with the details! # Mobile notifications Source: https://docs.snapshot.box/tools/mobile-notifications You can now subscribe to mobile notifications from the Spaces you follow on Snapshot! ## Lighthouse [Lighthouse](https://lighthouse.cx/download?utm_source=snapshot_org) connects you to all your Snapshot spaces and keeps you updated with push notifications whenever a proposal is created or ending soon. Read proposals and comments, and even vote without leaving the app. Everything is cryptographically verified, allowing you to focus on the content that matters. If you own or manage a space, Lighthouse also enables you to securely communicate with your voters, analyze engagement, and more. # Snapshot.js Source: https://docs.snapshot.box/tools/snapshot-js The official JavaScript client for implementing Snapshot's functionality in other apps. ## **Overview** **`Snapshot.js`** is an open source JavaScript client which comes with the core functions of the Snapshot's offchain voting system. It was designed to work both in the browser and with `Node.js`. [**Snapshot.js Repository**](https://github.com/snapshot-labs/snapshot.js) ## Get started ### **Installation** **Node.js** To install Snapshot.js on Node.js, open your terminal and run: ```shell theme={null} npm i @snapshot-labs/snapshot.js ``` **Browser** You can create an index.html file and include Snapshot.js with: ```html theme={null} ``` ### Development **Install dependencies** ```shell theme={null} yarn ``` **Build package** ```shell theme={null} yarn build ``` ## Usage #### Base features #### Init client ```javascript theme={null} import snapshot from '@snapshot-labs/snapshot.js'; const hub = 'https://hub.snapshot.org'; // or https://testnet.hub.snapshot.org for testnet const client = new snapshot.Client712(hub); ``` #### Cast a vote ```javascript theme={null} import { Web3Provider } from '@ethersproject/providers'; const web3 = new Web3Provider(window.ethereum); const [account] = await web3.listAccounts(); const receipt = await client.vote(web3, account, { space: 'yam.eth', proposal: '0x21ea31e896ec5b5a49a3653e51e787ee834aaf953263144ab936ed756f36609f', type: 'single-choice', choice: 1, reason: 'Choice 1 make lot of sense', app: 'my-app' }); ``` #### Create proposal ```javascript theme={null} import { Web3Provider } from '@ethersproject/providers'; const web3 = new Web3Provider(window.ethereum); const [account] = await web3.listAccounts(); const receipt = await client.proposal(web3, account, { space: 'yam.eth', // your space id type: 'single-choice', // define the voting system title: 'Test proposal using Snapshot.js', body: 'This is the content of the proposal', choices: ['Alice', 'Bob', 'Carol'], start: 1636984800, // change it according to your space settings end: 1637244000, // change it according to your space settings snapshot: 13620822, // Use a latest block plugins: JSON.stringify({}), labels: [], privacy: '', // Either '' or 'shutter' app: 'my-app' // provide the name of your project which is using this snapshot.js integration }); ``` #### **Create or edit a space** ```javascript theme={null} import { Web3Provider } from '@ethersproject/providers'; const web3 = new Web3Provider(window.ethereum); const [account] = await web3.listAccounts(); const receipt = await client.space(web3, account, { "space":"pistachiodao.eth", "settings": `{ "name":"pistachiodao.eth", "avatar":"", // IPFS address of space avatar "about":"", "network":"1", "symbol":"XYZ", "website": "", "twitter": "", "github": "", "coingecko": "", "domain":"", // custom domain address "skin":"", // custom skin when custom domain is set "guidelines":"", // guidelines for proposal creation "template":"", // template for new proposals "private": false, // visibility in the space list "moderators":[], // list of space Moderators "members": [], // list of Authors "admins":[], "categories":[ "social", "media" ], "plugins":{ "hal":{} }, "parent":"", // main space ID "children":[], // list of sub-spaces "voting": { "delay":0, // voting delay in seconds "hideAbstain":false, "period":0, // voting duration in seconds "quorum":0, "type":"", // define the default voting system "privacy":"" // pass "shutter" for shielded voting }, "strategies":[{ "name":"ticket", "network":"1", "params":{"symbol":"TICKET"} }], // provide up to 8 strategies with their configuration "validation":{ "name":"basic", "params":{} }, // provide one proposal validation strategy "filters":{ "onlyMembers": false // enable Authors only to create proposals }, "voteValidation":{ "name":"any", "params":{} }, // provide one voting validation strategy "treasuries":[] // provide the organization's treasury account(s) }` }); ``` #### Join a space ```javascript theme={null} import { Web3Provider } from '@ethersproject/providers'; const web3 = new Web3Provider(window.ethereum); const [account] = await web3.listAccounts(); const receipt = await client.follow(web3, account, { "space":"pistachiodao.eth" }); ``` ### **Utils** The below methods are sending a request to Score API. Same as [Hub API](/tools/api) it requires an API Key for **higher usage limits**. You can see we require it for the **`apiKey`** variable. If you already have an API Key for Hub API, you can reuse it for Score. In case you don't have an API Key, follow the instructions here: [API keys](/tools/api/api-keys) #### **getScores** Calculate voting power for a list of voters. ```javascript theme={null} import snapshot from '@snapshot-labs/snapshot.js'; const space = 'yam.eth'; const strategies = [ { name: 'erc20-balance-of', params: { address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', symbol: 'DAI', decimals: 18 } } ]; const network = '1'; const voters = [ '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11', '0xeF8305E140ac520225DAf050e2f71d5fBcC543e7', '0x1E1A51E25f2816335cA436D65e9Af7694BE232ad' ]; const snapshot = 11437846; const apiKey = 'your_api_key_here' // get an API Key for higher limits const url = `https://score.snapshot.org/?apiKey=${apiKey}` snapshot.utils.getScores( space, strategies, network, voters, snapshot, url ).then(scores => { console.log('Scores', scores); }); ``` #### getVp Retrieve voting power for a specific address using given strategies. ```javascript theme={null} import snapshot from '@snapshot-labs/snapshot.js'; const address = '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11'; const network = '1'; const strategies = [ { name: 'erc20-balance-of', params: { address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', symbol: 'DAI', decimals: 18 } } ]; const snapshot = 11437846; const space = 'yam.eth'; const delegation = false; const apiKey = 'your_api_key_here' // get an API Key for higher limits const options = { url: `https://score.snapshot.org/?apiKey=${apiKey}` } snapshot.utils.getVp(address, network, strategies, snapshot, space, delegation, options).then(vp => { console.log('Voting Power', vp); }); js ``` #### validate Validate an address using a given validation strategy. ```javascript theme={null} import snapshot from '@snapshot-labs/snapshot.js'; const validationName = 'basic'; const author = '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11'; const spaceId = 'yam.eth'; const networkId = '1'; const snapshot = 11437846; const validationParams = { minScore: 100 }; const options = {}; const apiKey = 'your_api_key_here' // get an API Key for higher limits const url = `https://score.snapshot.org/?apiKey=${apiKey}` snapshot.utils.validate(validationStrategyName, author, spaceId, networkId, snapshot, validationParams, options, url).then(result => { console.log('Validation Result', result); }); ``` #### **getProvider** Return a Ethers.js JsonRPCProvider connected to an archive node. ```javascript theme={null} import snapshot from '@snapshot-labs/snapshot.js'; const network = '1'; const provider = snapshot.utils.getProvider(network); ``` # Subgraphs Source: https://docs.snapshot.box/tools/subgraphs Query data with Subgraphs on The Graph. Snapshot’s onchain data can be easily queried with open APIs known as subgraphs. Subgraphs are decentralized APIs powered by The Graph, a protocol for indexing & querying data from blockchains. ## The Snapshot Subgraph You can see an interactive query playground on the [Snapshot subgraph’s page on The Graph Explorer](https://thegraph.com/explorer/subgraphs/4YgtogVaqoM8CErHWDK8mKQ825BcVdKB8vBYmb4avAQo?view=Query\&chain=arbitrum-one), where you can test any query. Check out the following examples: ```graphql theme={null} Example Query: Get the first 5 delegations from Snapshot { delegations(first: 5) { id delegator space delegate } } ``` Example output ```json theme={null} { "data": { "delegations": [ { "delegate": "0xde1e6a7ed0ad3f61d531a8a78e83ccddbd6e0c49", "delegator": "0x00000000005ef87f8ca7014309ece7260bbcdaeb", "id": "0x00000000005ef87f8ca7014309ece7260bbcdaeb-cvx.eth-0xde1e6a7ed0ad3f61d531a8a78e83ccddbd6e0c49", "space": }, //… ]} } ``` ## Schema The schema for this subgraph is defined [here in Snapshot’s GitHub](https://github.com/snapshot-labs/snapshot-subgraph/blob/master/schema.graphql). ## Snapshot Subgraph endpoint [https://gateway.thegraph.com/api/\\\[api-key\]/subgraphs/id/4YgtogVaqoM8CErHWDK8mKQ825BcVdKB8vBYmb4avAQo](https://gateway.thegraph.com/api/\\\[api-key]/subgraphs/id/4YgtogVaqoM8CErHWDK8mKQ825BcVdKB8vBYmb4avAQo) This is visible from the [Snapshot subgraph’s page](https://thegraph.com/explorer/subgraphs/4YgtogVaqoM8CErHWDK8mKQ825BcVdKB8vBYmb4avAQo?view=Query\&chain=arbitrum-one) on Graph Explorer. ## How to obtain your own API key 1. Go to [thegraph.com/studio](https://thegraph.com/studio) and connect your wallet. 2. Go to [https://thegraph.com/studio/apikeys/](https://thegraph.com/studio/apikeys/) to create an API key. 3. You can use this API key on any subgraph on [Graph Explorer](https://thegraph.com/explorer), and it’s not limited to just Snapshot. ## Other Snapshot Subgraphs * [**Snapshot on Arbitrum**](https://thegraph.com/explorer/subgraphs/HuLBhuKuknXEEUmVmKR8Lsmpi5h1SfNLGcaa1e9tWyMG?view=Query\&chain=arbitrum-one) * [**Snapshot on Fantom**](https://thegraph.com/explorer/subgraphs/szZ3FWewDGHtpeZzf6uQ5dxPY68JNfrGPoWqBXwtBXR?view=Query\&chain=arbitrum-one) * [**Snapshot on Gnosis Chain**](https://thegraph.com/explorer/subgraphs/2XuuZyGrxw72keXKfeHQW7yaGqVa7dyoghkgdGMdC6Az?view=Query\&chain=arbitrum-one) [See all other subgraphs published by Snapshot Labs.](https://thegraph.com/explorer/profile/0x8c28cf33d9fd3d0293f963b1cd27e3ff422b425c?view=Subgraphs\&chain=arbitrum-one) ## How to Query through the API You can pass any GraphQL query to the Snapshot endpoint and receive data in JSON format. This following code example will return the exact same output as above. ### Sample code (Node.js): ```javascript theme={null} const axios = require('axios'); const graphqlQuery = `{ delegations(first: 5) { id delegator space delegate } }`; const queryUrl = 'https://gateway.thegraph.com/api/[api-key]/subgraphs/id/4YgtogVaqoM8CErHWDK8mKQ825BcVdKB8vBYmb4avAQo'; const graphQLRequest = { method: 'post', url: queryUrl, data: { query: graphqlQuery, }, }; // Send the GraphQL query axios(graphQLRequest) .then((response) => { // Handle the response here const data = response.data.data; console.log(data); }) .catch((error) => { // Handle any errors console.error(error); }); ``` ## How to use the Visual Query Editor You can use the GraphiQL Explorer to compose your GraphQL queries by clicking on the fields you want. # Overview Source: https://docs.snapshot.box/tools/tools-overview Learn how you can integrate Snapshot into your product, query our APIs or set up webhooks and notifications. Use Snapshot's JavaScript library to integrate features like space and proposal creation, voting, and more in your product. Query the GraphQL API exposing Snapshot's data like information about spaces, proposals, voting, and more. Set up a webhook to receive notifications about specific events to your endpoint. Use automated bots to get notified about proposals on Snapshot. # Webhooks Source: https://docs.snapshot.box/tools/webhooks Receive event notifications with webhooks. Snapshot uses webhooks to notify your application when an event happens. Webhooks are particularly useful for asynchronous events like when a proposal is created, when it starts, or when it ends. The webhook server sends a request for any new event, the request is sent to the configured URL with `POST` method and the event object as body. **Here is an example of the event object:** ```javascript theme={null} { id: 'proposal/QmZ21uS8tVucpaNq2LZCbZUmHhYYXunC1ZS2gPDNWwPWD9', event: 'proposal/created', space: 'yam.eth', expire: 1620947058 } ``` **Here are the possible events:** `proposal/created` \ When a new proposal is created `proposal/start` \ When the voting period for a proposal starts. `proposal/end` \ When the voting period for a proposal ends. `proposal/deleted` \ When a proposal is deleted by the author or an admin of the space. ### Test a webhook You can use this URL [https://webhook.snapshot.org/api/test?url=https://example.com](https://webhook.snapshot.org/api/test?url=https://example.com) and change example.com with your own endpoint to trigger a test callback. ### Subscribe to events If you want to subscribe to Webhooks, please fill out this [form](https://tally.so/r/mVQZQl). If you don't receive events even after 48 hours after filling the form, please contact our support on [Help Center](/faq/support-and-feedback). # Create a proposal Source: https://docs.snapshot.box/user-guides/create Learn what a proposal is and how to create one. A proposal is the key element of the voting system. It presents a change suggestion related to a specific organization and enables eligible users to cast their vote. A specific [voting system](/proposals/voting-types) (single choice, weighted, quadratic, and others) can be selected individually for each proposal. Voting power for each user is calculated on the basis of the voting strategies selected in the [space settings](/user-guides/voting-strategies). ## Who can create a proposal? Space [controller](/user-guides/spaces/space-roles),[ admins](/user-guides/spaces/space-roles), [authors](/user-guides/spaces/space-roles), and users who are eligible according to the [proposal validation](/user-guides/validation-strategies) strategies defined in the space settings. **Proposal limit** Each space has a limit on the number of proposals that can be created daily and monthly. For more details have a look at [#proposals-limitations](#proposals-limitations). ## Create a proposal 1. Head to the space which you wish to create your proposal for. 2. Connect with the wallet provider - make sure the connected wallet is **where you hold the tokens relevant** to the specific space. 3. Click the pencil icon in the top-right corner of the space page to start a new proposal: 4. The proposal editor opens with a two-column layout. On the left, fill in the following fields:\ \- **Title** (required)\ \- **Body** (optional, markdown supported - you can switch between markdown and visual editor)\ \- **Discussion** link (optional)\ \- **Execution** (if the space has a treasury configured)\ \ On the right sidebar, configure:\ \- **Voting system** (e.g. Basic voting, Single choice, Weighted, etc.)\ \- **Choices** (pre-filled with For / Against / Abstain for basic voting)\ \- **Labels** (if the space has labels configured)\ \- **Timeline:** set the start and end dates for voting. Make sure you allow enough time for users to vote. 5. Click `Publish` in the top-right corner - and that's it! You can see your proposal in the proposals list on the space page. ## **Snapshot block number** When you create a proposal by default the **snapshot block number** will be populated with the latest block synced from our node. The voting power of each user will be calculated for the **state of the blockchain at this specific snapshot**. It means that if the user acquires required tokens **after** the proposal has been created, they will not be taken into account for their voting power calculation. ### Proposals limitations * Each proposal's description is limited to **10,000 characters**. With the [Snapshot Pro](/user-guides/spaces/pro) plan, the limit increases to **50,000 characters**. * One address can have a maximum of **20 active proposals at a time**, across multiple spaces. * Each space has a limit on the number of proposals created daily and monthly: | Space status | Daily proposal limit | Monthly proposal limit | | -------------------------------------------- | --------------------------- | ---------------------- | | [Pro](/user-guides/spaces/pro) | 100 | 500 | | [Verified](/user-guides/spaces/get-verified) | 10 | 50 | | Unverified | 5 | 10 | | Flagged | 0 — cannot create proposals | 0 | Learn more about Space verification and flagging in [badges-and-warnings](/user-guides/spaces/badges-and-warnings). * You can combine up to **4** [voting strategies](/user-guides/voting-strategies). The limit also applies to multi-chain strategies. ([Pro](/user-guides/spaces/pro) spaces can add up to **12** strategies) * All testnet spaces will have the same proposal limits as a Verified space * Can add up to **10** choices on a proposal ([Pro](/user-guides/spaces/pro) spaces can add up to **1000** choices) # Delegation Source: https://docs.snapshot.box/user-guides/delegation Discover the delegates of specific spaces and delegate your Voting Power directly through Snapshot, ## How to delegate? Snapshot enables a couple of ways to delegate your Voting Power to another address (a delegate). You can delegate your Voting Power via: * [Delegates registry per space](#delegates-registry) - if the space has set up a custom delegation contract. A great solution if you are not sure who to delegate to. * [Snapshot's delegation page](#delegate-page) - the quickest solution to delegate to a known address. * [Smart contract](#smart-contract-interaction) - if you prefer to interact with the contract directly. ### Delegates registry This page only applies to custom delegation contracts. To see the Snapshot native delegation, head to: **[https://snapshot.box/#/delegate/space-name.eth](https://snapshot.box/#/delegate/space-name.eth)** It is possible to discover the Delegate registry of Spaces that provided their custom delegation contract in settings. Head to the Space page and click **Delegates** in the left sidebar: You will then see a list of delegates for the Space with the number of their delegators and their total Voting Power within the Space. You can delegate your Voting Power to one of the delegates directly by clicking the **`Delegate`** button: ### Delegate page 1. Go to [snapshot.box/#/delegate](https://snapshot.box/#/delegate) 2. Enter the address you want to delegate to. 3. To limit the delegation to a specific space, tap the on switch button and enter the space key (example: `balancer.eth`) you want your delegation to take effect on. If no space is selected, the effect will take place for all spaces. 4. Click confirm to save your delegation. The **direct delegation** to a chosen space has priority over the **all spaces** delegation. What does it mean? Address A delegates to B for all spaces, and A delegates to C for a chosen space. The chosen space uses overriding delegation strategy.\ B votes first - their VP is taken into account.\ C votes - their vote has priority (direct single space delegation) and erases B's Voting power (all spaces delegation).\ A votes - B and C's Voting Power decreased to 0. ### Smart contract interaction You need to call the `setDelegate` method with the space id as the first argument (space id is its ENS domain name, for example *fabien.eth)*, and the address of the delegate as the second argument. Here is an example of integration in a Solidity contract: [https://github.com/convex-eth/platform/blob/d3061c19b5e01a4e562c8121b08c44f1b42f0b85/contracts/contracts/BasicCvxHolder.sol#L49-L53](https://github.com/convex-eth/platform/blob/d3061c19b5e01a4e562c8121b08c44f1b42f0b85/contracts/contracts/BasicCvxHolder.sol#L49-L53) #### Supported networks * Mainnet * Sepolia * Optimism * Arbitrum * Polygon * BNB Chain * Gnosis Chain * Fantom * Base * Base sepolia * Linea * Blast * Sonic * Mantle ## Delegation contract Snapshot uses the Gnosis "Delegate Registry" contract here: [https://github.com/gnosis/delegate-registry](https://github.com/gnosis/delegate-registry) The contract is deployed on this address: [0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446](https://etherscan.io/address/0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446#code). The contract is also available on "Supported networks" listed above. Delegations are stored on this subgraph: [https://thegraph.com/explorer/subgraph/snapshot-labs/snapshot](https://thegraph.com/explorer/subgraph/snapshot-labs/snapshot) A **delegation Voting Strategy must be added** to the Snapshot space before delegated votes will be counted. You can use the [**with-delegation**](https://snapshot.box/#/strategy/with-delegation) strategy. # Premium voting strategies Source: https://docs.snapshot.box/user-guides/premium-voting-strategies Some Snapshot voting strategies require significant computation and are only available to [Snapshot Pro](/user-guides/spaces/pro) spaces. These are called premium voting strategies. ## List of premium strategies * aura-vlaura-vebal-with-overrides * balance-of-with-linear-vesting-power * balancer-delegation * cyberkongz * cyberkongz-v2 * delegation * delegation-with-cap * delegation-with-overrides * erc20-balance-of-delegation * erc20-balance-of-fixed-total * erc20-balance-of-quadratic-delegation * erc20-votes-with-override * esd-delegation * ocean-dao-brightid * orbs-network-delegation * api-v2-override * rocketpool-node-operator-delegate-v8 * eden-online-override * split-delegation * sonic-staked-balance If you are currently using the "delegation" strategy and want to move to a non-overriding alternative, see the [migration guide](/faq#how-do-i-migrate-from-delegation-to-with-delegation-strategy). # Add a custom domain Source: https://docs.snapshot.box/user-guides/spaces/add-custom-domain Use a custom domain to host your Snapshot space directly on your own URL. Your community will see only your space with your logo and colors matching your brand for a fully branded governance experience. ### Examples More than 200 DAOs already use custom domains for their governance, such as: [vote.worldlibertyfinancial.com](https://vote.worldlibertyfinancial.com)\ [governance.starknet.io](https://governance.starknet.io)\ [vote.convexfinance.com](https://vote.convexfinance.com) ### Requirements This feature is available with the [Snapshot Pro](/user-guides/spaces/pro) plan. Once your subscription is active, follow the setup process below. ### Setup steps #### 1. Create a CNAME record Log in to your domain provider and add a new CNAME record: * **Host:** the domain or subdomain you want to use (e.g., `vote.convexfinance.com`) * **Points to:** `cname.snapshot.box` #### 2. Contact us After you have created the CNAME record, contact us via the messenger on our [Help Center](/faq/support-and-feedback) to confirm your custom domain. We'll handle the rest and activate your branded Snapshot space. ## Migrating from a whitelabel Effective August 15, 2025, whitelabel (custom domain) functionality is a Snapshot Pro feature. To continue using your custom domain, please subscribe to [Snapshot Pro](https://snapshot.box/#/pro). If you prefer to disable your custom domain, remove the CNAME record from your DNS provider and consider setting up a redirect from your old domain to your main website. # Space badges Source: https://docs.snapshot.box/user-guides/spaces/badges-and-warnings Learn about the meaning of space badges At Snapshot Labs, we want to help our users safely browse and discover spaces and make informed decisions about them. That's why we've introduced verification and warning badges. The goal is to provide users a simple way to navigate voting in web3. To facillitate that Snapshot displays a verification badge or warning label next to the space name and in each proposal belonging to that space. The **verification badge** signifies that the space has been verified as the authentic version of the protocol it claims to be. Please note that the verified badge does not represent an endorsement of the protocol by Snapshot Labs. A verified badge also says nothing about its merits as an investment. A space may carry a verified badge but might still be a bad investment idea. Think of the verified badge only as a tool to help you find the correct version of the space you're searching for. If you would like to get your space verified, head to [get verified](/user-guides/spaces/get-verified) and follow the guide. The **warning badge** means that we either identified that space as impersonating a project, IP infringement or potential scam.
BadgeLabelDescription
Pro spaceVerified space with Pro plan
VerifiedManually curated by Snapshot Labs to identify spaces that passed the verification criteria.
WarningManually curated by Snapshot Labs to identify spaces that impersonate a project, infringe IP, or spaces that are proven to be scams.
Voting on a proposal which belongs to a space flagged with the warning badge **is not dangerous** as the vote does not trigger a transaction - your account and assets are safe. # Cover image size Source: https://docs.snapshot.box/user-guides/spaces/cover-image-size Cover images in Snapshot spaces are displayed at a dynamic size that can change depending on the screen size, so the top and bottom may be cut off. We recommend using a **1500 x 400** pixel image and keeping important elements away from the edges. You can preview how the cover will look in your space settings before saving. # Create a space Source: https://docs.snapshot.box/user-guides/spaces/create This page guides you step by step through the process of creating a space for your organization. If you want to experiment with Snapshot before creating a real space, try [testnet.snapshot.box](https://testnet.snapshot.box) - a Sepolia testnet playground for testing. To create a new Snapshot space, you need an ENS name. For spaces on [snapshot.box](https://snapshot.box), you'll need an ENS name on Ethereum mainnet. For spaces on [testnet.snapshot.box](https://testnet.snapshot.box), you'll need an ENS name on Sepolia. You can register one at [ens.domains](https://ens.domains). To get started, go to [snapshot.box/#/create](https://snapshot.box/#/create) or click the **+** button in the left sidebar. You will be guided through the following steps. ### 1. Profile Set up your space's identity. Enter a **name** (required) and optionally add a description, avatar, cover image, categories, voting power symbol, and social accounts (website, GitHub, X, Farcaster, CoinGecko). You can update this information at any time after creating the space. ### 2. Domain name Select your space's domain name. You need an ENS name on Ethereum mainnet or a web3 domain name on a mainnet network. Your available domains will be listed automatically. If you don't have a domain, you can register a new ENS name or attach a custom domain. By default, the space's controller is the domain owner. ### 3. Network Select the base network for your space. ### 4. Voting strategies Choose how your users' votes are counted through a set of strategies. You can pick from common strategies like **ERC-20**, **ERC-20 Votes**, **ERC-721**, or **ERC-1155**, or browse the full list to add a custom strategy. Each strategy takes into account the assets that belong to the voting address **at the time of proposal creation**, not at the time of voting. ### 5. Proposal validation Configure who is allowed to create a proposal. Options include: * **Only authors can propose:** restrict proposal creation to designated authors * **Basic:** use a minimum score with any strategy to determine eligibility * **Gitcoin Passport gated:** require users to have a Gitcoin Passport * **Karma EAS Attestation:** use EAS attestations for eligibility ### 6. Voting settings Set the **voting delay** (time between proposal creation and voting start) and the **voting period** (how long voting remains open). If left empty, the proposal author will be able to set these values. ### 7. Members Assign roles and permissions to your space members. Available roles: * **Admin:** can modify settings, manage proposals, and create proposals * **Moderator:** can manage proposals and create proposals * **Author:** can create proposals without validation Once everything is configured, click **Create space** to finalize. # Alternative way to create a space Source: https://docs.snapshot.box/user-guides/spaces/create/alternative-way-to-create-a-space If you do not want to have the wallet control your settings, you can follow the steps below to create a space on Snapshot. ### Drawbacks * You will not be able to change settings from the UI * Every time you want to change the settings, you will need to broadcast a new transaction ### How to create a space * Create a JSON file for your settings on Snapshot. The format of the JSON file could be as follows: [https://github.com/snapshot-labs/snapshot.js/blob/master/test/examples/space.json](https://github.com/snapshot-labs/snapshot.js/blob/master/test/examples/space.json) * Store the JSON file on IPFS * Use the IPFS link on the ENS text record. This will make the ENS owner the only controller of the settings. ![](https://lh6.googleusercontent.com/qfA-Pj7o2Fvld76V2gZIJm9U1V0uRBgNdedfxU4iKjGDfE3cHH7KLMx26eawZPD0Zl8j3H7AAfFsToDdl9ViQ5Y7WyI8FACqVlkc5JG9zwcyZg877KmnH6cf2vleHnn-icWLGTg=s0) * You can check if your space is valid from the GitHub link below [https://github.com/snapshot-labs/snapshot.js/blob/a0adc547aa0922aa6abd35708a4a292048bca6a2/test/schema.ts#L4](https://github.com/snapshot-labs/snapshot.js/blob/a0adc547aa0922aa6abd35708a4a292048bca6a2/test/schema.ts#L4) * Once the above transaction is successful, go to the below link to update the space in Snapshot: `https://hub.snapshot.org/api/spaces/`**``**`/poke` # Register an ENS domain Source: https://docs.snapshot.box/user-guides/spaces/create/ens-domain To create your space on Snapshot you need to have an ENS domain. This page will take you through the steps to create an ENS domain. **ENS on Ethereum Mainnet** To register a space on [snapshot.box](https://snapshot.box) you need an ENS domain on **Ethereum Mainnet** even if you want to use Ethereum Testnet or any other network (Binance Smart Chain, Gnosis Chain, etc). If you want to experiment with the platform you can register a test space on [testnet.snapshot.box](https://testnet.snapshot.box) using an ENS on Sepolia Testnet. If you already have an ENS domain, feel free to skip this and follow the [create a space](/user-guides/spaces/create) guide. ### Creating an ENS domain **1a.** Search for the availability of your name on Snapshot's `Create a space` page **1b.** Search for the availability of your name on [ENS](https://app.ens.domains/). **2.** If the name is available you will be able to see the 3 steps and the registration fee. Please note that the names with 3 or 4 characters cost considerably more than the names with 5+ characters. **3.** Connect your wallet by tapping on the `Connect` button on the top left corner of your screen. Make sure your wallet has enough balance to make the transaction successful and that you selected Ethereum Mainnet (or Sepolia Testnet for the demo page). **4.** Confirm all transactions for the three steps from your chosen wallet provider. **5.** You have now successfully registered on ENS! Additionally, you can also make your Ethereum address point to an ENS name by clicking on ‘Set Reverse Record’ or by going to 'My Account' and then selecting 'Reverse record' and completing the transaction. You have created your domain on ENS and are now ready to create your space on Snapshot. If you want to register a custom domain you already own, check out the [ENS DNS Registrar guide](https://docs.ens.domains/dns-registrar-guide). # Space verification Source: https://docs.snapshot.box/user-guides/spaces/get-verified This page explains what a space verification is and how to get verified. ## Verification for legitimacy Space verification is a process of checking if the space is real and can be trusted. Verified spaces have a special badge next to their name, as shown in the screenshot below. Don't worry if you voted on a proposal of a fake space - signing a message doesn't cause any implications for you. ## How to get your space verified? To get your space verified on Snapshot, ensure it meets the following criteria: * Space has an **avatar** image uploaded * Space has a **description** * There is at least **1 proposal** * The space has at least **5 followers** * There are at least **10 votes** across proposals * A **treasury** is configured * **Ownership verification** through an official website, GitHub organization, or a tweet linking to the Snapshot space Once your space fulfills these requirements, contact our support on [Help Center](/faq/support-and-feedback) to request verification. The review process may take up to 72 hours. Verification status is valid as long as the space **meets all requirements.** # Migrate or delete a space Source: https://docs.snapshot.box/user-guides/spaces/migrate-or-delete ## Delete a space If you are a space controller you can delete the space through Snapshot's interface directly. Deleting a space **cannot be reversed** and you will **not be able to create a new space** with the same ENS domain name. Go to your space **Settings** and select the **Advanced** tab: Scroll down to the **Danger zone** section and click **Delete space**: Confirm the space deletion with the **space ID** and sign a message in your wallet. ## Migrate a space If you have an existing Snapshot space and need to move it to a new ENS domain, follow the steps below: ### Step 1: Create a new space Set up a fresh Snapshot space under your new ENS domain. If you want to keep the same configuration (profile, voting strategies, etc.), get in touch once the new space is created. The team will copy over those settings so you don't have to reconfigure everything. ### Step 2: We migrate your existing activity The Snapshot team will manually migrate all proposals, votes, followers, and related data from your old space, ensuring your community doesn't lose any activity. When the migration is complete, links to your old space or proposals will automatically redirect users to the new ENS domain. Contact our support on [Help Center](/faq/support-and-feedback) to request a migration. # Snapshot Pro Source: https://docs.snapshot.box/user-guides/spaces/pro Snapshot Pro is designed for spaces seeking advanced governance tools. By upgrading to Pro, you gain access to a powerful set of features that streamline proposal creation, voting, and oversight. **Subscribe:** [**snapshot.box/#/pro**](https://snapshot.box/#/pro) ## Features * **Increased proposal limits:** Up to 100 proposals per day and 500 per month * **Extended character limit:** Up to 50,000 characters for proposal descriptions * **More voting strategies:** Combine up to 10 strategies (vs 8 for free) * **More choices:** Up to 1,000 choices per proposal (vs 20 for free) * **Premium voting strategies:** Access to [computation-heavy strategies](/user-guides/premium-voting-strategies) * **Custom domain:** Host your space on your own URL with full branding * **Delegation dashboard:** Custom delegation dashboard for your space * **Dedicated support:** Direct access to the Snapshot team via Telegram ## Payment options We accept payments exclusively in cryptocurrency on the Ethereum network. You can use **USDC**, **USDT**, or **GHO** to subscribe. ### Payment contract address All payments are processed through the Schnaps contract: `0xe40bfeb5a3014c9b98597088ca71eccdc27ca410` This is the only contract address used for Snapshot Pro payments, deployed only on Ethereum mainnet. The [contract code is open source](https://github.com/snapshot-labs/schnaps). Always double-check the contract address before making a payment. If you see a different address or chain, it is not official. ## Free trial Yes, we offer a **1-month free trial** on Snapshot testnet. Trials are approved manually. Please contact us via the messenger on our [Help Center](/faq/support-and-feedback) to request your free trial. ## Cancellation policy Subscriptions to Snapshot Pro cannot be canceled once activated. ## Dedicated support To access dedicated support, reach out directly to **@bonustrack** on Telegram. Provide your Snapshot Pro subscription confirmation along with your space ID, and we will set up a dedicated Telegram support group for you. ## Delegation dashboard The delegation dashboard setup requires manual assistance. Please contact **@bonustrack** on Telegram to request help with configuring your delegation dashboard. ## Custom domain Use a custom domain to host your Snapshot space directly on your own URL. See [Add a custom domain](/user-guides/spaces/add-custom-domain) for setup instructions. # Settings Source: https://docs.snapshot.box/user-guides/spaces/settings Customize your space settings, manage members, voting strategies, validation, and more. ## Access your settings As a space admin, you can access the settings page from the space sidebar. The settings are organized into tabs, each covering a specific aspect of your space configuration. You can navigate directly to the settings page with the URL: `https://snapshot.box/#/s:<YOUR-SPACE>/settings` ## Profile Edit your space's profile information including name, description, avatar, cover image, categories, voting power symbol, and social accounts (website, GitHub, X, Farcaster, CoinGecko). ### Social accounts Link your social media accounts by entering your handle in the corresponding fields. ## Controller The controller is the account able to change the space settings and cancel pending proposals. By default it's set as the ENS domain owner, but you can change it to another address. ## Voting strategies Specify how voting power should be calculated by adding up to 6 strategies. Select a network and add strategies from the available list. Voting power is cumulative across strategies. To learn more about strategies, head to [voting-strategies](/user-guides/voting-strategies). ## Members Assign roles and permissions to your space members: * **Admin:** can modify settings, manage proposals, and create proposals * **Moderator:** can manage proposals and create proposals * **Author:** can create proposals without validation Head to [space-roles](/user-guides/spaces/space-roles) to learn more about each role. ## Proposal Configure proposal guidelines, templates, and validation. The proposal validation determines who is allowed to create a proposal. ### Proposal validation To validate if someone can post a proposal, you can use the basic validation which checks voting power against a minimum threshold, or restrict proposals to authors only. To learn what a validation is head to [validation-strategies](/user-guides/validation-strategies). ## Voting Set the **voting delay** (time between proposal creation and the start of voting) and the **voting period** (duration that voting remains open). Configure **quorum** (the amount of voting power required for a proposal to pass), **type** (voting system), **privacy**, and **vote validation**. ### Shielded voting You can enable shielded voting if you want to enable partial privacy and reduce voter apathy. Powered by Shutter, it uses threshold encryption so that voters' choices are private during the voting period and revealed when the proposal closes. To enable it, select **Shutter** in the **Privacy** dropdown on the Voting tab. ## Delegations Set a custom delegation contract to enable delegate discovery for your space. Once set, the delegates registry will be visible in the **Delegates** tab on the space page. ## Advanced Configure parent and children spaces (sub-spaces), terms, and other advanced settings. To learn more about sub-spaces, head to [sub-spaces](/user-guides/spaces/sub-spaces). ## Custom domain You can add a custom domain to your space in the **Custom domain** tab. Head to [add-custom-domain](/user-guides/spaces/add-custom-domain) for a step-by-step guide. ## Treasuries Link your organization's treasury to Snapshot by adding the treasury network, address, and name. You can add multiple treasuries to one space. ## Save your settings Make sure to click the **Save** button to apply your changes. You will need to **sign a message** (gasless) in your wallet to confirm. # Space roles Source: https://docs.snapshot.box/user-guides/spaces/space-roles Learn what the space roles are and how you can assign them to users. ## What is a role? Snapshot spaces use a hierarchical role system to manage governance and participation. The four main roles are Controller, Admin, Moderator, and Author, each with specific permissions. ## Role permissions ### Controller The **Controller** is the highest authority, limited to a single entity per space. They have full control, including adding or removing admins, editing space settings, canceling proposals, and publishing proposals. Controllers can be represented by smart contract wallets like Safe, and sometimes the space itself serves as the Controller. ### Admin **Admins** can edit space settings, cancel proposals, and publish proposals but cannot add or remove other admins. ### Moderator **Moderators** can cancel proposals and publish proposals but cannot edit settings or manage admins. ### Author **Authors** can publish proposals without needing voting power or meeting proposal validation requirements. They have no other administrative permissions. On Snapshot X there is only one role: the Controller. The Controller can change settings and cancel proposals. ## Assign a role to a user ### Controller The controller is first assigned during the process of space creation. By default, it is the ENS domain controller. There can be only **one controller** per space and it can be updated **only by the ENS owner.** To view or update the controller, go to your space **Settings** and select the **Controller** tab: Click the edit icon next to the controller address, paste the address of the new controller, and confirm. This will trigger your wallet and ask you to sign a **transaction with a gas fee.** ### Admins, moderators, and authors To manage members, go to your space **Settings** and select the **Members** tab. You can add addresses and choose their applicable role from the dropdown: # Sub-spaces Source: https://docs.snapshot.box/user-guides/spaces/sub-spaces Create a link between multiple spaces of your organization Organizations can create multiple spaces and link them together. Adding a sub-space displays its proposals within your space. This is useful for enforcing different space settings for proposal creation, voting, and execution. For example, instead of having to change the space settings each time you create a proposal, you could create additional spaces with some of your most frequently used settings. ### Setup You can configure sub-spaces in the **Advanced** tab of your space settings: 1. Go to your space **Settings** and select the **Advanced** tab. 2. Set a **Main space** to indicate the parent space of the current space. 3. Use the **Sub-space(s)** field to add child spaces, then click **Add space**. To make the relationship visible on both sides, the sub-space also needs to add your space as its main space in its own settings. Once configured on both sides, the sub-spaces will be displayed on the space overview page. ### Limits * A space can add up to 16 sub-spaces # What is a space? Source: https://docs.snapshot.box/user-guides/spaces/what-is-a-space A space on Snapshot is a custom place for each organization to handle its own voting and decisions. It's where members come to see proposals and decide on them together, using settings the organization sets up. A space serves as a hub for all proposals related to the organization and a source of information for users. It allows the organization to manage roles of its members and customize proposal and voting settings. Please note that any updates will not affect proposals which already exist, only the new ones will be affected. For more details have a look at the [settings](/user-guides/spaces/settings) section. ### How to access a space? Spaces are listed on the **Explore** page at [https://snapshot.box](https://snapshot.box) and can be filtered by protocol, network, and category. You can search for a space by name using the search bar. You can access a space directly through a link that includes the ENS name (e.g. [https://snapshot.box/#/s:vanilladao.eth](https://snapshot.box/#/s:vanilladao.eth)). It is also possible to define a **custom domain name** for your space. Browse spaces ### Proposal search and filtering You can browse through all of a space's proposals on the **Proposals** page. Use the **Status** dropdown to filter by pending, active, or closed proposals. If the space uses labels, you can also filter by **Labels**. ### Following a space If you want quick access to a space you can follow it from the explore page or through the space's page by clicking the **Follow** button. It will create a shortcut for the space on the left sidebar. ### Space page The space overview page displays the space's cover image, avatar, name, and key stats such as the number of proposals, votes, and followers. Below the header, you can see a summary of recent proposals. The sidebar provides navigation to the space's proposals, leaderboard, delegates, and treasury. Vanilla DAO space overview # Using Safe multisig Source: https://docs.snapshot.box/user-guides/using-safe-multi-sig Learn how you can use Snapshot with a Gnosis Safe multisig wallet. Voting with a Safe is possible using two methods: an offchain signature or a transaction. You can select your preferred method in the Safe interface under Settings > Safe Apps. You can also use a Safe to create proposals or set up a space on Snapshot. Your Safe has to be on the same network as the Space is. Head to Space settings, **Strategies** tab to check the Space's network. **Spaces can be created and updated** only by Ethereum Mainnet accounts. Voting and proposals are accepted from Space's network only. ## Connecting your Safe To connect your Safe to Snapshot 1. Go to your Safe wallet like `https://app.safe.global/apps/open?safe=<NETWORK>:<SAFE_ADDRESS>` 2. Go to the **Apps** tab. 3. Search for Snapshot and click on it. 4. You should now see the Snapshot interface connected to your Safe wallet. [https://www.loom.com/share/f02b6ec7a95e44a88f9a4ebba281e002](https://www.loom.com/share/f02b6ec7a95e44a88f9a4ebba281e002) ## Signing with your Safe There are two ways to sign with your Safe multisig wallet on Snapshot: 1. **Synchronous signing (offchain):** you keep the confirmation modal open until all Safe signers confirm the transaction. 2. **Asynchronous signing (onchain):** you can close the confirmation modal and the transaction will be created in your Safe transactions queue. The Safe signers can confirm it later. For more information, refer to the [Gnosis Safe documentation](https://help.safe.global/en/articles/40783-what-are-signed-messages). ### Synchronous signing By default, the first signer who is signing a message will have to keep the confirmation modal open until all other signers confirm the message. This happens offchain and does not create a transaction in your Safe transactions queue. but in messages tab of your Safe. Other signers need to confirm the message in their Safe interface. ### Asynchronous signing If you'd like to enable asynchronous signing for all Safe's signers and not have to keep the modal open, you have to enable onchain signatures in the Safe settings.\\ 1. Go to Safe Settings -> Safe Apps. 2. Enable `Always use onchain signatures` Signers can now sign even if you close the confirmation modal. It will create a pending transaction in your Safe transactions queue. This transaction must be confirmed by the Safe signers within **144 hours.** # Validation strategies Source: https://docs.snapshot.box/user-guides/validation-strategies ## What is a validation strategy? A voting validation is a JavaScript function that returns a boolean (`true` or `false`) for the connected account. Voting validations are being used on Snapshot to decide if an **account can vote** or **create a proposal** in a specific space. Each space can use one voting validation for all of its proposals at a time. While voting strategies calculate the Voting Power mainly on the basis of the monetary assets, the validation strategy can serve as a protection against **Sybil attacks**. It can take into consideration how many POAPs an account owns or track the account activity to assess if the account is a bot or a **real human**. The **default** validation is checking if the address has **any voting power.** If the voting power is higher than `0` the connected account is validated. A validation strategy can send a call to a node or subgraph. When setting the Validation Strategy up it’s important to keep in mind that it is **meant to make it difficult for users outside of your community to post scam proposals or post spam votes.** Therefore for Proposal Validation make sure to use a **high threshold**, for example \$100 worth of your organization’s token. A good idea would be to check the holdings of previous proposal creators, both legitimate and scammers, to assess a reasonable value. Spaces are required to use **Proposal Validation**. Learn how to set it up on this page or read [**our article**](https://snapshot.mirror.xyz/-uSylOUP82hGAyWUlVn4lCg9ESzKX9QCvsUgvv-ng84)**.** Spaces using only a [ticket strategy](https://snapshot.box/#/strategy/ticket) are required to set a Voting Validation to secure their spaces and ensure a fair voting process preventing spam. Learn here how to set it up: [#voting-validation-in-space-settings](#voting-validation-in-space-settings) ## How to use validation strategies: Validation strategies can be used for two purposes: * proposal validation - determine if the account can create a new proposal, * voting validation - determine if the account can take part in the voting process. #### Proposal Validation in Space Settings Head to **Proposals** tab in the sidebar to update the configuration: #### Voting Validation in Space Settings Head to **Voting** tab in the sidebar to update the configuration: If you want to allow addresses with any voting power to vote you can use the default voting validation. If you are using only a [ticket](https://snapshot.box/#/strategy/ticket) Voting Strategy for your space you are required to use a [Gitcoin Passport Validation](#validation-strategy-example-gitcoin-passport) for Voting to protect your space from spam votes. ## Authors only mode If you wish to limit proposal creators to Admins, Moderators and Authors only, you can do so by enabling the **Authors only** setting in the **Proposal** tab in the space settings. Make sure to give the Author role to the users you trust! ## Validation strategy example: Basic The Basic validation strategy allows you to use existing Voting Strategies configured for your space or define a custom setup to determine if a user is eligible to create a proposal or cast a vote. In order to use existing setup of Voting Strategies you can simply chose **Basic Validation** and define a required threshold as on the screenshot below. `100` corresponds to user's Voting Power calculated on the basis of the Voting Strategies. Use current setup and define a strong threshold to avoid spam in your space. If you wish to use a different configuration, toggle the **Use custom strategies** button and define the strategies for your use case: Use a custom setup using various Voting Strategies to calculate if a user is eligible to create a proposal or vote. ## Validation strategy example: Gitcoin Passport Validation strategy built together with **Gitcoin Passport.** You can select individual or multiple stamps that matter for your space. You can also decide if they need to meet all of these criteria or only one. The more criteria you select, the more sybil resistant your space is. #### Implementation Have a look at the example of the Gitcoin Passport validation strategy. [https://github.com/snapshot-labs/score-api/blob/master/src/strategies/validations/passport-gated/index.ts](https://github.com/snapshot-labs/score-api/blob/master/src/strategies/validations/passport-gated/index.ts) ```javascript theme={null} import snapshot from '@snapshot-labs/snapshot.js'; import Validation from '../validation'; import { getPassport, getVerifiedStamps, hasValidIssuanceAndExpiration } from '../passport-weighted/helper'; export default class extends Validation { public id = 'passport-gated'; public github = 'snapshot-labs'; public version = '0.1.0'; async validate(): Promise { const requiredStamps = this.params.stamps; const passport: any = await getPassport(this.author); if (!passport) return false; if (!passport.stamps?.length || !requiredStamps?.length) return false; const verifiedStamps: any[] = await getVerifiedStamps( passport, this.author, requiredStamps.map((stamp) => ({ id: stamp })) ); if (!verifiedStamps.length) return false; const provider = snapshot.utils.getProvider(this.network); const proposalTs = (await provider.getBlock(this.snapshot)).timestamp; const operator = this.params.operator; // check issuance and expiration const validStamps = verifiedStamps .filter((stamp) => hasValidIssuanceAndExpiration(stamp.credential, proposalTs) ) .map((stamp) => stamp.provider); if (operator === 'AND') { return requiredStamps.every((stamp) => validStamps.includes(stamp)); } else if (operator === 'OR') { return requiredStamps.some((stamp) => validStamps.includes(stamp)); } else { return false; } } } ``` Voting validation can be specified in your space settings at `https://snapshot.box/#/s:/settings`. ## Create a custom validation The possibilities are endless! You can build a custom validation strategy for your space. Please have a look at [validation-strategy](/developer-guides/validation-strategy) for more details. ## Find more voting validations here: [https://github.com/snapshot-labs/score-api/tree/master/src/strategies/validations](https://github.com/snapshot-labs/score-api/tree/master/src/strategies/validations) # Voting strategies Source: https://docs.snapshot.box/user-guides/voting-strategies Learn what a voting strategy is and how to set it up. ## What is a voting strategy? Voting strategies determine how voting power is calculated for Snapshot proposals based on specific rules or conditions. Snapshot offers more than 400 available strategies, ranging from simple token-based methods to complex ones involving multiple conditions. Anyone can create custom strategies to precisely meet their governance needs. You can combine up to 8 strategies to calculate cumulative voting power, or up to 10 strategies for [Snapshot Pro](/user-guides/spaces/pro) spaces. Strategies are defined in the space settings in the [voting strategies](/user-guides/spaces/settings#voting-strategies) section. The default strategy is `erc20-balance-of`, which calculates the balance of a predefined ERC-20 token for each user. ### Most common voting strategies * **ERC-20 balance** (`erc20-balance-of`): Voting power is based on participants' ERC-20 token holdings. * **ERC-721 NFT balance** (`erc721`): Uses ownership of ERC-721 NFTs as voting power. * **ERC-1155 NFT balance** (`erc1155-balance-of`): Similar to ERC-721 but designed for ERC-1155 NFTs. * **ERC-20 Votes** (`erc20-votes`): Voting power is determined by delegated ERC-20 token balances. * **Whitelist** (`whitelist`): Grants a fixed voting power (usually 1 vote) to specific wallet addresses, regardless of onchain token holdings. ### Other popular strategies * **Contract call** (`contract-call`): Uses the result of a custom contract call as voting power. * **Delegation** (`delegation`): Allows delegation of voting power based on existing strategies. * **Balance with minimum** (`balance-of-with-min`): Assigns 1 voting power to participants holding at least a specified amount of a certain token. * **API** (`api`): Retrieves voting power from an external offchain API. * **Whitelist weighted** (`whitelist-weighted`): Assigns custom voting power values to specified addresses. * **ETH balance** (`eth-balance`): Uses ETH holdings (or the equivalent gas token on other networks) as voting power. * **Ticket** (`ticket`): Gives 1 voting power per participant, used exclusively in combination with a voting validation strategy. To learn more about creating custom voting strategies, head to the [developer guide](/developer-guides/voting-strategy). ## How to set up a strategy? Majority of spaces on Snapshot is using a single strategy however if you need a more complex calculation, you can combine up to 8 strategies. They will be applied to all proposals created for your space (created *after* the update of the settings) and the voting power will be calculated cumulatively. **Multiple voting strategies** If you combine several voting strategies the voting power will be calculated in the following way:\ *Total voting power = voting power from strategy A + voting power from strategy B + ...* In order to set up a voting strategy head to your space settings and scroll down to **Strategies** section. You should see the below pop-up after clicking **Add strategy** and selecting a strategy from the list: Example of setting up an erc20-balance-of strategy. You will see that there is information that you need to provide in order to make the strategy work, for example the **network** where the token is deployed, its **symbol** and **address** of the token's contract. Each strategy will require a different setup and you can read the full description and see the required parameters in the strategy's page, for example [erc20-balance-of](https://snapshot.box/#/strategy/erc20-balance-of). You can find each strategy's details through using the search bar and **Strategies** filter. ## Testing a voting strategy Before you add the strategy to your space's settings we highly recommend to test it in the **Playground** in order to avoid any potential issues with the voting process. If you made a mistake in your space settings and votes have already been cast **it is not possible to revert them.** The best solution would be to (1) delete the proposal, (2) update the settings with correct strategies and (3) recreate the proposal from scratch after the settings have been updated. You can access it from the strategy's detail page by clicking the **Playground** on the right-hand side: Your browser will load a Playground page where you can test the custom setup for the chosen strategy. As you can see on the below screenshot you can set the required parameters and provide a list of addresses which in this case are or are not holding a the `PUNK` ERC721 token. If everything is set up correctly you should see the calculated voting power for each address after clicking the play button: # Development service Source: https://docs.snapshot.box/user-guides/voting-strategies-development-service Need a custom voting strategy for your Snapshot space but don't have the technical expertise or time to build it yourself? Our voting strategies development service provides professional strategy development tailored to your specific needs. ## Service tiers ### Simple strategy (\$600) * **Development time:** 1 to 2 days * **Includes:** Basic voting logic implementation * **Best for:** Standard token-based voting, whitelisting, weighted voting, or combining existing strategies * **Examples:** ERC-20 balance checks, NFT ownership verification, simple mathematical calculations ### Advanced strategy (\$1,800) * **Development time:** 2 to 4 days * **Includes:** Advanced voting logic, deployment and maintenance of subgraphs or APIs * **Best for:** Cross-chain voting, complex calculations, custom data sources, or strategies requiring external infrastructure * **Examples:** Multi-chain token aggregation, DeFi protocol integrations, custom API endpoints, subgraph deployments **Special offer:** When you subscribe to [Snapshot Pro](/user-guides/spaces/pro) for 1 year, we'll include the development of a simple strategy at no additional cost. After subscribing, contact us on Telegram or through the [Help Center](/faq/support-and-feedback) to claim this offer. ## How we work 1. **Contact us:** Reach out via Telegram or through the [Help Center](/faq/support-and-feedback) messenger 2. **Consultation:** We discuss your requirements to determine whether a simple or advanced strategy fits best 3. **Development:** Our team builds and tests your custom strategy 4. **Deployment:** We deploy the strategy to Snapshot Score API 5. **Support:** Ongoing support for any questions or issues ## Build it yourself Prefer to create your own strategy? Check out our [developer guide](/developer-guides/voting-strategy). # Vote on a proposal Source: https://docs.snapshot.box/user-guides/voting/vote Learn how you can submit your vote on a proposal and how your voting power is calculated. ## Who can vote on proposals? Eligibility to vote is determined by the voting strategies specified in the space settings, generally requiring users to have a sufficient amount of tokens in their wallet at the time of proposal creation. ### Voting strategies Each space specifies their [voting strategies](/user-guides/voting-strategies) in the [space settings](/user-guides/spaces/settings#voting-strategies). This setup defines whether you are eligible to take part in voting and what your voting power is, calculated at the [snapshot of proposal creation](/user-guides/create#snapshot-block-number). In most cases you will be required to hold a sufficient amount of the specified token at the time of proposal creation. If you can't vote, it's likely because you did not hold the required tokens when the proposal was created. ### Voting validation Another aspect determining whether you are eligible to vote or not is a [voting validation](/user-guides/validation-strategies) defined by the space. It is a mechanism used to define certain conditions like minimum token balance or also to prevent [Sybil Attacks](https://en.wikipedia.org/wiki/Sybil_attack). In other words the space owner wants to make sure that you are human and that bot or fake accounts are not used to overrule the outcome of the voting. ## Cast a vote 1. Click the `Connect wallet` button in the top right corner. 2. Connect with the wallet provider where you hold the tokens relevant for the space you want to vote in. 3. Go to the space page on Snapshot and selected the active proposal you are interested in. 4. Select the option(s) you want to vote for. The [voting systems](/proposals/voting-types) can differ between individual proposals. 5. Click to `Vote` button and sign the message via your wallet provider when prompted. 6. You have successfully cast your vote. If you are using MetaMask you'll need to scroll to the end of the signature and click on the arrow down for the Sign button to become active. Voting on Snapshot doesn't affect your account or the funds that are associated to it. # SafeSnap Source: https://docs.snapshot.box/v1-interface/plugins/safesnap-reality SafeSnap enables trustless execution for your Snapshot governance on a Safe treasury using [Reality.eth](https://reality.eth.limo/) oracle. ## How does it work? SafeSnap plugin is an oracle based solution which works together with Safe and Snapshot in the following way: * A Safe module, where anyone can create a new proposal: an array of multisend transaction payloads. * Each proposal is a `Reality.eth` question asking if (1) the linked Snapshot proposal passed, (2) did the proposal include the payload, and (3) does the payload do what the proposal describes. * If the proposal passes on Snapshot, then `Reality.eth` should resolve to the same outcome, and after a 24 hour cooldown period, the proposal’s transactions are executable by anyone. * Reality uses an ERC-20 token (a given DAO’s governance token) for the bond. The minimum bond can be set by way of a proposal to the DAO. * The UI is a Snapshot plugin, in which users can enter an array of tx-payloads to be executed sequentially by the Safe if the proposal passes. Once the proposal has passed, the Reality.eth question has resolved, and the 24 hour cooldown period is over, there is the option on the Snapshot interface to trigger each of the multisend transactions in the proposal. ## Setup Follow the official Zodiac guide on how to setup a SafeSnap for your project. **Non-dev operators** (space controller or admin): [Kleros Reality Module setup guide](https://docs.kleros.io/integrations/types-of-integrations/1.-dispute-resolution-integration-plan/channel-partners/kleros-reality-module) **Developers**: [Zodiac Reality Module setup guide](https://github.com/gnosis/zodiac-module-reality/blob/main/docs/setup_guide.md) ## Security recommendations In order to ensure maximal safety we recommend to define several paremeters for your setup: * Set a **substantial bond** for an answer * Select an **arbitrator** * Select a **long cooldown** * Set up a **monitoring infrastructure** for questions ## Additional resources Learn more about SafeSnap: [Introducing SafeSnap](https://blog.gnosis.pm/introducing-safesnap-the-first-in-a-decentralized-governance-tool-suite-for-the-gnosis-safe-ea67eb95c34f)