NEAR Revisão de Contrato ao Vivo | Parte 4: Fazenda de Berry

15 min read
To Share and +4 nLEARNs

Introdução

Aqui é Eugene, e hoje vamos falar sobre o contrato Berry Farm que é o suplemento do Berry Club que permite converter suas bananas em pepinos e cultivar NEAR. Vamos primeiro fazer uma rápida revisão da Berry Farm. O repositório pode ser encontrado no meu Github . Aqui está o vídeo original no qual este guia é baseado:

UI – Interface de Usuário

 

Berry farm é um aplicativo muito bem projetado com texto grande e muitos emojis. A maneira como funciona é que exibe seus saldos assim que você estiver logado. Ele os extrai de dois contratos diferentes, bem como de sua conta. Ele os combina de várias fontes. Abacate e banana vêm do contrato Berry Club , pepinos são locais para esse contrato e NEAR vem do saldo da sua conta. Se você farmou qualquer coisa, receberá recompensas quando as recompensas forem distribuídas. Parece que alguém fez muitas compras de abacate recentemente e as recompensas aumentaram. Ele também tem estatísticas globais, o que significa que 2.500 NEAR foram transferidos do Berry Club para Berry Farm. Ganhei 116,9 NEAR e minha recompensa será 0,014332 NEAR com base na quantidade de pepinos que tenho em comparação com o número total de pepinos.

O número total de pepinos é 54116,4. Eu recebo 3% dessa recompensa toda vez que há uma recompensa. Então, quando clico em atualizar, basicamente atualizo as estatísticas de várias contas e posso reivindicar NEAR, que transfere do contrato para minha conta. Também posso trocar bananas por pepinos e estou fazendo um pedido para o contrato do Berry Club.

Eu vou usar transfer_with_vault que está usando o novo padrão, e requer uma pequena quantidade de NEAR, e acho que é como 1 yocto NEAR para confirmar que não estou fazendo isso através de uma chave de acesso. Não posso fazer uma transferência através de uma chave de acesso para evitar o saque automático, e isso é apenas uma proteção de segurança. Se você, por exemplo, autorizar o Berry Club de algum outro aplicativo que tenta drenar todas as suas bananas, ele falhará, porque não poderá chamar transfer_raw ou transfer_with_vault. Para esclarecer, transfer_raw é o novo nome para transferência sem contrato para que você possa apenas depositar na conta de alguém que existe, e no cofre transfer_with_vault está chamando o destinatário para retirar tokens.

Gastei 10 bananas para conseguir mais pepinos e posso atualizar o saldo novamente para ver se alguém retirou alguma coisa. É assim que a Interface do Usuário funciona, mas há mais funcionalidades do que apenas isso. O contrato suporta pepinos como token fungível e as bananas também. Você pode criar outro aplicativo que transfere pepinos e há mais um que é o Banana Swap, que Vlad Garchina construiu.

É um Uniswap simplificado com um único pool onde você pode comprar e vender bananas. Na verdade, eu não tentei antes. Eu quero obter 1 Near em bananas que eu preciso vender por 6 bananas. Vamos ver se funciona.

Isto se chama transferências Berry Club que está mais uma vez envolvida, mas para um contrato diferente. No momento, não exibimos argumentos, mas eventualmente o faremos.

Está dizendo que me transferi e recebi 1 NEAR no qual gastei 6 bananas. Muito legal.

Você não pode adicionar liquidez e é preciso um corte de 10%. Portanto, esta é a interface do usuário.

Revisão de contrato

Berry Club

Deixe-me apresentar o contrato. Então vamos começar com o contrato Banana Farm, mas você provavelmente vai precisar dar uma olhada no token do contrato do Pixelboard, o contrato do Berry Club, bem como aquele que envia tokens.

Berry Club tem um contrato codificado chamado farm contract id.

Quando você desenha, ele verifica se você não desenha pixels vazios, caso contrário, você pode simplesmente acionar uma recompensa sem gastar abacate.

Em seguida, ele chama may_send_reward, que obtém a hora atual do blockchain e verifica se o next_reward_timestamp é menor que a hora atual.

A próxima recompensa é o início do tempo de cultivo, que era um carimbo de data/hora global que originalmente permitia uma contagem regressiva de 26 horas ou last_reward_timestamp quando o acionamos pela última vez, mais 60 segundos.

Então, se é hora de enviar a próxima recompensa, ele lembra a hora atual e calcula a recompensa com base nessa lógica, então pega o saldo atual do Berry Club, pega o armazenamento atual, calcula o armazenamento pelo custo de armazenamento mais alguma margem de segurança, que é de 50 NEAR.

Ele sempre mantém 15 NEAR para os saldos futuros. Então está dizendo que se o saldo estiver disponível, se o nosso saldo for maior do que a quantidade que precisamos para armazenamento + segurança, calculamos o saldo líquido e dividimos pela parcela da recompensa que daremos toda vez, que é 24 vezes 68. 

