Lição 239: Leilões em Licitações Fechadas
Os leilões em licitações fechadas são um tipo de leilão onde todos os licitantes apresentam suas propostas de forma privada, sem conhecer as ofertas de outros participantes. A maior oferta é a vencedora, mas o valor da oferta vencedora pode ser estratégico, uma vez que os licitantes não conseguem ver as propostas dos demais. Esse método é frequentemente utilizado em diversos cenários, incluindo imóveis e contratos governamentais.
Nesta lição, vamos criar uma implementação simples de um leilão em licitações fechadas usando Solidity, a linguagem de programação para contratos inteligentes no Ethereum. Vamos explorar como configurar o leilão, enviar as propostas e declarar o vencedor.
Conceitos Chave
- Licitantes Fechados: Os licitantes enviam suas propostas de forma privada.
- Critérios de Vitória: O licitante com a maior proposta vence.
- Gerenciamento das Licitações: Apenas o organizador do leilão pode revelar o vencedor.
Estrutura Básica do Contrato Inteligente
Vamos esboçar nosso contrato de leilão em licitações fechadas. O contrato precisará das seguintes funcionalidades:
- Uma forma de iniciar e encerrar o leilão.
- Armazenamento para as propostas.
- Um método para os participantes submeterem suas propostas de forma segura.
- Uma função para revelar a proposta vencedora.
Implementação do Código
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract LeilaoLicitacaoFechada {
struct Proposta {
uint256 valor;
bytes32 hashSecreto;
address licitante;
bool revelada;
}
address public organizador;
uint256 public tempoFinal;
bool public leilaoFinalizado;
mapping(address => Proposta) public propostas;
address public maiorLicitante;
uint256 public maiorProposta;
event PropostaFeita(address indexed licitante, uint256 valor);
event LeilaoFinalizado(address vencedor, uint256 valor);
modifier apenasOrganizador() {
require(msg.sender == organizador, "Apenas o organizador pode chamar esta função.");
_;
}
modifier leilaoAtivo() {
require(block.timestamp < tempoFinal, "Leilão já foi finalizado.");
_;
}
modifier statusLeilaoFinalizado() {
require(leilaoFinalizado, "Leilão não foi finalizado ainda.");
_;
}
constructor(uint256 duracaoLeilao) {
organizador = msg.sender;
tempoFinal = block.timestamp + duracaoLeilao;
}
function fazerProposta(bytes32 secreto) external payable leilaoAtivo {
require(msg.value > maiorProposta, "A proposta deve ser maior que a proposta atual.");
require(propostas[msg.sender].valor == 0, "Você já fez uma proposta.");
propostas[msg.sender] = Proposta({
valor: msg.value,
hashSecreto: secreto,
licitante: msg.sender,
revelada: false
});
maiorProposta = msg.value;
maiorLicitante = msg.sender;
emit PropostaFeita(msg.sender, msg.value);
}
function revelarProposta(uint256 valor, string memory secreto) external statusLeilaoFinalizado {
Proposta storage proposta = propostas[msg.sender];
require(!proposta.revelada, "Proposta já revelada.");
require(proposta.hashSecreto == keccak256(abi.encodePacked(secreto)), "Segredo incorreto.");
require(valor == proposta.valor, "Valor revelado deve corresponder à proposta enviada.");
if (valor > maiorProposta) {
maiorProposta = valor;
maiorLicitante = msg.sender;
}
proposta.revelada = true;
}
function finalizarLeilao() external apenasOrganizador statusLeilaoFinalizado {
leilaoFinalizado = true;
emit LeilaoFinalizado(maiorLicitante, maiorProposta);
}
function retirar() external {
require(leilaoFinalizado, "Leilão não foi finalizado ainda.");
require(msg.sender != maiorLicitante, "Vencedor não pode retirar fundos.");
Proposta storage proposta = propostas[msg.sender];
require(proposta.revelada, "Você precisa revelar sua proposta primeiro.");
uint256 valor = proposta.valor;
proposta.valor = 0; // Prevenir re-entrada
payable(msg.sender).transfer(valor);
}
}
Explicação do Código
-
Estrutura da Proposta: Definimos uma estrutura
Proposta
com propriedades para armazenar o valor da proposta, o hash secreto, o endereço do licitante e uma flag para verificar se uma proposta foi revelada. -
Modificadores:
apenasOrganizador
: Garante que apenas o criador do contrato (organizador) possa chamar funções específicas.leilaoAtivo
: Verifica se o leilão ainda está em andamento.statusLeilaoFinalizado
: Garante que certas ações só possam ser realizadas após o leilão ter terminado.
-
Funções:
constructor
: Inicializa o leilão com uma duração especificada.fazerProposta
: Permite que os usuários enviem propostas enviando Ether e fornecendo um hash secreto de sua intenção de licitar. A maior proposta é atualizada conforme necessário.revelarProposta
: Após o leilão, esta função verifica a proposta em relação ao segredo e atualiza o maior licitante se necessário.finalizarLeilao
: Finaliza o leilão e emite o evento com os detalhes do vencedor.retirar
: Permite que licitantes não vencedores retirem seus fundos após revelarem suas propostas.
Conclusão
A implementação acima demonstra um leilão básico em licitações fechadas em Solidity. Ela encapsula a essência das licitações fechadas enquanto garante a integridade e segurança do contrato. Você pode ainda aprimorar as características de segurança, adicionar funcionalidades como extensão de leilão ou implementar propostas mínimas.
Em cenários do mundo real, sempre considere testar e auditar contratos inteligentes cuidadosamente antes de fazer o deploy. Os leilões em licitações fechadas podem ser aplicados em diversos domínios, e sua implementação segura pode levar a confiança e transparência nas transações. Boa codificação!