Gnosis Safe pattern, propuestas on-chain y votaciones con tokens de gobernanza
// Gnosis Safe: MultiSigWallet.sol (simplificado) contract MultiSigWallet { address[] public owners; // [Alice,Bob,Carol,Dave,Eve] uint256 public required = 3; // threshold struct Transaction { address to; uint256 value; bytes data; bool executed; uint256 confirmations; } mapping(uint256 => mapping(address => bool)) public isConfirmed; function confirmTransaction(uint256 txId) external { require(isOwner[msg.sender]); isConfirmed[txId][msg.sender] = true; tx.confirmations++; if (tx.confirmations >= required) execute(txId); } }
// MyGovernor.sol ” basado en OpenZeppelin Governor import "@openzeppelin/contracts/governance/Governor.sol"; import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol"; import "@openzeppelin/contracts/governance/TimelockController.sol"; contract MyGovernor is Governor, GovernorVotes, GovernorTimelockControl { constructor(IVotes _token, TimelockController _timelock) Governor("MyGovernor") GovernorVotes(_token) GovernorTimelockControl(_timelock) {} function votingDelay() public pure override returns (uint256) { return 1; // 1 bloque para abrir votación } function votingPeriod() public pure override returns (uint256) { return 45818; // ~1 semana en bloques } function quorum(uint256) public pure override returns (uint256) { return 1e18; // 1 token = quórum mínimo } } // Proponer: uint256 propId = governor.propose( [tokenAddress], // targets [0], // values [transferCalldata], // calldatas "Transfer 500k DAI to grants" ); // Votar (después de votingDelay): governor.castVoteWithReason(propId, 1, "Apoyo el programa"); // 1=For // Si pasa ’ queue en Timelock ’ execute después de delay (48h)