Se você ligar a cada minuto, então você drenará a maior parte da conta, mas está sempre diminuindo por conta própria, porque o saldo diminui por conta própria, mas na maioria das vezes dá todo o saldo em um dia se você ligasse a cada minuto . 

Em primeiro lugar, você não pode produzir um bloco que está com carimbo de data/hora anterior e você não pode produzir um bloco além do seu slot. Você tem um slot dedicado quando precisa produzir um bloco. Portanto, o máximo que você pode fazer é produzir um pedaço do bloco final no milissegundo final do seu slot, que está um segundo à frente. 

Você não pode realmente avançar, caso contrário todos os outros nós quebrarão o protocolo também, então eles são limitados pela compreensão do tempo + a barra que eles usam para decidir se aceitam ou não um bloco.  Então você não pode realmente fazer um tempo correr mais rápido, a menos que todos os validadores queiram fazer isso. Isso significaria que temos os validadores que essencialmente deixarão de seguir o protocolo. Eles precisam coordenar seu tempo.

Então, no final, ele recebeu a recompensa, dizendo que eu vou distribuir essa recompensa, e o que ele faz é chamar o contrato de Farm, e chamar take_my_near e ele simplesmente não passa nenhum argumento e passa sua recompensa e gás. Apenas uma quantidade mínima de gás é necessária para adicionar os saldos. 

Foi assim que o Berry Club foi atualizado para começar a distribuir recompensas potencialmente após cada sorteio. Leva um pouco mais. Ele usa o gás que foi gasto no desenho para distribuir a recompensa ocasionalmente, o que precisa de cerca de 10 tera de gás para isso.

Farm de Berry

Vamos para Berry Farm e começar com este contrato.  A maneira como o farm de berry funciona precisa, em tempo constante, ser capaz de distribuir recompensas com base no número total de pepinos, o que não é uma tarefa trivial, é um pouco semelhante ao staking pool e como o staking pool distribui recompensas. 

O staking pool cria um monte de ações para cada depósito que você faz e a ação tem um preço global atual que diz: “Ei, eu comprei ou cunhei mais ações e agora minhas ações podem ser resgatadas para um determinado número de tokens NEAR”. 

O preço da ação começa a partir de 1 yocto NEAR por ação e, quanto mais recompensas você acumula, mais o preço das ações sobe. Quando você usa o unstake (retira de stake), você vende ações ao preço atual e recebe NEAR de volta e arredonda para baixo. 

O desafio é quando você aposta pepinos e o preço de um pepino é zero, e quando você as aposta pela primeira vez, não pode realmente comprar ações e cunhar ações, porque o preço delas é zero. A lógica dos compartilhamentos não funciona muito bem para isso, então para isso eu precisava criar algo diferente para fazer a contabilidade. 

Vamos aos exemplos. Digamos que Mike seja a primeira pessoa que depositou 10 pepinos no contrato e, em seguida, digamos que 100 NEAR foram distribuídos. Mike receberá todas as recompensas porque ele é o único, ele controla 100% da participação na Berry Farm agora. Mike estava offline, por exemplo, e não os reivindicou, então não podemos atualizar sua conta, porque isso deve ser feito em tempo constante. Não podemos iterar por todas as contas, mas de alguma forma precisamos lembrar que Mike pegou todas as NEAR pelos seus pepinos. 

Agora vamos dizer que Josh entra e aposta outros 10 pepinos, agora a participação de Mike é de 50% e a participação de Josh é de 50%, mas Josh apostou os pepinos depois que esses 100 NEAR iniciais já foram distribuídos. Ele não tem direito a nada disso agora e Mike precisa pegar mais 50, porque ele tem 50% de participação e Josh fica com 50 NEAR. 

Quando Mike voltar a ficar online, precisamos ser capazes de exibir seu saldo em 150 NEAR que ele ganhou em tempo constante. Portanto, este é o desafio que precisávamos enfrentar com este contrato, e a maneira como ele foi resolvido foi ter uma proporção global chamada de Near por Pepino, que diz quanto NEAR é recebido por um determinado saldo de pepino quando uma conta é criada, ou tocado de qualquer maneira..

Então temos um saldo NEAR, então se a última fração foi menor que a fração atual, significa que podemos multiplicar pepinos da conta dada pela diferença entre 2 frações, e calcular quanto NEAR tenho direito. Quando a conta de Mike foi criada, a fração era 0 dividida por um e quando 100 NEAR foram depositados onde a contagem total de pepinos era 10, essa fração se tornou igual a 10. foram distribuídos, esta fração foi aumentada em 5, pois havia um total de 20 pepinos e 100 NEAR. Então, 100 NEAR dividido por 20 significa 5 NEAR por pepino, então isso se tornou 15. 

