Visão Geral
O Block-Sena é uma loteria on-chain em que as compras de bilhetes, bloqueio da rodada, sorteio e distribuição de prêmios são registrados na blockchain. O protocolo usa um fluxo em duas fases: blockSenaPauseDraw (trava a rodada e registra o compromisso) e blockSenaDrawPay (revela, sorteia e paga).
Objetivo
Garantir um processo auditável, reproduzível e com regras de payout transparentes para cada rodada.
Auditabilidade
Qualquer pessoa pode verificar inputs (commit, salt, bloco alvo), cálculo do seed, números sorteados e eventos de liquidação.
Commit-Reveal (2 Fases)
A função blockSenaPauseDraw(usdValuePoolSnapshot, commitHash) bloqueia a rodada para novas compras, define o bloco alvo futuro e armazena apenas o hash do salt secreto.
A função blockSenaDrawPay(salt) valida que keccak256(salt) == commitHash, usa o blockhash do bloco alvo, gera os 6 números únicos e executa os payouts.
O blockhash só pode ser lido por ~256 blocos. Se expirar, a rodada precisa de reset operacional. Esse reset é um fail-safe raro, com timeout on-chain, e todo uso fica público on-chain.
Compromisso do Salt
Bloco Alvo
Fluxo do Sorteio (21h UTC -> +5 blocos -> DrawPay)
O fluxo operacional do Block-Sena separa claramente o encerramento das apostas da geração dos 6 números. Essa separação elimina o risco de comprar bilhetes depois de conhecer o resultado ou tentar ajustar bilhetes para "bater" com os números sorteados.
A função blockSenaPauseDraw(usdValuePoolSnapshot, commitHash) trava a rodada, bloqueia novas compras, registra o commitHash, define targetBlock = block.number + 5 e salva o snapshot do pool em USD.
Depois do PauseDraw, nenhum novo bilhete entra naquela rodada. Nesse momento, o blockhash(targetBlock) ainda não existe, então os 6 números finais ainda não podem ser previstos nem calculados.
A função blockSenaDrawPay(salt) valida o salt contra o commit, lê o blockhash do bloco alvo, gera os 6 números únicos e executa os payouts por token. Se tentar chamar antes do bloco alvo, a transação reverte on-chain.
Qualquer pessoa pode verificar no explorer: tx de blockSenaPauseDraw, targetBlock, tx de blockSenaDrawPay, salt revelado, números sorteados e eventos de liquidação/pagamento.
Não é possível comprar um bilhete depois de ver os 6 números da rodada, porque a rodada já foi travada em blockSenaPauseDraw antes do sorteio ser executado.
Não é possível conhecer os 6 números no momento da pausa, porque a fórmula depende de um bloco futuro (targetBlock) que ainda não existe naquele momento.
Não é possível executar o sorteio antes da hora técnica, porque blockSenaDrawPay exige on-chain que o bloco atual já tenha passado do targetBlock.
O blockSenaResetDraw existe apenas para evitar que uma rodada fique travada para sempre se ocorrer uma falha longa de infraestrutura (ex.: RPCs indisponíveis, manutenção de serviços, outage de rede/infra ou problemas operacionais prolongados) e o DrawPay não puder ser executado antes da expiração do blockhash(targetBlock).
No fluxo normal, o esperado é executar o DrawPay poucos blocos após o PauseDraw (alvo em +5 blocos). O reset é uma proteção de liveness, não parte do fluxo normal de sorteio.
Fórmula Matemática do Sorteio (6 números únicos)
O seed do sorteio é derivado da combinação de um bloco futuro, do salt comprometido e de dados da rodada. A partir dele, o contrato gera números de 1 a 30, descartando duplicados até completar 6 dezenas únicas.
Em termos de segurança operacional: como os bilhetes já foram congelados na fase de PauseDraw antes desse bloco futuro existir, o sorteio não pode ser "montado" para casar com um bilhete inserido depois, e nenhum participante consegue apostar na mesma rodada após conhecer o resultado.
Seed do Sorteio
Geração de Cada Número
Esse procedimento impede números repetidos no resultado final e mantém o sorteio dentro do intervalo válido 1..30.
Aposta Múltipla (6 a 10 números) e Quotas Combinatórias
No Block-Sena, um bilhete pode conter de 6 até 10 números. Esse bilhete representa várias combinações equivalentes de 6 números. O cálculo de prêmios é feito por quotas vencedoras (combinações), não apenas por “pessoas”.
Total de Combinações de um Bilhete com k números
Quotas vencedoras por faixa (4/5/6)
Considere um bilhete com k números e x acertos dentro das 6 dezenas sorteadas.
Exemplo (bilhete com 10 números e os 6 sorteados dentro dos 10)
q6 = 1, q5 = 24, q4 = 90. O mesmo bilhete pode ganhar simultaneamente nas 3 faixas.
Payout Multi-Token (Liquidação por Token)
Cada token do pool (ex.: nativo, USDC, USDT) é liquidado independentemente. O contrato calcula vencedores e prêmios por rodada e por token, mantendo um histórico exato em RoundTokenStats.
Divisão por Faixa
Prêmio por quota vencedora
Se não houver vencedores
O valor daquela faixa não é perdido: ele compõe o acumulado (carry-over) do token para a próxima rodada.
Se houver múltiplos vencedores
O prêmio é dividido por quotas vencedoras. Uma mesma carteira pode receber várias quotas agregadas em um único pagamento por token.
Como Auditar uma Rodada (Passo a Passo)
- Localize a tx de blockSenaPauseDraw e anote o commitHash e o targetBlock.
- Após o alvo, localize a tx de blockSenaDrawPay e leia o salt enviado.
- Recalcule keccak256(salt) e confirme que bate com o commitHash.
- Leia o blockhash(targetBlock) no explorer e o prevrandao do bloco da tx de draw.
- Reproduza o seed e a rotina de geração dos 6 números (descartando duplicados) e compare com o evento DrawExecuted.
- Se houve falha operacional rara, confira o evento DrawReset (roundId, targetBlock e bloco do reset) para validar o timeout e a rastreabilidade do reset.
- Verifique os eventos RoundTokenSettled para pools, pagamentos por faixa e carry-over por token.
- Confira transfers nativos/ERC20 para validar os pagamentos aos vencedores.
Garantias, Transparência e Limites Operacionais
O Block-Sena foi desenhado para que o resultado de uma rodada seja auditável, reproduzível e transparente. O commit-reveal combinado com bloco futuro reduz significativamente a possibilidade de manipulação manual do resultado.
Em termos técnicos, o modelo torna o resultado imprevisível no momento do lock, porque a rodada é encerrada antes de existir o blockhash(targetBlock) usado no seed. Assim, a fórmula permanece pública e auditável sem permitir apostas posteriores baseadas no resultado.
O que é garantido on-chain
Regras de sorteio, cálculo de quotas, payout por faixa (80/15/5), histórico por token, eventos e rastreabilidade de cada etapa.
Operação emergencial
Existe função de reset de draw para cenários técnicos raros (ex.: expiração de blockhash por falha prolongada de infra/rede). Ela só pode ser executada com a rodada travada e após timeout on-chain. Todo uso é público, fica registrado on-chain e pode ser auditado no explorer.
O reset não move fundos, não apaga bilhetes e não altera o pool. Ele apenas destrava o ciclo da rodada para permitir uma nova tentativa de sorteio da mesma rodada em caso de falha rara.
Os valores do prêmio permanecem no contrato até o sorteio e os pagamentos automáticos aos vencedores. Se não houver vencedores em uma faixa, o valor permanece contabilizado como acumulado (carry-over) para a próxima rodada. O owner não tem função para retirar fundos contabilizados do pool de prêmios.
A função rescueAll existe apenas para resgatar excedentes não contabilizados (ex.: envio direto por engano), calculando saldo real - pool contabilizado. Ela não alcança os fundos do prêmio já contabilizados.
Em outras palavras: o Block-Sena não pede confiança cega. Ele entrega um fluxo que pode ser acompanhado, reproduzido matematicamente e conferido on-chain por qualquer pessoa, a qualquer momento.