Votar Sin Costos: Cómo Hice que Participar en Decisiones Grupales Sea Gratis para Todos

"Solidity + EIP-712 + Next.js + ERC-2771: La combinación tecnológica que hizo posible un sistema de votación donde nadie paga comisiones de gas."

En el mundo de las organizaciones, donde la participación en decisiones grupales muchas veces enfrenta barreras de costo y complejidad, esta solución demuestra cómo la tecnología Web3 puede democratizar la gobernanção empresarial — permitiendo que cualquier persona participe sin necesitar criptomonedas.


DAO Web3 Screenshot

Subtítulo técnico: Meta-transacciones con EIP-712, ERC-2771 y patrón Relayer para gobernanza sin gas


🎯 Las DAOs Democráticas No Deberían Requerir Cripto para Votar

La paradoja: Una DAO dice ser descentralizada y democrática, pero solo los miembros que tienen ETH para pagar gas pueden participar en las decisiones. ¿De qué sirve la descentralización si el 80% de los holders de tokens no pueden votar porque no saben cómo comprar Ethereum?


📊 El Problema de Participación que Enfrenta Cada Organización

En las DAOs tradicionales, la participación en la gobernanza sufre de una barrera fundamental: las comisiones de gas.

Barrera Impacto en la Participación
Necesita comprar ETH Los usuarios fuera del mundo cripto no pueden participar en absoluto
Volatilidad del gas En períodos ocupados, votar puede costar $50-$200
Complejidad de wallets Conectar MetaMask y aprobar transacciones confunde a los usuarios
Fatiga de transacciones Cada voto requiere una transacción on-chain separada

El resultado? La mayoría de las DAOs tienen tasas de participación del 2-5%. La gran mayoría de los holders de tokens permanecen en silencio porque la fricción es demasiado alta.

flowchart TD
    A[Miembro de la DAO] --> B{¿Tiene ETH para gas?}
    B -- No --> C[No Puede Votar]
    B -- Sí --> D{¿Quiere comprar ETH?}
    D -- No --> C
    D -- Sí --> E[Puede Votar - Pero Alta Fricción]
    
    style C fill:#ffcccc,stroke:#ff0000
    style E fill:#fff3e0,stroke:#ffa000

Esto no es solo un problema de UX — es un defecto fundamental en el diseño de gobernanza. La verdadera gobernanza requiere participación, y la participación requiere accesibilidad.


💡 La Solución: UX Web2 con Seguridad Web3

La idea clave: separar quién firma el voto de quién paga la comisión de blockchain.

sequenceDiagram
    participant U as 👤 Usuario (Sin ETH necesario)
    participant W as 💼 Wallet
    participant R as ⚡ Relayer API
    participant C as 📋 Contrato DAO
    
    U->>W: Firma voto EIP-712 (gratis, sin gas)
    W-->>U: Retorna Firma
    U->>R: POST /api/relay {firma}
    R->>C: executeMetaTx(firma)
    C-->>R: Voto registrado on-chain
    R-->>U: 200 OK {txHash}
    
    note over U,C: El usuario nunca paga gas. El Relayer sí.

Cómo Funciona — En Lenguaje Simple

  1. El usuario firma su voto — como hacer click en "Me gusta" en redes sociales, sin cripto
  2. Un servidor relays el voto — paga la comisión de gas en nombre del usuario
  3. El voto se registra on-chain — inmutable y verificable por cualquiera

El usuario obtiene simplicidad Web2 (click y vota). La blockchain obtiene seguridad Web3 (registros inmutables y verificables).


🛠️ Tecnologías Usadas

Capa Tecnología Propósito
Smart Contracts Solidity ^0.8.24, OpenZeppelin Lógica de gobernanza on-chain
Estándares EIP-712, ERC-2771 Firmas estructuradas + meta-transacciones
Frontend Next.js 15+, TypeScript, React 19 Interfaz de usuario
Web3 Wagmi v2, Viem Hooks type-safe para interacción EVM
Backend Next.js API Routes Relayer que paga el gas
Testing Foundry, Anvil Tests unitarios y despliegue local
Estilos Tailwind CSS, Headless UI Interfaz accesible y responsive

🔧 Implementación: La Arquitectura Técnica

El Stack de Meta-Transacciones

Tecnología Propósito Por Qué Importa
EIP-712 Firmas de datos estructurados y tipados Los usuarios ven qué están firmando en formato legible
ERC-2771 Estándar para contratos de meta-transacciones Extrae el msg.sender real del calldata
Relayer Ruta API de Next.js que paga gas Conecta la intención del usuario con la ejecución on-chain

Ejemplo: Estructura EIP-712 para Votos

El frontend define la estructura del voto que el usuario firmará:

// EIP-712 domain y tipo para el voto const DOMAIN = { name: 'GovernanceDAO', version: '1', chainId: 1, verifyingContract: '0x1234...5678', } as const; const VOTE_TYPE = { Vote: [ { name: 'proposalId', type: 'uint256' }, { name: 'support', type: 'bool' }, // true = FOR, false = AGAINST { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' }, ], } as const;