Agora, quando Mike volta, ele olha para seu saldo de pepino, que é 10 Near por pepino em um contrato global, é 15, seu último valor lembrado é zero, então ele apenas pega a diferença que é 15 multiplicada por 10 e reivindica esse saldo em NEAR, e isso 1 é ajustado para 15. Quando Josh volta, ele obtém esse valor que era 10, e ele tem 10 pepinos e o valor atual é 15. A diferença é 5 multiplicado pelo saldo de pepino de 10, então ele fica com 50 Near. 

É assim que gerenciamos o saldo NEAR e apropriamos as recompensas recebidas das pessoas usando tempo constante para recalcular. Então, em vez de manter uma fração inteira na memória, usamos um denominador global que é fixo e usei-o para 10 elevado a 18, que é o mesmo que a precisão de pepinos, bananas e abacates. Esse é o pano de fundo de como tudo é calculado.

Vejamos a estrutura principal do contrato, um contrato chamado farm. Ele possui um mapa de pesquisa de contas e usa hashes curtos semelhantes a tokens fungíveis com cofres. Ele tem o ID da conta do token de banana que também pode ser codificado, mas foi usado no contrato porque podemos realmente passá-lo, porque essa conta foi implantada depois e eu não queria atualizar o estado do contrato do banana Berry Club. Eu não queria modificar o estado novamente por meio da capacidade de atualização, então, em vez disso, codifiquei o valor no contrato anterior. Near por pepino, a fração que expliquei anteriormente, é o numerador e o equilíbrio total do pepino é necessário como denominador. Cofres e próximo voto são usados ​​para transferências; eles provavelmente nunca acabaram se acostumando a transferir pepinos, exceto talvez uma vez para um teste.

Isso é o que vimos antes de ser mais uma vez um hash do ID da conta.

A estrutura da conta é o último valor antes da conta ser tocada com essa fração. O near_balance é o saldo não reivindicado. 

Sempre que você toca em uma conta depositando mais pepinos ou reivindicando NEAR, ele atualiza o último valor e move todo o NEAR não reivindicado para o seu saldo local fora da diferença, e o saldo do pepino é o seu saldo em pepinos. O near_claimed são as estatísticas, isso está apenas dizendo quanta recompensa você já reivindicou. Não é necessário para a lógica do contrato.

Há duas estruturas auxiliares apenas para o front-end. A HumanAccount retorna valores de forma mais legível e HumanStats são estatísticas globais de consumo. Vamos entrar na função take_my_near para realmente dar uma olhada em como ela funciona.

A primeira coisa que fazemos é verificar se há pepinos suficientes lá, porque o usamos como denominador. Queremos apenas 1 pepino para realmente desencadear isso, e isso é apenas uma precaução. Você não gosta de acionar esse tipo de coisa. Vamos explorar esse valor. 

O que acontece é que você obtém a quantidade de NEAR, e yocto NEAR, e você multiplica pelo denominador global. Então você está resolvendo uma fração que é Near por Pepino dividido pelo denominador mais o saldo anexado dividido pelo saldo total de pepino. Aqui está a fórmula: near_per_cucumber / denom + attach_deposit / total_cucumber_balance. Então new_near_per_cucumber é na verdade o numerador com attach_deposit e o denominador então dividido pelo denominador. Aqui está a fórmula: new_near_per_cucumber = (near_per-cucumber_numer +denom + depósito anexado) / denom. Esta é a fórmula que usamos para calcular o new_near_per_cucumber. Sempre que você toca em uma conta, ela sempre transforma seu saldo atual não reivindicado em um número fixo e, em seguida, você pode modificar qualquer um dos valores sem quebrar a lógica. Este método de toque é chamado por cada Método Getter e cada método de mudança. Antes de modificar a conta, ele sempre chama o toque na conta.

Por exemplo, em get_near_balance obtemos a conta interna. Se a conta existir, nós a tocamos localmente. Então devemos obter o near_balance.

Se você obtiver a conta, tocamos nela antes, obtenha seu saldo_próximo, saldo_pepino e reivindique o saldo. Essas são funções de visualização que estão alterando as coisas, mas não as salva, apenas altera temporariamente o valor da conta e não a salva de volta. Ele apenas faz um toque que é uma espécie de recálculo com o valor mais recente.

Ele o salva quando você realmente faz qualquer chamada de alteração, então, por exemplo, chame para Claim_near. Obtemos sua conta e get_mut_account realmente toca a conta. Você obtém a conta que já está atualizada e near_balance é o saldo real. 

