Lição: 243: Votação Snapshot
A votação snapshot é um mecanismo utilizado na governança descentralizada, permitindo que os detentores de tokens votem em propostas com base em uma captura (snapshot) da posse de tokens em um bloco específico. Essa abordagem garante que o poder de voto reflita o estado das posses de tokens em um determinado momento, prevenindo manipulações que podem ocorrer ao comprar ou vender tokens imediatamente antes de uma votação.
Nesta aula, vamos abordar os fundamentos da votação snapshot e fornecer uma implementação simples em Solidity.
O que é Votação Snapshot?
A votação snapshot permite que decisões de governança sejam tomadas com base em uma captura fixa dos saldos de tokens em um bloco específico. Esse método oferece um grau de certeza e justiça, uma vez que impede que mudanças de última hora na distribuição de tokens afetem o resultado da votação.
Componentes Chave da Votação Snapshot
- Token de Voto: O token ERC20 que representa o poder de votação.
- Mecanismo de Captura: Uma forma de registrar os saldos dos detentores de tokens em um bloco específico.
- Estrutura da Proposta: Uma forma de definir o que está sendo votado, incluindo detalhes como propostas, opções e prazos de votação.
- Lógica de Votação: A implementação que permite que os usuários realizem seus votos com base na captura.
Exemplo de Implementação
Abaixo está uma implementação simples de votação snapshot em Solidity. Este exemplo cria um contrato de governança onde propostas podem ser submetidas e votadas pelos detentores de tokens.
Contrato de Governança Simples
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract Governance {
using Counters for Counters.Counter;
IERC20 public token;
Counters.Counter public proposalIdCounter;
struct Proposal {
uint256 id;
string description;
uint256 voteCount;
uint256 snapshotBlock;
mapping(address => bool) hasVoted;
}
mapping(uint256 => Proposal) public proposals;
event ProposalCreated(uint256 id, string description, uint256 snapshotBlock);
event Voted(uint256 proposalId, address voter, uint256 votes);
constructor(IERC20 _token) {
token = _token;
}
function createProposal(string memory description) external returns (uint256) {
proposalIdCounter.increment();
uint256 proposalId = proposalIdCounter.current();
uint256 snapshotBlock = block.number;
Proposal storage newProposal = proposals[proposalId];
newProposal.id = proposalId;
newProposal.description = description;
newProposal.snapshotBlock = snapshotBlock;
emit ProposalCreated(proposalId, description, snapshotBlock);
return proposalId;
}
function vote(uint256 proposalId) external {
Proposal storage proposal = proposals[proposalId];
require(block.number > proposal.snapshotBlock, "Votação ainda não está aberta");
require(!proposal.hasVoted[msg.sender], "Você já votou");
uint256 votes = token.balanceOf(msg.sender);
require(votes > 0, "Você não tem poder de voto");
proposal.voteCount += votes;
proposal.hasVoted[msg.sender] = true;
emit Voted(proposalId, msg.sender, votes);
}
function getProposal(uint256 proposalId) external view returns (string memory description, uint256 voteCount, uint256 snapshotBlock) {
Proposal storage proposal = proposals[proposalId];
return (proposal.description, proposal.voteCount, proposal.snapshotBlock);
}
}
Principais Funcionalidades do Contrato
- Criação de Propostas: Os usuários podem criar propostas que capturam os saldos de tokens no bloco em que a proposta é criada.
- Votação: Os detentores de tokens podem votar em propostas com base em seu saldo de tokens no bloco de captura. Cada endereço pode votar uma vez por proposta.
- Eventos: Eventos são emitidos para a criação de propostas e votações, permitindo que interfaces fora da cadeia (off-chain) acompanhem as ações.
Uso
- Desplegue o contrato
Governance
com um endereço de contrato ERC20. - Chame
createProposal()
para criar uma nova proposta. - Chame
vote()
com o ID da proposta para votar com base nos saldos de tokens da captura.
Conclusão
A votação snapshot é uma maneira robusta e justa de habilitar a governança descentralizada em um ambiente de blockchain. Ao usar um mecanismo de captura, garante que o poder de voto se baseie nas posses de tokens em um momento específico, protegendo contra ataques de empréstimos relâmpagos (flash loan) e outras formas de exploração. A implementação em Solidity fornecida demonstra uma abordagem simples para criar e votar em propostas. Sinta-se à vontade para expandir este exemplo adicionando recursos como expiração de propostas, várias opções de votação ou mecanismos avançados de contagem!