Lição 133: Contratos Inteligentes Dependentes de Tempo
No mundo do desenvolvimento em blockchain, o tempo desempenha um papel crucial na funcionalidade dos contratos inteligentes. Contratos inteligentes dependentes de tempo nos permitem criar aplicações que podem executar transações ou mudar estados com base no conceito de tempo. Esta lição irá explorar como implementar contratos inteligentes dependentes de tempo em Solidity, fornecendo exemplos e explicações ao longo do caminho.
Compreendendo o Tempo em Solidity
Em Solidity, existem dois tipos principais de variáveis relacionadas ao tempo que costumamos usar:
-
Timestamp de Bloco: O timestamp do bloco atual pode ser obtido usando
block.timestamp
. Este timestamp é definido pelos mineradores e não é completamente confiável, mas é adequado para a maioria das aplicações. -
Número de Bloco: O número do bloco atual pode ser acessado usando
block.number
. Isso pode ser útil para identificar pontos específicos na blockchain.
Tanto block.timestamp
quanto block.number
podem ser utilizados para criar contratos que executam ações após um período pré-determinado.
Exemplo 1: Contrato Simples de Liberação Temporal
Podemos criar um contrato de liberação temporal simples que permite ao proprietário bloquear fundos por um período específico. Durante esse tempo, ninguém pode retirar os fundos.
Código do Contrato Inteligente
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract LiberaçãoTemporal {
address public proprietário;
uint256 public tempoLiberacao;
constructor(uint256 _tempoLiberacao) {
proprietário = msg.sender;
tempoLiberacao = block.timestamp + _tempoLiberacao; // O tempo é definido para liberar após _tempoLiberacao segundos
}
modifier apenasProprietário() {
require(msg.sender == proprietário, "Não é o proprietário do contrato");
_;
}
modifier estáBloqueado() {
require(block.timestamp < tempoLiberacao, "Os fundos já estão desbloqueados");
_;
}
modifier estáDesbloqueado() {
require(block.timestamp >= tempoLiberacao, "Os fundos ainda estão bloqueados");
_;
}
function retirar() external apenasProprietário estáDesbloqueado {
// Lógica para retirar fundos
payable(proprietário).transfer(address(this).balance);
}
receive() external payable estáBloqueado {
// Aceitar depósitos enquanto estiver bloqueado
}
function tempoRestante() external view returns (uint256) {
if(block.timestamp >= tempoLiberacao) {
return 0;
}
return tempoLiberacao - block.timestamp;
}
}
Explicação
Neste contrato LiberaçãoTemporal
:
- O construtor define o
tempoLiberacao
para um determinado período no futuro a partir da implantação. - A função
retirar()
permite que o proprietário retire fundos apenas quando o tempo de liberação tiver passado. - A função
receive()
aceita depósitos enquanto o contrato ainda estiver bloqueado. - Uma função
tempoRestante()
permite que os usuários verifiquem quanto tempo falta até que os fundos possam ser retirados.
Exemplo 2: Contrato de Leilão com Limite de Tempo
A seguir, vamos implementar um contrato de leilão que permite lances por um tempo limitado. O maior licitante pode reivindicar o item do leilão após o término do leilão.
Código do Contrato Inteligente
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Leilão {
address public maiorLicitante;
uint256 public maiorLance;
uint256 public tempoFimLance;
address public proprietário;
event NovoLance(address indexed licitante, uint256 valor);
event LeilãoEncerrado(address vencedor, uint256 valor);
constructor(uint256 _duracaoLance) {
proprietário = msg.sender;
tempoFimLance = block.timestamp + _duracaoLance; // Duração do leilão
}
modifier apenasAntesDoFim() {
require(block.timestamp < tempoFimLance, "O leilão já foi encerrado");
_;
}
modifier apenasDepoisDoFim() {
require(block.timestamp >= tempoFimLance, "O leilão ainda está em andamento");
_;
}
function lance() external payable apenasAntesDoFim {
require(msg.value > maiorLance, "Já existe um lance maior");
if (maiorLicitante != address(0)) {
// Reembolsar o anterior maior licitante
payable(maiorLicitante).transfer(maiorLance);
}
maiorLicitante = msg.sender;
maiorLance = msg.value;
emit NovoLance(msg.sender, msg.value);
}
function finalizarLeilão() external apenasDepoisDoFim {
require(msg.sender == proprietário, "Apenas o proprietário pode finalizar o leilão");
emit LeilãoEncerrado(maiorLicitante, maiorLance);
payable(proprietário).transfer(maiorLance); // Transfere o maior lance para o proprietário do leilão
}
function obterTempoRestante() external view returns (uint256) {
if (block.timestamp >= tempoFimLance) {
return 0;
}
return tempoFimLance - block.timestamp;
}
}
Explicação
Neste contrato Leilão
:
- O
tempoFimLance
é definido com base na duração passada durante a inicialização do contrato. - A função
lance()
permite que os participantes deem lances se fizerem uma oferta maior que o maior lance atual, com o anterior maior licitante sendo automaticamente reembolsado. - Após o término do leilão, o proprietário pode finalizar o leilão, transferindo o valor do maior lance para si mesmo.
- Uma função
obterTempoRestante()
ajuda os licitantes a verificarem quanto tempo resta para os lances.
Conclusão
Contratos inteligentes dependentes de tempo podem introduzir uma variedade de funcionalidades nas aplicações descentralizadas. Ao aproveitar timestamps de bloco e números de bloco, os desenvolvedores podem criar contratos que mudam de estado com base no tempo, habilitando recursos como liberações temporais e leilões. Nesta lição, exploramos dois exemplos práticos: um contrato de liberação temporal e um contrato de leilão, ambos destacando diferentes aspectos da gestão do tempo em Solidity.
À medida que você experimenta com esses conceitos, considere explorar casos de uso adicionais e combinações para utilizar o tempo de forma eficaz em seus contratos inteligentes.