Leva o near_balance a zero, está dizendo que você reivindicou tudo isso e salva sua conta. Então, se você reivindicar um valor positivo, nós o transferiremos para você da sua conta. Ele retorna quanto NEAR você reivindicou. A beleza desse método de toque é que ele pode ser chamado em qualquer ponto. Ele não precisa ser chamado em um determinado ponto, então sempre dará o mesmo resultado, não importa se você chamou duas vezes no meio ou uma vez. Isso é apenas para retornar ao usuário com o quanto ele tem. Ele só diz o quanto NEAR você ganhou calculando a partir do estado atual. 

No Berry Club também fazemos as mesmas coisas que tocamos, e isso é necessário, porque digamos que você queira saber quantas bananas você farmou. Como sabemos a última vez que você tocou em sua conta, quando você desenhou algo pela última vez, sabemos quantos pixels você tem. Podemos calcular de um determinado momento para o anterior multiplicado pelo número de pixels que você tinha quantas bananas você deveria ter agora, e o front-end faz a mesma coisa. O front-end o simula, obtém as mesmas informações, exceto a mais recente, e depois cria um cronômetro que as calcula. 

Em teoria, o método get_near_balance não precisa retornar seu valor NEAR que está atualizado, pode apenas dizer que aqui está o total Near por Pepino e seu último NEAR total por Pepino e também seu último saldo NEAR, mas em vez disso é feito no nível do contrato. Digamos que não tivéssemos métodos de visualização pelos quais você não paga e apenas retorna e recupera um estado, então você teria que fazer essa lógica no front end ao invés de fazer aqui na memória.

Token.rs

A lógica final que precisamos fazer é como você recebe seus pepinos do Berry Club, e isso é feito usando transfer_with_vault do Berry Club. Discutimos anteriormente como o mapa 122 funciona.

Você passa o receiver_id, valor e carga útil. Possui um cheque assert_paid que apenas verifica se o depósito é positivo. Está dizendo “você precisa de pelo menos 1 yocto NEAR para evitar chamadas de teclas de acesso à função para evitar que uma interface do usuário do Berry Club maliciosa drene todas as suas bananas”. 

Ele pega o gás e então inicia uma chamada que coloca bananas em um cofre. Ele também inicia uma chamada para o receptor. Nesse caso, chamamos de contrato on-farm e ele passa ao remetente id uma quantidade de bananas, um vault id que é apenas um u64 sem JSON e uma carga útil que é uma string. No exemplo anterior, quando estávamos falando sobre o mapa 122, o payload era um binário de vec q8 em base64, porque era um payload serializado borsh. 

Durante a discussão, observei que, se você revisar esse argumento em uma carteira, não poderá ver a carga útil que deseja fazer.  É um enum com uma única opção chamada deposit_and_stake.

Agora, quando você faz uma chamada de função da interface do usuário do farm que irá para a carteira nos argumentos, a carga útil será como uma string adjacente dentro de uma string dizendo deposit and stake em vez de ser um zero codificado como base, em vez de ser um borsh versão serializada, é legível por humanos. 

Este contrato possui tipos de payload diferentes do Uniswap. Por exemplo, ele terá um payload dizendo quanto NEAR você deseja receber no máximo ou receber no mínimo. A UI maliciosa do Uniswap pode realmente substituir esse valor e, se você não o verificar no lado da carteira, poderá cair na tendência da frente.  Obtemos a conta usando get_mut_account, que obtém uma conta existente ou cria uma nova conta onde define todos os saldos como 0, mas o último numerador próximo por pepino é o global atual. Isso significa que você não cultivou nada e tem saldo zero de pepino. Ele toca de qualquer maneira, mesmo que não seja necessário, poderíamos ter evitado isso se mapeássemos e, em seguida, ele retorna o hash e a conta. 

A conta já está em dia. O que fazemos é primeiro aumentar o saldo total de pepinos e, em seguida, salvá-lo de volta ao estado da conta e também aumentar o saldo global de pepinos pela quantidade de pepinos depositados. Então, nós realmente não verificamos se o cofre continha pepinos, então confiamos que o chamador anterior, que é um contrato de banana, realmente colocou as bananas no cofre e retornamos a promessa desse método. É uma combinação estranha com uma única entrada porque a carga útil pode ser apenas um tipo agora. 

Chamamos de retirada_do_cofre, indicamos o valor que queremos retirar, que é o valor total, e então o chamamos de volta para o ID da conta do token de banana, que é um contrato do Berry Club. Mesmo assim, esse contrato ainda não recebeu bananas, mas não importa porque não usa bananas mesmo. Ele não precisa de bananas antes que possa prosseguir, já travado. Aumenta o equilíbrio total do pepino diluindo as ações. Agora, quando o take_my_near chegar, ele usará o novo saldo total de pepino. Agora vou dividir o número de compartilhamentos entre todos os participantes.

Conclusão

Essa é a visão geral dos contratos Berry Club, Berry Farm e token.rs. Obrigado pela leitura e boa sorte em seus futuros empreendimentos com a NEAR.

12
Scroll to Top