WEB3DEV

Cover image for Como construir um contrato inteligente e aplicativo da Web para stake de tokens ERC20
Diogo Jorge
Diogo Jorge

Posted on

Como construir um contrato inteligente e aplicativo da Web para stake de tokens ERC20

Image description

Neste guia, veremos como você pode criar seu próprio contrato inteligente e aplicativo da Web para stake de tokens ERC20, que recompensa seus usuários por fazer stake de tokens ERC20 com mais tokens ERC20 de recompensa!

Mostraremos como:

  • Criar o contrato de stake ERC20 no Solidity usando ContractKit
  • Implantá-lo na blockchain de sua escolha
  • Criar um aplicativo da web para os usuários fazerem stake de seus tokens e reivindicarem recompensas

Vamos começar!

Criando um Contrato Inteligente de Stake ERC20

Primeiro, mostraremos como criar um contrato inteligente no Solidity com a ajuda de ContractKit; isso permite que você personalize a lógica do contrato inteligente o quanto quiser usando o Solidity.

Criando um projeto Solidity

Vamos usar a CLI para configurar nosso projeto Solidity e criar nosso contrato inteligente.

Para começar, execute o seguinte comando no seu terminal:

npx thirdweb@latest create contract
Enter fullscreen mode Exit fullscreen mode

Isso iniciará um processo interativo para criar seu projeto da seguinte forma:

Image description

Criando um contrato usando a CLI Thirdweb

Assim que seu projeto estiver configurado, estamos prontos para começar a escrever nosso contrato inteligente!

Escrevendo o Contrato de stake ERC20

No projeto de contratos recém-criado, navegue até o diretório contracts e exclua o arquivo de contrato padrão contract.sol.

Crie um novo arquivo chamado StakingContract.sol, que representa o contrato de stake que vamos escrever. Nós vamos utilizar o contrato base Staking20Base disponível no ContractKit como base para nosso contrato inteligente.

Seguiremos um processo de três etapas para criar um contrato que herda Staking20Base:

  1. Importe o contrato base do pacote @thirdweb-dev/contracts.
  2. Faça nosso contrato inteligente herdar o contrato base importado.
  3. Configure o contrato inteligente com um construtor.

Atualize o conteúdo do StakingContract.sol igual a:

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

import "@thirdweb-dev/contracts/base/Staking20Base.sol";
import "@thirdweb-dev/contracts/token/TokenERC20.sol";

contract StakingContract is Staking20Base {
    constructor(
        uint256 _timeUnit,
        uint256 _rewardRatioNumerator,
        uint256 _rewardRatioDenominator,
        address _stakingToken,
        address _rewardToken,
        address _nativeTokenWrapper
    ) Staking20Base(
        _timeUnit,
        _rewardRatioNumerator,
        _rewardRatioDenominator,
        _stakingToken,
        _rewardToken,
        _nativeTokenWrapper
    ) {}

    function _mintRewards(address _staker, uint256 _rewards) internal override {
        TokenERC20 tokenContract = TokenERC20(rewardToken);
        tokenContract.mintTo(_staker, _rewards);
    }
}
Enter fullscreen mode Exit fullscreen mode

No código acima, estamos importando o contrato Staking20Base de @thirdweb-dev/contracts e o herdamos em nosso contrato inteligente.

Isso significa que nosso StakingContract agora tem todas as funcionalidades do contrato Staking20Base disponível para uso!

Criando a função _mintRewards()

Agora que nosso contrato inteligente está configurado, precisamos criar uma função para enviar aos nossos participantes suas recompensas.

O Staking20Base expõe uma função chamada _mintRewards() que você pode substituir em seu contrato principal para colocar qualquer lógica que desejar quando o usuário tentar reivindicar suas recompensas de stake.

Image description

Código-fonte do contrato Staking20Base.sol

Neste caso, nós vamos cunhar os tokens de recompensa para o usuário quando eles chamarem essa função.