Ejemplo: Generación de Firma en TypeScript

El frontend genera la firma criptográfica que el usuario firmará con su wallet:

import { encodeAbiParameters, parseAbiParameters } from 'viem'; import { getSignedTypeData } from './eip712'; async function signVote( walletClient: WalletClient, userAddress: Address, proposalId: bigint, support: boolean, nonce: bigint, deadline: bigint ): Promise<Signature> { // Construir el tipo EIP-712 para el voto const typeData = { types: { Vote: [ { name: 'proposalId', type: 'uint256' }, { name: 'support', type: 'bool' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' }, ], }, primaryType: 'Vote', domain: { name: 'GovernanceDAO', version: '1', chainId: 1, verifyingContract: '0x1234...5678', }, message: { proposalId, support, nonce, deadline, }, }; // Firmar con la wallet del usuario (MetaMask muestra datos legibles) const signature = await walletClient.signTypedData(typeData); return signature; }

Smart Contracts (Solidity ^0.8.24)

El sistema tiene tres contratos principales trabajando juntos:

graph TB
    subgraph Smart Contracts
        GT[GovernanceToken&lt;br/&gt;ERC-20 + Delegación]
        GD[GovernorDAO&lt;br/&gt;Propuestas y Votos]
        FW[Forwarder&lt;br/&gt;ERC-2771]
    end
    
    subgraph Frontend
        N[Next.js 15&lt;br/&gt;Wagmi + Viem]
    end
    
    subgraph Backend
        R[Relayer API&lt;br/&gt;Meta-transacciones]
    end
    
    N --&gt;|Lectura| GT
    N --&gt;|Lectura| GD
    N --&gt;|Firma EIP-712| R
    R --&gt;|executeMetaTx| FW
    FW --&gt;|Verifica| GD
    GD --&gt;|Verifica balance| GT
    
    style GT fill:#1a1a2e,stroke:#00f2ff,stroke-width:2px,color:#fff
    style GD fill:#1a1a2e,stroke:#00ff88,stroke-width:2px,color:#fff
    style FW fill:#1a1a2e,stroke:#ff00f2,stroke-width:2px,color:#fff
  1. GovernanceToken.sol — ERC-20 con delegación de votos. Los holders pueden delegar su poder de votación a otros.
  2. GovernorDAO.sol — Creación de propuestas, ciclo de vida de votación y ejecución.
  3. Forwarder.sol — Implementación ERC-2771 que verifica y retransmite meta-transacciones.

Ciclo de Vida de una Propuesta

stateDiagram-v2
    [*] --&gt; Pendiente: Creación (≥10% tokens)
    Pendiente --&gt; Activa: Comienza votación
    Activa --&gt; Exitosa: Mayoría a favor
    Activa --&gt; Derrotada: Mayoría en contra
    Exitosa --&gt; Ejecutada: Ejecución on-chain
    Derrotada --&gt; [*]
    Ejecutada --&gt; [*]

Requisito de propuestas: Solo las cuentas con ≥ 10% de los tokens totales pueden crear propuestas. Esto previene spam de gobernanza.

Frontend (Next.js 15 + TypeScript)

El frontend en packages/web/src/ usa:

  • Wagmi + Viem: Hooks type-safe para interacción EVM
  • TanStack Query: Caché de estado blockchain con auto-revalidación
  • Tailwind CSS + Headless UI: Interfaz accesible y responsive
  • Dashboard en tiempo real: Estado de propuestas y conteo de votos en vivo

🧠 Profundizando: La Magia del ERC-2771

Extrayendo el Remitente Real

La parte más compleja: el contrato debe saber quién votó realmente, no quién pagó el gas.

// El contrato extrae el remitente real del calldata function _msgSender() internal view override returns (address sender) { if (isTrustedForwarder(msg.sender)) { // El remitente real está en los últimos 20 bytes del calldata assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } } else { return super._msgSender(); } }

Este patrón en Forwarder.sol es la pieza crítica — permite al contrato distinguir entre una llamada directa y una meta-transacción retransmitida.

Ejemplo: Relayer API (Next.js)

El Relayer es una ruta API que recibe la firma del usuario y la ejecuta on-chain:

// packages/web/src/app/api/relay/route.ts import { NextRequest, NextResponse } from 'next/server'; import { ethers } from 'ethers'; import { GOVERNOR_ADDRESS, FORWARDER_ADDRESS } from '@/config'; export async function POST(req: NextRequest) { const { signature, voteData } = await req.json(); // 1. Verificar que la firma es válida antes de enviar a blockchain const domain = { name: 'GovernanceDAO', version: '1', chainId: Number(process.env.CHAIN_ID), verifyingContract: GOVERNOR_ADDRESS, }; const types = { Vote: [ { name: 'proposalId', type: 'uint256' }, { name: 'support', type: 'bool' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' }, ], }; // Recuperar la dirección del firmante const signer = await ethers.verifyTypedData(domain, types, voteData, signature); // 2. Verificar que el usuario tiene tokens de gobernanza const hasVotes = await checkVotingPower(signer, voteData.proposalId); if (!hasVotes) { return NextResponse.json({ error: 'No voting power' }, { status: 403 }); } // 3. Construir y enviar la transacción on-chain (pagando gas) const contract = new ethers.Contract(FORWARDER_ADDRESS, FORWARDER_ABI, provider); const tx = await contract.executeMetaTx(voteData, signature); await tx.wait(); return NextResponse.json({ txHash: tx.hash }); }

Por Qué EIP-712 Importa para la UX

Cuando los usuarios firman con EIP-712, MetaMask muestra datos estructurados legibles en lugar de strings hex:

Votar Propuesta #3 ───────────────── Propuesta: Actualizar asignación de tesorería Voto: A FAVOR Nonce: 42 Dominio: GovernanceDAO v1 Cadena: 1

Esto previene phishing y asegura que los usuarios entiendan qué están firmando.


📊 Comparación: Tradicional vs Blockchain

Aspecto Tradicional (Burocrático) Blockchain Gasless
Costo por voto Infinito (burocracia, papel, tiempo) $0 (usuario no paga gas)
Participación potencial 5-15% (limitado por logística) 30-50% (accesible para todos)
Barra de entrada Physical presence or mail Solo conectar wallet
Inmutabilidad Registros pueden alterarse Inmutable en blockchain
Verificación Depende de auditoría humana Cualquiera puede verificar on-chain
Tiempo de votación Días o semanas Minutos (confirmación)
Transparencia Parcial (resultados reportados) Total (todos los votos visibles)
Accesibilidad global Limitada por zona geográfica Global, 24/7

📈 Impacto: Qué Habilita la Votación Sin Costos

Métrica DAO Tradicional DAO Gasless
Tasa de participación 2-5% Potencialmente 30-50%
Barra de entrada Debe comprar ETH, aprender wallets Solo conectar wallet
Costo por voto $0.50 - $50+ $0 (usuario no paga nada)
Usuarios fuera de cripto No pueden participar Pueden participar

🤔 Por Qué Esto Importa Más Allá de las DAOs

El patrón de meta-transacciones se aplica a cualquier sistema descentralizado que necesite participación de usuarios:

  • Votación DeFi en upgrades de protocolo — hacerlo accesible a holders que no son traders
  • Gobernanza de comunidades NFT — permitir que holders voten sin requerir ETH
  • Plataformas sociales descentralizadas — habilitar votos de moderación de contenido sin barreras de gas
  • Aplicaciones con tokens-gated — control de acceso sin fricción de transacciones

✅ Lecciones Aprendidas

  1. Las meta-transacciones son poderosas pero complejas — implementar correctamente la verificación ERC-2771 fue el mayor desafío técnico
  2. EIP-712 transforma la UX — mostrar datos estructurados en lugar de hex mejora dramáticamente la confianza del usuario
  3. El Relayer es una suposición de confianza — el relayer podría censurar votos; iteraciones futuras deberían soportar múltiples relayers


🔗 Explorar el Código

Código fuente completo: github.com/87maxi/dao

Archivos clave:

Probalo: Cloná el repo, ejecutá anvil localmente, y desplegá los contratos. Conectá tu wallet, delegá tokens, y emití un voto sin gas — vas a firmar con EIP-712 y el relayer local se encarga del resto.


📊 Métricas de Gasless Governance

Operación Costo con Gas (ETH) Costo Gasless Ahorro
Firmar propuesta ~$3 - $15 $0 100%
Votar en propuesta ~$2 - $10 $0 100%
Crear propuesta (con deposit) ~$5 - $25 $0 100%
Ejecutar propuesta aprobada ~$8 - $40 (relayer) ~$0.01 99.9%

Nota: Los costos de gas varían según la congestión de la red. Los valores son aproximados para Polygon/Ethereum L2.


🔗 Recursos y Aprendizaje Continuo

Para profundizar en los patrones de gobernanza descentralizada y meta-transacciones:


💬 ¿Quieres Contribuir?

¿Tienes experiencia en gobernanza descentralizada o has implementado sistemas de voting on-chain? Me encantaría escuchar tus ideas o colaborar en mejoras.

🐛 ¿Encontraste un bug? Abre un issue en github.com/87maxi/dao/issues 💡 ¿Tienes una mejora para el relayer? Abre un pull request 📝 ¿Quieres escribir sobre DAOs? Comparte tu artículo y lo incluiré en los enlaces relacionados


Enlaces Relacionados


Proyecto del Master en Blockchain y Web3 — CodeCrypto Academy

💬

Comentarios

Powered by Giscus · GitHub Discussions

🧠 Web3 & Blockchain