Pré-requisitos:
- O que é Staking (participação) e Yield Farming (cultivo de rendimento)?
- Principais recursos e componentes de um contrato inteligente de Staking e Yield Farming.
- Casos de uso de um Contrato Inteligente de Staking e Yield Farming.
- Escrevendo um contrato inteligente de Staking e Yield Farming.
- Implantação com QuickNode RPC.
O QUE É STAKING E YIELD FARMING?
Staking e Yield Farming são atividades populares no espaço de criptomoedas e blockchain. São métodos para usuários como eu e você ganharem recompensas participando de redes blockchain. Aqui está uma explicação de cada um:
Staking:
Staking é o processo de participação ativa na validação de transações em uma blockchain de prova de participação (PoS ou Proof-of-Stake). Envolve manter uma certa quantidade de criptomoeda em uma carteira para apoiar as operações da rede e, em troca, os participantes recebem recompensas na forma de tokens de criptomoeda adicionais.
Como funciona:
- Adquirindo criptomoeda: o usuário adquire uma certa quantidade de uma criptomoeda que opera em uma blockchain PoS. Essa criptomoeda é frequentemente chamada de “token de staking”.
- Configuração da carteira: o usuário precisa manter esses tokens em um tipo específico de carteira (geralmente chamada de carteira de staking) que suporte staking.
- Bloqueio de tokens: o usuário bloqueia uma certa quantidade de tokens na carteira como garantia. Esses tokens permanecem na carteira, mas ficam temporariamente inutilizáveis para outros fins.
- Participação no consenso da rede: ao colocar seus tokens em staking, o usuário participa ativamente do mecanismo de consenso da rede, ajudando a validar transações e proteger a blockchain.
- Ganho de recompensas: em troca de sua participação, os stakers recebem recompensas na forma de tokens adicionais. As recompensas são normalmente proporcionais à quantidade de tokens em stake (apostados).
Benefícios:
- Renda passiva: o staking permite que os usuários ganhem recompensas de forma passiva, simplesmente mantendo e fazendo staking dos seus tokens.
- Segurança de rede: os stakers desempenham um papel crucial na manutenção da segurança e integridade da rede blockchain.
Riscos:
- Slashing: em alguns sistemas PoS, se um staker se comportar de forma maliciosa ou não seguir as regras da rede, ele poderá ser penalizado, incluindo a perda de uma parte de seus tokens colocados em stake.
Yield Farming:
Definição: Yield Farming é uma prática DeFi (Finanças Descentralizadas) que permite aos usuários gerar retornos sobre suas participações em criptomoedas participando ativamente em empréstimos ou fornecimento de liquidez em plataformas blockchain.
Como funciona:
- Fornecimento de liquidez: os usuários fornecem liquidez para uma exchange descentralizada (DEX) ou uma plataforma de empréstimo, depositando sua criptomoeda em um pool de liquidez.
- Recebimento de tokens: em troca do fornecimento de liquidez, os usuários recebem um novo token representando sua participação no pool.
- Maximização do rendimento (yield): os usuários podem tomar outras medidas para maximizar seu rendimento. Isso pode envolver estratégias como “troca de rendimento” ou “composição de rendimento”, em que os usuários movem seus ativos entre diferentes protocolos para obter recompensas adicionais.
Benefícios:
- Potencial de alto rendimento: o yield farming pode oferecer retornos significativamente mais elevados em comparação com as contas de poupança tradicionais ou staking.
Riscos:
- Perda impermanente: ao fornecer liquidez a um pool, os usuários podem sofrer perdas em comparação com a retenção dos tokens individualmente devido a flutuações de preços.
- Riscos de contratos inteligentes: yield farming geralmente envolve a interação com contratos inteligentes e as vulnerabilidades nesses contratos podem levar a perdas financeiras.
PRINCIPAIS RECURSOS E COMPONENTES DO CONTRATO INTELIGENTE DE STAKING E YIELD FARMING.
Estas são características gerais:
Contrato inteligente de staking:
-
Gerenciamento de stake:
- Permite que os usuários bloqueiem e desbloqueiem seus tokens para staking.
- Acompanha a quantidade de tokens em stake por cada usuário.
-
Distribuição de recompensas:
- Calcula e distribui recompensas aos stakers com base na quantidade de tokens em stake e na duração do seu staking.
-
Bloqueio de token:
- Implementa um mecanismo para bloquear tokens em stake por um período específico, garantindo que os usuários não possam retirá-los imediatamente.
-
Mecanismo de slashing (se aplicável):
- Aplica penalidades por comportamento malicioso ou violações de regras por parte dos stakers.
-
Registro de Eventos:
- Emite eventos para notificar usuários e sistemas externos sobre os principais eventos de staking (staking, retirada de staking, distribuição de recompensas).
-
Interface do usuário (opcional):
- Fornece uma interface de fácil utilização para os usuários interagirem com o contrato de staking, incluindo staking, retirada de staking e visualização de recompensas.
Contrato inteligente de yield farming:
-
Gestão do pool de liquidez:
- Gerencia a criação, operação e encerramento de pools de liquidez.
- Permite aos usuários depositar e sacar liquidez.
-
Atribuição de recompensa:
- Atribui recompensas (na forma de tokens) aos provedores de liquidez com base na sua participação no pool.
-
Estratégias de maximização de rendimento:
- Implementa estratégias para maximizar o rendimento, como troca de rendimento, composição ou produção de yield farming em vários protocolos.
-
Reinvestimento de rendimento automatizado (opcional):
- Reinveste automaticamente as recompensas ganhas de volta ao pool de liquidez para aumentar os retornos.
-
Mitigação de Perdas Impermanentes (opcional):
- Implementa mecanismos para mitigar ou compensar perdas impermanentes sofridas por provedores de liquidez.
-
Registro de eventos:
- Emite eventos para notificar usuários e sistemas externos sobre os principais eventos de yield farming (depósito, retirada, distribuição de recompensas).
-
Interface do usuário (opcional):
- Fornece uma interface de fácil utilização para os usuários interagirem com o contrato de yield farming, incluindo depósito, retirada e visualização de recompensas.
-
Integração de contratos inteligentes:
- Pode integrar-se com outros contratos inteligentes, como exchanges descentralizadas ou protocolos de empréstimo, para facilitar estratégias de yield farming.
Componentes comuns para ambos:
-
Propriedade e controle de acesso:
- Inclui mecanismos para propriedade de contratos e controle de acesso para garantir que apenas partes autorizadas possam fazer alterações críticas.
-
Recursos de segurança:
- Implementa as melhores práticas de segurança para proteção contra vulnerabilidades comuns, como ataques de reentrância ou problemas de overflow/underflow.
-
Mecanismo de bloqueio de tempo (Timelock) (opcional):
- Fornece um mecanismo de bloqueio de tempo para atrasar determinadas operações ou atualizações do contrato, permitindo a adoção de medidas de governança ou segurança.
-
Integração com sistemas externos (opcional):
- Pode integrar-se a oráculos, feeds de preços ou outros sistemas externos para acessar dados do mundo real para tomada de decisões dentro do contrato.
-
Mecanismo de governança (opcional):
- Permite a governança na cadeia, permitindo que os detentores de tokens ou partes interessadas votem nos principais parâmetros ou alterações no contrato.
-
Documentação:
- Inclui documentação clara e abrangente para orientar os usuários, desenvolvedores e auditores na compreensão e interação com o contrato.
CASOS DE USO DE CONTRATO INTELIGENTE DE STAKING E YIELD FARMING
-
Blockchain de prova de participação (PoS):
- Os validadores colocam seus tokens em stake para proteger a rede e validar as transações.
-
Governança e votação:
- Os usuários colocam tokens em stake para participar em decisões de governança, como atualizações de protocolo, alterações de parâmetros ou atribuição de fundos.
-
Fornecimento de liquidez em DeFi:
- Os usuários colocam seus tokens em stake para fornecer liquidez a exchanges descentralizadas ou plataformas de empréstimo e ganhar recompensas.
-
Vesting e bloqueio de token:
- Os projetos podem implementar o staking como uma forma de bloquear tokens por um período específico, garantindo o compromisso de longo prazo das partes interessadas.
-
Redes de teste incentivadas:
- Os projetos usam o staking como um mecanismo de incentivo para que os usuários participem de redes de teste e forneçam feedback valioso.
-
Depósito de segurança para serviços:
- Os usuários podem colocar tokens em stake como depósito de segurança ao utilizar determinados serviços, criando confiança e reduzindo comportamentos fraudulentos.
Casos de uso de contratos inteligentes de yield farming:
-
Mineração de liquidez:
- Os projetos incentivam os usuários a fornecer liquidez à sua plataforma, recompensando-os com tokens.
-
Bootstrapping de novos projetos:
- Novos projetos podem usar o yield farming para distribuir seus tokens e atrair liquidez para sua plataforma.
-
Distribuição de tokens de governança:
- O yield farming pode ser usado como um meio de distribuir tokens de governança aos primeiros participantes ou provedores de liquidez.
-
Balanceamento de pools de liquidez:
- Estratégias de yield farming podem ser empregadas para equilibrar a liquidez entre diferentes ativos dentro de uma exchange descentralizada.
-
Estimular a adoção da plataforma:
- As plataformas podem usar o yield farming para atrair usuários e liquidez, dando início à atividade em sua plataforma.
-
Fornecimento de liquidez para mercados de NFT:
- Os usuários podem fornecer liquidez para mercados de NFT, permitindo uma negociação e troca mais fácil de NFTs.
-
Seguro descentralizado:
- O yield farming pode ser usado para fornecer liquidez para plataformas de seguro descentralizadas, garantindo cobertura aos usuários.
-
Protocolos de crédito e de empréstimo:
- O yield farming pode ser usado para incentivar os usuários a emprestar ou tomar emprestado ativos dentro de uma plataforma de empréstimo descentralizada.
ESCREVENDO UM CONTRATO INTELIGENTE DE STAKING E YIELD FARMING
Ei, chega de fundamentos, é hora de ir para a parte técnica!
Abaixo está um código de contrato inteligente de staking e yield farming:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract StakingYieldFarm {
address public owner;
uint256 public totalStaked;
mapping(address => uint256) public stakedBalances;
mapping(address => uint256) public rewards;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Somente o proprietário pode chamar esta função");
_;
}
function stake(uint256 amount) external {
require(amount > 0, "A quantidade em stake deve ser superior a zero");
require(msg.sender != address(0), "Endereço inválido");
// Transfere tokens para o contrato
// (Assumindo que existe um contrato de token e que ele tenha uma função `approve`)
// tokenContract.approve(address(this), amount);
// tokenContract.transferFrom(msg.sender, address(this), amount);
stakedBalances[msg.sender] += amount;
totalStaked += amount;
}
function unstake(uint256 amount) external {
require(amount > 0, "A quantidade a ser retirada (unstake) deve ser superior a zero");
require(stakedBalances[msg.sender] >= amount, "Saldo em stake insuficiente");
stakedBalances[msg.sender] -= amount;
totalStaked -= amount;
// Transfere tokens em stake de volta ao usuário
// tokenContract.transfer(msg.sender, amount);
}
function claimRewards() external {
uint256 reward = rewards[msg.sender];
require(reward > 0, "Não há recompensas para reivindicar");
rewards[msg.sender] = 0;
// Transfere recompensas para o usuário
// rewardTokenContract.transfer(msg.sender, reward);
}
function distributeRewards(address[] memory recipients, uint256[] memory amounts) external onlyOwner {
require(recipients.length == amounts.length, "Comprimentos de entrada inválidos");
for (uint256 i = 0; i < recipients.length; i++) {
rewards[recipients[i]] += amounts[i];
}
}
function getStakedBalance(address account) external view returns (uint256) {
return stakedBalances[account];
}
function getTotalStaked() external view returns (uint256) {
return totalStaked;
}
function getRewardBalance(address account) external view returns (uint256) {
return rewards[account];
}
}
Uma explicação detalhada do código abaixo:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
-
// SPDX-License-Identifier: MIT
: é um comentário especial que indica a licença sob a qual o código foi lançado. Neste caso, especifica a licença MIT, que é uma licença permissiva de código aberto. Ela permite que outros usem, modifiquem e distribuam o código com a devida atribuição. -
pragma solidity ^0.8.0;
: esta instrução Pragma especifica a versão do compilador Solidity a ser usada. Diz ao compilador para usar uma versão igual ou superior a 0.8.0. do Solidity, que é a linguagem de programação usada para escrever contratos inteligentes Ethereum.
contract StakingYieldFarm {
address public owner;
uint256 public totalStaked;
mapping(address => uint256) public stakedBalances;
mapping(address => uint256) public rewards;
-
contract StakingYieldFarm { ... }
: esta linha define um novo contrato inteligente denominadoStakingYieldFarm
. -
address public owner;
: declara uma variável de estado públicaowner
do tipoaddress
. Ela armazenará o endereço do proprietário ou criador do contrato. -
uint256 public totalStaked;
: declara uma variável de estado públicatotalStaked
do tipouint256
. Essa variável acompanhará a quantidade total de tokens em stake no contrato. -
mapping(address => uint256) public stakedBalances;
: declara uma variável de estado públicastakedBalances
como um mapeamento. Associa os endereços aos seus respectivos saldos de tokens em stake. -
mapping(address => uint256) public rewards;
: declara uma variável de estado públicorewards
como um mapeamento. Associa os endereços às suas recompensas ganhas.
constructor() {
owner = msg.sender;
}
-
constructor() { ... }
: é a função do construtor do contrato. É executada uma vez quando o contrato é implantado. -
owner = msg.sender;
: dentro do construtor, define a variávelowner
para o endereço do remetente (aquele que implanta o contrato). Isso estabelece o proprietário inicial do contrato.
modifier onlyOwner() {
require(msg.sender == owner, "Somente o proprietário pode chamar esta função");
_;
}
-
modifier onlyOwner() { ... }
: define um modificador chamadoonlyOwner
. Modificadores são usados para alterar o comportamento das funções. Esse modificador restringe o acesso às funções apenas ao proprietário (owner
). -
require(msg.sender == owner, "Somente o proprietário pode chamar esta função");
: verifica se o endereço que chama a função (msg.sender
) é igual ao endereço doowner
. Caso contrário, gera uma exceção com a mensagem "Somente o proprietário pode chamar esta função". -
_;
: este é um espaço reservado para o código real da função. Indica onde o código da função modificada será executado.
function stake(uint256 amount) external {
require(amount > 0, "A quantidade em stake deve ser superior a zero");
require(msg.sender != address(0), "Endereço inválido");
// Transfere tokens para o contrato
// (Assumindo que existe um contrato de token e que ele tenha uma função `approve`)
// tokenContract.approve(address(this), amount);
// tokenContract.transferFrom(msg.sender, address(this), amount);
stakedBalances[msg.sender] += amount;
totalStaked += amount;
}
-
function stake(uint256 amount) external { ... }
: define uma função chamadastake
. Pode ser chamada externamente por qualquer pessoa que queira colocar tokens em stake. -
require(amount > 0, "A quantidade em stake deve ser superior a zero");
: verifica se o parâmetroamount
é maior que zero. Caso contrário, gera uma exceção com a mensagem “A quantidade em stake deve ser superior a zero”. -
require(msg.sender != address(0), "Endereço inválido");
: verifica se o endereço do remetente (msg.sender
) não é o endereço nulo (address(0)). Se for, gera uma exceção com a mensagem "Endereço inválido". - As linhas comentadas representam a funcionalidade esperada de transferência de tokens para o contrato. Pressupõe-se que existe um contrato de token com as funções
approve
etransferFrom
. Essas linhas devem ser substituídas pela implementação real do staking de tokens. -
stakedBalances[msg.sender] += amount;
: isto aumenta o saldo dos tokens em stake do remetente (msg.sender
) pelo valor (amount
) especificado. -
totalStaked += amount;
: isto aumenta o valor total em stake no contrato.
function unstake(uint256 amount) external {
require(amount > 0, "A quantidade retirada (unstake) deve ser superior a zero");
require(stakedBalances[msg.sender] >= amount, "Saldo em stake insuficiente");
stakedBalances[msg.sender] -= amount;
totalStaked -= amount;
// Transfere tokens em stake de volta ao usuário
// tokenContract.transfer(msg.sender, amount);
}
-
function unstake(uint256 amount) external { ... }
: define uma função chamadaunstake
. Ela permite que um usuário retire o stake de uma determinada quantidade (amount
) de tokens. -
require(amount > 0, "A quantidade a ser retirada (unstaked) deve ser superior a zero");
: verifica se o parâmetroamount
é maior que zero. Caso contrário, gera uma exceção com a mensagem “A quantidade a ser retirada (unstake) deve ser superior a zero”. -
require(stakedBalances[msg.sender] >= amount, "Saldo em stake insuficiente");
: verifica se o remetente (msg.sender
) tem um saldo de tokens em stake maior ou igual aoamount
. Caso contrário, gera uma exceção com a mensagem "Saldo em stake insuficiente". -
stakedBalances[msg.sender] -= amount;
: isto diminui o saldo em stake do remetente pelo valor (amount
) especificado. -
totalStaked -= amount;
: isto diminui o valor total em stake no contrato. - A linha comentada representa a funcionalidade esperada de transferência de tokens em stake de volta ao usuário. Assume que existe um contrato de token com uma função
transfer
. Essa linha deve ser substituída pela implementação real para transferência dos tokens a serem retirados (unstaked tokens).
function claimRewards() external {
uint256 reward = rewards[msg.sender];
require(reward > 0, "Não há recompensas para reivindicar");
rewards[msg.sender] = 0;
// Transfere recompensas para o usuário
// rewardTokenContract.transfer(msg.sender, reward);
}
-
function claimRewards() external { ... }
: isto define uma função chamadaclaimRewards
. Permite que um usuário reivindique as recompensas ganhas. -
uint256 reward = rewards[msg.sender];
: recupera o saldo da recompensa associado ao endereço do remetente. -
require(reward > 0, "Não há recompensas para reivindicar");
: verifica se o saldo da recompensa é maior que zero. Caso contrário, gera uma exceção com a mensagem "Não há recompensas para reivindicar". -
rewards[msg.sender] = 0;
: define o saldo de recompensas do remetente como zero, indicando que as recompensas foram reivindicadas. - A linha comentada representa a funcionalidade esperada de transferência de recompensas ao usuário. Pressupõe-se que existe um contrato de token de recompensa com uma função
transfer
. Essa linha deve ser substituída pela implementação real de transferência de recompensas.
function distributeRewards(address[] memory recipients, uint256[] memory amounts) external onlyOwner {
require(recipients.length == amounts.length, "Comprimentos de entrada inválidos");
for (uint256 i = 0; i < recipients.length; i++) {
rewards[recipients[i]] += amounts[i];
}
}
-
function distributeRewards(address[] memory recipients, uint256[] memory amounts) external onlyOwner { ... }
: isto define uma função chamadadistributeRewards
. Ela permite que o proprietário distribua recompensas a vários destinatários. -
require(recipients.length == amounts.length, "Comprimentos de entrada inválidos");
: verifica se os comprimentos dos arraysrecipients
eamounts
são iguais. Caso contrário, gera uma exceção com a mensagem "Comprimentos de entrada inválidos". - Em seguida, faz uma iteração sobre o array
recipients
e adiciona as recompensas especificadas ao saldo de cada destinatário.
function getStakedBalance(address account) external view returns (uint256) {
return stakedBalances[account];
}
function getTotalStaked() external view returns (uint256) {
return totalStaked;
}
function getRewardBalance(address account) external view returns (uint256) {
return rewards[account];
}
}
-
function getStakedBalance(address account) external view returns (uint256) { ... }
:: isto define uma função chamadagetStakedBalance
que permite a qualquer pessoa consultar o saldo em stake de uma determinada conta (account
). -
function getTotalStaked() external view returns (uint256) { ... }
: : define uma função chamadagetTotalStaked
que permite a qualquer pessoa consultar o valor total em stake no contrato. -
function getRewardBalance(address account) external view returns (uint256) { ... }
: isto define uma função chamadagetRewardBalance
que permite a qualquer pessoa consultar o saldo de recompensa de uma determinada conta (account
).
Este contrato inteligente fornece funcionalidades para staking e retirada de stake de tokens, reivindicar recompensas e distribuir recompensas. Também permite ao proprietário gerenciar a distribuição de recompensas.
Vamos escrever este código em nosso IDE REMIX.
IMPLANTAÇÃO COM RPC QUICKNODE
PASSO 1.
Crie um novo nó Sepolia no QuickNode. Você terá que navegar até o painel de controle do QuickNode e clicar em “Create” (criar).
Depois, certifique-se de clicar na cadeia Ethereum. Confira uma captura de tela abaixo:
Clique em “Sepolia”:
Em seguida, clique em “Continue” (continuar) para prosseguir. Por fim, clique em “Create endpoint” (criar ponto de extremidade) para obter seu URL da Sepolia.
PASSO 2.
Clique em “Add network” (adicionar rede). Siga as instruções sobre como adicionar o URL RPC ao navegador da sua carteira.
Clique em “Add network manually” (adicionar rede manualmente).
PASSO 3.
Insira um nome (qualquer), já que está usando o QuickNode, você pode usar “QKN”. Copie/cole seu ponto de extremidade Web3 (certifique-se de incluir “/” no final!), insira o ChainID e clique em “Save” (salvar).
Estamos usando a rede de testes Sepolia, então é aconselhável usar o ID da cadeia Sepolia, que é “11155111”.
Por fim, você obterá o resultado abaixo.
Perfeito! Estamos quase terminando, agora solicitamos um pouco de Eth da rede de testes Sepolia para podermos implantar nosso contrato inteligente.
PASSO 4.
Agora, para obter taxas de gás, vamos usar a https://faucet.quicknode.com/drip. Abaixo está o procedimento.
Em seguida, conecte a carteira e obtenha um pouco de Eth.
Depois de fazer isso, você obterá o resultado abaixo:
Com isso, estamos prontos para implantar nosso contrato inteligente de staking e yield farming.
Implantação do Código de Contrato Inteligente na Rede de Testes Sepolia
Clique em “Confirm” (confirmar) para finalizar as transações.
Conclusão
Parabéns por criar com sucesso seu próprio contrato inteligente de Staking e Yield Farming na rede Ethereum!
Assine o boletim informativo do QuickNode para mais artigos e guias sobre a Ethereum. Se você tiver algum comentário, sinta-se à vontade para entrar em contato conosco por meio do Twitter. Você sempre pode conversar conosco em nosso servidor da comunidade Discord, que conta com alguns dos desenvolvedores mais legais que você já conheceu :)
Este artigo foi escrito por Playboi.eth e traduzido por Isabela Curado Nehme. Seu original pode ser lido aqui.
Top comments (0)