Se você ainda não tiver um contrato de token implantado, poderá criar um contrato de token ERC20 pelo painel na próxima etapa ou criar um contrato inteligente personalizável no Solidity usando o Contrato Base ERC20 e implantá-los também.

Importar o TokenERC20 contrato em seu StakingContract.sol:

import "@thirdweb-dev/contracts/token/TokenERC20.sol";
Enter fullscreen mode Exit fullscreen mode

Em seguida, vamos substituir a função _mintRewards()do contrato base de staking:

function _mintRewards(address _staker, uint256 _rewards) internal override {
    TokenERC20 tokenContract = TokenERC20(rewardToken);
    tokenContract.mintTo(_staker, _rewards);
}
Enter fullscreen mode Exit fullscreen mode

É isso! Agora seus participantes podem reivindicar suas recompensas com sua lógica personalizada para cunhar/transferir os tokens.

Implantando e configurando o contrato

Agora que o contrato está escrito, podemos implantar o contrato na blockchain!

Recomendamos começar com uma testnet antes de implantar em uma rede principal.

Seguiremos os passos abaixo para configurar nosso contrato de staking pronto para os usuários começarem a interagir com ele:

  1. Implante um token ERC-20 para tokens de staking
  2. Implante um token ERC-20 para tokens de recompensa
  3. Implantar o contrato de staking
  4. Defina permissões do cunhador (minter) para o contrato de stake no token de recompensa (se você optar por cunhar tokens)

Feito isso, o contrato de stake está pronto para uso e qualquer pessoa pode fazer stake de tokens no contrato e reivindicar suas recompensas.

Implantando Contrato Inteligente de Token de Staking

Se você ainda não possui um token ERC20 para o qual deseja que os usuários façam stake, vá para a Página de contrato inteligente de token no painel do thirdweb e clique no botão Deploy Now (Implantar agora).

Insira os metadados do seu contrato inteligente, selecione a rede para implantar e clique em Deploy Now. Isso deve abrir sua carteira conectada e você será solicitado a aprovar uma transação. Após a aprovação, o contrato será implantado e você será redirecionado para o painel de contratos:

Image description
Dashboard (painel) para o contrato de token ERC-20

Recomendamos cunhar alguns tokens usando o botão Mint (cunhar), pois estes serão colocados em stake no contrato nas próximas etapas.

Anote o endereço do contrato inteligente, (abaixo do nome), pois precisaremos dele para implantar nosso contrato de stake em breve.

Implantando contrato inteligente de token de recompensa

Crie um novo contrato de token que atuará como o token de recompensa. Siga as mesmas etapas feitas para o contrato de token de stake.

Implantando o Contrato Inteligente de Staking

No diretório do projeto de contratos, execute o seguinte comando no terminal para compilar e implantar o contrato na blockchain:

npx thirdweb@latest deploy
Enter fullscreen mode Exit fullscreen mode

Isso vai compilar o contrato e, se nenhum erro for encontrado, carregará a ABI do contrato no IPFS. Em seguida, seu navegador deve aparecer para promover o processo de implantação e você precisará preencher os parâmetros do construtor.

  • _timeUnit: Quantos segundos antes das recompensas serem dadas. Por exemplo, 1 significa cada 1 segundo, uma nova quantidade de recompensas é fornecida (você pode atualizar esse valor após a implantação)
  • rewardRatioNumerator e rewardRatioDenominador: por exemplo. Uma proporção de 1 / 20 significaria 1 token de recompensa é dado a cada timeUnit para cada 20 tokens em stake.
  • _stakingToken: endereço do contrato inteligente do token ERC20 que você deseja que os usuários coloquem em stake no contrato.
  • _rewardToken: endereço do contrato inteligente do token ERC20 que você deseja recompensar aos usuários pelo stake.

Por exemplo, na captura de tela abaixo, os usuários fazem stake do token 0x97; e são recompensados 1/2 (metade) do número de tokens que eles colocaram em stake no token 0x7F a cada 1 segundo.

Para o wrapper (encapsulador) de token nativo, coloque o endereço do token encapsulado para essa cadeia. Por exemplo, para Ethereum, é WETH (ether encapsulado).

