SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
05.12.2024

Lição: 238: Contratos de Leilão

Introdução

Nesta aula, iremos explorar como criar um contrato de leilão usando Solidity. Os leilões são uma forma popular de vender bens e serviços, e os contratos inteligentes nos permitem automatizar e garantir esse processo na blockchain Ethereum. Vamos implementar um contrato de leilão simples que permite aos participantes fazer lances e concluir o leilão.

Conceitos Chave

Antes de mergulharmos no código, vamos recapitular alguns conceitos fundamentais sobre leilões:

  1. Hora de Início: O leilão tem um horário de início definido.
  2. Hora de Término: O leilão possui um horário de término definido, após o qual não podem ser feitos lances.
  3. Lance Mínimo: Cada lance subsequente deve ser maior do que o maior lance atual.
  4. Lances: Os participantes podem fazer lances até que o leilão termine.
  5. Seleção do Vencedor: O maior pulador ao final do leilão é o vencedor.
  6. Retirada: Os licitantes não vencedores devem conseguir retirar seus lances.

Estrutura do Contrato

Nosso contrato de leilão consistirá nos seguintes componentes principais:

  1. Variáveis de estado para armazenar os parâmetros do leilão.
  2. Um mapeamento para rastrear os lances.
  3. Funções para iniciar o leilão, fazer lances e finalizar o leilão.

Implementação

Vamos quebrar a implementação passo a passo.

Passo 1: Definir o Contrato

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Leilao {
    address public leiloeiro;
    uint public horarioFimLeilao;
    uint public maiorLance;
    address public maiorLicitante;
    bool public encerrado;

    mapping(address => uint) public retornosPendentes;

    event NovoLance(address indexed licitante, uint valor);
    event LeilaoEncerrado(address vencedor, uint valor);

    constructor(uint _tempoDeLance) {
        leiloeiro = msg.sender;
        horarioFimLeilao = block.timestamp + _tempoDeLance;
    }
}

Passo 2: Fazer Lances

Agora, implementaremos uma função para fazer lances. A função verificará se o lance é válido com base no status atual do leilão.

function lance() public payable {
    require(block.timestamp < horarioFimLeilao, "O leilão já terminou.");
    require(msg.value > maiorLance, "O valor do lance não é alto o suficiente.");

    // Armazenar o maior lance anterior para retirada
    if (maiorLance != 0) {
        retornosPendentes[maiorLicitante] += maiorLance;
    }

    maiorLicitante = msg.sender;
    maiorLance = msg.value;

    emit NovoLance(msg.sender, msg.value);
}

Passo 3: Retiradas

Em seguida, vamos implementar uma função de retirada para os licitantes não vencedores.

function retirar() public returns (bool) {
    uint valor = retornosPendentes[msg.sender];
    if (valor > 0) {
        retornosPendentes[msg.sender] = 0;
        payable(msg.sender).transfer(valor);
        return true;
    }
    return false;
}

Passo 4: Encerrar o Leilão

Finalmente, implementaremos uma função para encerrar o leilão e declarar o vencedor.

function encerrarLeilao() public {
    require(msg.sender == leiloeiro, "Apenas o leiloeiro pode encerrar o leilão.");
    require(block.timestamp >= horarioFimLeilao, "O leilão ainda não terminou.");
    require(!encerrado, "O leilão já foi encerrado.");

    encerrado = true;

    emit LeilaoEncerrado(maiorLicitante, maiorLance);

    // Transferir o valor do maior lance para o leiloeiro
    payable(leiloeiro).transfer(maiorLance);
}

Contrato Completo

Aqui está o contrato de leilão completo com todos os componentes combinados:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Leilao {
    address public leiloeiro;
    uint public horarioFimLeilao;
    uint public maiorLance;
    address public maiorLicitante;
    bool public encerrado;

    mapping(address => uint) public retornosPendentes;

    event NovoLance(address indexed licitante, uint valor);
    event LeilaoEncerrado(address vencedor, uint valor);

    constructor(uint _tempoDeLance) {
        leiloeiro = msg.sender;
        horarioFimLeilao = block.timestamp + _tempoDeLance;
    }

    function lance() public payable {
        require(block.timestamp < horarioFimLeilao, "O leilão já terminou.");
        require(msg.value > maiorLance, "O valor do lance não é alto o suficiente.");

        if (maiorLance != 0) {
            retornosPendentes[maiorLicitante] += maiorLance;
        }

        maiorLicitante = msg.sender;
        maiorLance = msg.value;

        emit NovoLance(msg.sender, msg.value);
    }

    function retirar() public returns (bool) {
        uint valor = retornosPendentes[msg.sender];
        if (valor > 0) {
            retornosPendentes[msg.sender] = 0;
            payable(msg.sender).transfer(valor);
            return true;
        }
        return false;
    }

    function encerrarLeilao() public {
        require(msg.sender == leiloeiro, "Apenas o leiloeiro pode encerrar o leilão.");
        require(block.timestamp >= horarioFimLeilao, "O leilão ainda não terminou.");
        require(!encerrado, "O leilão já foi encerrado.");

        encerrado = true;

        emit LeilaoEncerrado(maiorLicitante, maiorLance);

        payable(leiloeiro).transfer(maiorLance);
    }
}

Conclusão

Nesta aula, criamos um contrato de leilão simples em Solidity. Implementamos funcionalidades chave, como fazer lances, retirar fundos e encerrar o leilão. Este conhecimento fundamental pode ser expandido para criar sistemas de leilão mais complexos com recursos adicionais, como preços de reserva, opções de compra imediata e extensões de tempo.

Isso é apenas o começo; sinta-se à vontade para experimentar com o contrato e adicionar mais funcionalidades à medida que você se aprofunda no desenvolvimento de contratos inteligentes!

Video

Did you like this article? Rate it from 1 to 5:

Thank you for voting!