Image description

Preencha os metadados para o contrato a ser implantado

Por fim, selecione a rede na qual deseja implantar (precisa ser igual aos outros contratos inteligentes) e clique em Deploy Now.

Configurando as permissões no token de recompensa

Saindo do contrato inteligente de tokens de recompensa, navegue até a aba Permissions (permissões), e você deverá ver a seguinte interface:

Image description

Configurando permissões no contrato de token ERC-20 usando o painel da thirdweb

Na função de cunhagem, adicione o endereço do contrato de staking e clique em Atualizar permissões. Você deve ser solicitado a aprovar uma transação. Depois de aprovado, o contrato de staking agora está autorizado a cunhar tokens usando o contrato de token de recompensa.

Isso é necessário para a função_mintRewards para trabalhar em nosso contrato inteligente de staking!

Criando o aplicativo Staking

Você pode acessar o código-fonte completo do aplicativo em nosso GitHub.

Agora vamos criar um projeto de aplicativo da web que permita aos usuários conectar sua carteira e interagir com nossos contratos inteligentes. Em um diretório seguro, execute o seguinte comando em seu terminal para criar um aplicativo com nosso SDK instalado e configurado:

npx thirdweb@latest create app
Enter fullscreen mode Exit fullscreen mode

Ao executar o comando acima, você deve ser apresentado a um assistente de criação de aplicativo com opções de configuração.

Image description

CLI da thirdweb criando um aplicativo

Depois que o aplicativo for criado, certifique-se de ir para _app.js e mude o ChainId desejado à rede que você tem seus contratos implantados.

Por exemplo, no meu caso, tenho os contratos implantados na Polygon Mumbai, então usarei ChainId.Mumbai.

Conectando-se ao Contrato Inteligente

Navegue para index.js arquivo dentro do diretório pages dentro do projeto e adicione a seguinte variável fora do componente:

const stakingContractAddress= "<staking_contract_address>";
Enter fullscreen mode Exit fullscreen mode

Lembre-se de substituir o valor da variável pelo endereço do seu contrato de staking.

Agora, vamos carregar o contrato de staking e outros dados usando ganchos do React.

Primeiro, usaremos o gancho useAddress() para que possamos acompanhar o endereço da carteira conectada o tempo todo e inicializar uma variável de estado chamada ammountToStake (quantidade para fazer stake) que posteriormente mapearemos para uma caixa de texto para obter entrada do usuário.

const address = useAddress();
const [amountToStake, setAmountToStake] = useState(0);
Enter fullscreen mode Exit fullscreen mode

Em seguida, vamos inicializar todos os nossos contratos usando useContract:

const { contract: staking, isLoading: isStakingLoading } = useContract(
  stakingContractAddress,
  "custom"
);

const { contract: stakingToken, isLoading: isStakingTokenLoading } =
  useContract(stakingTokenAddress, "token");


const { contract: rewardToken, isLoading: isRewardTokenLoading } = useContract(
  rewardTokenAddress,
  "token"
);
Enter fullscreen mode Exit fullscreen mode

Agora que temos nossos contratos, podemos usar o gancho useTokenBalance para obter o saldo da carteira conectada do token de stake e do token de recompensa:

// saldos de tokens
const { data: stakingTokenBalance, refetch: refetchStakingTokenBalance } =
  useTokenBalance(stakingToken, address);
const { data: rewardTokenBalance, refetch: refetchRewardTokenBalance } =
  useTokenBalance(rewardToken, address);
Enter fullscreen mode Exit fullscreen mode

Finalmente, podemos usar o gancho useContractRead para carregar as informações de staking para o usuário atual e usar um setIntervaldentro de um bloco useEffect para buscar novamente esses dados a cada 10 segundos.

// Obter dados do staking
const {
  data: stakeInfo,
  refetch: refetchStakingInfo,
  isLoading: isStakeInfoLoading,
} = useContractRead(staking, "getStakeInfo", address || "0");

useEffect(() => {
  setInterval(() => {
    refetchData();
  }, 10000);
}, []);

const refetchData = () => {
  refetchRewardTokenBalance();
  refetchStakingTokenBalance();
  refetchStakingInfo();
};
Enter fullscreen mode Exit fullscreen mode

Agora temos todos os dados que nosso aplicativo exige dos contratos, agora precisamos exibir esses valores e criar lógica para fazer stake de tokens de usuário.

Criando a IU

Agora podemos usar as informações que carregamos dos ganchos para renderizar na IU, fazendo uso do botão da ConnectWallet e dos componentes da IU Web3Button.

Podemos adicionar um botão para permitir que o usuário faça stake, retire e reivindique seus tokens:

<div className={styles.stakeContainer}>
  <input
    className={styles.textbox}
    type="number"
    value={amountToStake}
    onChange={(e) => setAmountToStake(e.target.value)}
  />
  <Web3Button
    className={styles.button}
    contractAddress={stakingContractAddress}
    action={async (contract) => {
      await stakingToken.setAllowance(
        stakingContractAddress,
        amountToStake
      );
      await contract.call(
        "stake",
        ethers.utils.parseEther(amountToStake)
      );
      alert("Tokens staked successfully!");
    }}
  >
    Stake!
  </Web3Button>


  <Web3Button
    className={styles.button}
    contractAddress={stakingContractAddress}
    action={async (contract) => {
      await contract.call(
        "withdraw",
        ethers.utils.parseEther(amountToStake)
      );
      alert("Tokens unstaked successfully!");
    }}
  >
    Unstake!
  </Web3Button>


  <Web3Button
    className={styles.button}
    contractAddress={stakingContractAddress}
    action={async (contract) => {
      await contract.call("claimRewards");
      alert("Rewards claimed successfully!");
    }}
  >
    Claim rewards!
  </Web3Button>
</div>
Enter fullscreen mode Exit fullscreen mode

E uma seção para mostrar as informações que nós lemos dos ganchos.

<div className={styles.grid}>
  <a className={styles.card}>
    <h2>Stake token balance</h2>
    <p>{stakingTokenBalance?.displayValue}</p>
  </a>

  <a className={styles.card}>
    <h2>Reward token balance</h2>
    <p>{rewardTokenBalance?.displayValue}</p>
  </a>

  <a className={styles.card}>
    <h2>Staked amount</h2>
    <p>
      {stakeInfo && ethers.utils.formatEther(stakeInfo[0].toString())}
    </p>
  </a>

  <a className={styles.card}>
    <h2>Current reward</h2>
    <p>
      {stakeInfo && ethers.utils.formatEther(stakeInfo[1].toString())}
    </p>
  </a>
</div>
Enter fullscreen mode Exit fullscreen mode

É isso! Seu aplicativo de staking com sua lógica personalizada em contrato inteligente agora está pronto.

Executando o aplicativo e testando

Execute o seguinte comando no terminal para ativar um servidor de desenvolvimento para testar seu aplicativo:

yarn dev
Enter fullscreen mode Exit fullscreen mode

Então você pode ir para localhost:3000 no seu navegador para visualizar o aplicativo. Se tudo for feito corretamente, você deverá ver uma tela como esta:

Image description

Aplicativo de stake em execução no navegador

Agora, você pode fazer stake de seus tokens de stake previamente cunhados e observar seu token de recompensa crescer com o tempo. Você também pode retirar o stake e reivindicar suas recompensas usando os botões que acabamos de criar.

Conclusão

Neste guia, usamos o ContractKit para criar seu próprio contrato de stake com lógica personalizada, depois implantamos o contrato, configuramos e, por fim, construímos um aplicativo da web em torno dele.

Se você tiver alguma dúvida sobre este guia ou quiser bater um papo, sinta-se à vontade para entrar em nosso Servidor de discord e entre em contato conosco no canal de suporte.

Este artigo foi escrito por Atharva Deosthale e traduzido por Diogo Jorge. O artigo original está aqui.

Oldest comments (0)