Dicas de desenvolvimento de contratos: experiências aprendidas com o código do Uniswap
Recentemente, ao escrever um tutorial de desenvolvimento de uma exchange descentralizada, consultei a implementação do Uniswap V3 e aprendi muitos pontos interessantes. Como um novato que tenta desenvolver contratos DeFi pela primeira vez, essas dicas devem ser muito úteis para outros iniciantes que desejam aprender sobre desenvolvimento de contratos.
Endereço de implantação de contrato previsível
Normalmente, o endereço obtido ao implantar um contrato parece aleatório e é difícil de prever. No entanto, em certas situações, precisamos inferir o endereço do contrato através de informações relacionadas à troca, como determinar permissões de transação ou obter o endereço do pool.
O Uniswap utiliza o método CREATE2 para criar contratos, adicionando o parâmetro salt para tornar o endereço previsível. A nova lógica de geração de endereço é: hash("0xFF", endereço do criador, salt, initcode). Este método torna os endereços de contrato previsíveis, o que é muito prático.
Uso inteligente de funções de callback
Nos contratos em Solidity, é possível chamar métodos entre si. Em certos cenários, A chama o método de B, e B faz uma chamada de retorno para A no método chamado; esse padrão é muito útil.
A negociação de swap da Uniswap utiliza um mecanismo de callback. O método swap do UniswapV3Pool chama o swapCallback, passando a quantidade real de Tokens necessários. O chamador deve transferir os Tokens dentro do callback, garantindo a execução completa e a segurança do método swap, sem a necessidade de registros complicados de variáveis.
Usar exceções para passar informações, usar try catch para realizar estimativas de transação
No contrato Quoter da Uniswap, o método swap do UniswapV3Pool é executado dentro de um bloco try catch. Isso é feito para simular a troca e estimar os tokens necessários para a transação, mas a estimativa não realiza a troca real dos tokens, portanto, resultará em um erro.
Uniswap lança erros especiais na função de callback e, em seguida, captura esses erros para extrair as informações necessárias. Essa abordagem pode parecer uma solução alternativa, mas é muito prática, pois não requer a modificação do método swap especificamente para estimar a demanda, tornando a lógica mais simples.
Resolver problemas de precisão com grandes números
O código do Uniswap envolve muitos cálculos, como calcular a quantidade de Tokens a serem trocados com base no preço atual e na liquidez. Para evitar a perda de precisão durante a operação de divisão, o processo de cálculo frequentemente usa a operação "<< FixedPoint96.RESOLUTION", que equivale a deslocar para a esquerda 96 bits, ou seja, multiplicar por 2^96.
Deslocar à esquerda e depois fazer a divisão pode garantir a precisão em transações normais sem estouros. Embora teoricamente ainda haja uma pequena perda de precisão, já é aceitável.
Calcular os lucros usando o modo Share
Uniswap precisa registrar os ganhos de taxa dos provedores de liquidez (. É evidente que não se pode registrar a taxa de cada LP a cada transação, pois isso consumiria uma grande quantidade de Gas.
A solução é registrar feeGrowthInside0LastX128 e feeGrowthInside1LastX128 na estrutura Position, representando a taxa de comissão que cada unidade de liquidez deve receber na última retirada de comissão de cada posição.
Basta registrar a taxa total de transação e a taxa de transação alocada por unidade de liquidez. Ao retirar LP, a taxa de transação que pode ser retirada pode ser calculada com base na liquidez detida. É semelhante a possuir ações, onde ao retirar os lucros, só é necessário saber o lucro histórico por ação e o lucro da última retirada.
![Série para iniciantes em Web3: Dicas de desenvolvimento de contratos que aprendi com o código do Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
Nem todas as informações precisam ser obtidas na cadeia
O armazenamento em cadeia é relativamente caro, nem todas as informações precisam estar na cadeia ou serem obtidas da cadeia. Por exemplo, muitas das interfaces chamadas pelo front-end do Uniswap são interfaces tradicionais da Web2.
A lista de pools de negociação, informações, etc. podem ser armazenadas em um banco de dados comum, algumas precisam ser sincronizadas periodicamente da cadeia, mas não é necessário chamar em tempo real a cadeia ou a interface RPC do nó para obter dados.
Muitos fornecedores de RPC de blockchain também oferecem interfaces avançadas, que permitem obter certos dados de forma mais rápida e barata. Essas interfaces geralmente utilizam cache para melhorar o desempenho e a eficiência.
Claro, as transações chave ainda são realizadas na cadeia.
Aprender a dividir contratos e utilizar contratos padrão existentes
Um projeto pode conter vários contratos realmente implementados. Mesmo que apenas um contrato seja implementado, o código pode ser mantido dividindo-se em vários contratos através da herança.
O contrato NonfungiblePositionManager da Uniswap herda vários contratos. O contrato ERC721Permit utiliza diretamente a implementação ERC721 da OpenZeppelin, o que facilita a gestão de posições com NFTs e melhora a eficiência do desenvolvimento.
Resumo
Desenvolver manualmente uma versão simples de uma troca descentralizada permitirá que você compreenda mais profundamente a implementação do Uniswap e aprenda mais sobre os pontos de conhecimento em projetos práticos. O aprendizado teórico é, sem dúvida, importante, mas a experiência prática é ainda mais valiosa. Espero que essas pequenas dicas possam ajudar no seu caminho de desenvolvimento de contratos.
![Web3 Novato: Dicas de desenvolvimento de contratos que aprendi com o código Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(
Esta página pode conter conteúdo de terceiros, que é fornecido apenas para fins informativos (não para representações/garantias) e não deve ser considerada como um endosso de suas opiniões pela Gate nem como aconselhamento financeiro ou profissional. Consulte a Isenção de responsabilidade para obter detalhes.
19 Curtidas
Recompensa
19
7
Compartilhar
Comentário
0/400
GasWaster
· 07-16 11:49
Quem estuda contratos tem que olhar
Ver originalResponder0
MissedAirdropAgain
· 07-16 07:39
Aprender o contrato não dá mais tempo...
Ver originalResponder0
YieldWhisperer
· 07-14 20:20
vi este padrão exato na dyydx em 2020... nada de novo, para ser honesto
Ver originalResponder0
MEVictim
· 07-14 20:18
Esses conhecimentos básicos de verificação de pedidos realmente são úteis?
Análise do código Uniswap: 7 dicas para desenvolvimento de contratos inteligentes
Dicas de desenvolvimento de contratos: experiências aprendidas com o código do Uniswap
Recentemente, ao escrever um tutorial de desenvolvimento de uma exchange descentralizada, consultei a implementação do Uniswap V3 e aprendi muitos pontos interessantes. Como um novato que tenta desenvolver contratos DeFi pela primeira vez, essas dicas devem ser muito úteis para outros iniciantes que desejam aprender sobre desenvolvimento de contratos.
Endereço de implantação de contrato previsível
Normalmente, o endereço obtido ao implantar um contrato parece aleatório e é difícil de prever. No entanto, em certas situações, precisamos inferir o endereço do contrato através de informações relacionadas à troca, como determinar permissões de transação ou obter o endereço do pool.
O Uniswap utiliza o método CREATE2 para criar contratos, adicionando o parâmetro salt para tornar o endereço previsível. A nova lógica de geração de endereço é: hash("0xFF", endereço do criador, salt, initcode). Este método torna os endereços de contrato previsíveis, o que é muito prático.
Uso inteligente de funções de callback
Nos contratos em Solidity, é possível chamar métodos entre si. Em certos cenários, A chama o método de B, e B faz uma chamada de retorno para A no método chamado; esse padrão é muito útil.
A negociação de swap da Uniswap utiliza um mecanismo de callback. O método swap do UniswapV3Pool chama o swapCallback, passando a quantidade real de Tokens necessários. O chamador deve transferir os Tokens dentro do callback, garantindo a execução completa e a segurança do método swap, sem a necessidade de registros complicados de variáveis.
Usar exceções para passar informações, usar try catch para realizar estimativas de transação
No contrato Quoter da Uniswap, o método swap do UniswapV3Pool é executado dentro de um bloco try catch. Isso é feito para simular a troca e estimar os tokens necessários para a transação, mas a estimativa não realiza a troca real dos tokens, portanto, resultará em um erro.
Uniswap lança erros especiais na função de callback e, em seguida, captura esses erros para extrair as informações necessárias. Essa abordagem pode parecer uma solução alternativa, mas é muito prática, pois não requer a modificação do método swap especificamente para estimar a demanda, tornando a lógica mais simples.
Resolver problemas de precisão com grandes números
O código do Uniswap envolve muitos cálculos, como calcular a quantidade de Tokens a serem trocados com base no preço atual e na liquidez. Para evitar a perda de precisão durante a operação de divisão, o processo de cálculo frequentemente usa a operação "<< FixedPoint96.RESOLUTION", que equivale a deslocar para a esquerda 96 bits, ou seja, multiplicar por 2^96.
Deslocar à esquerda e depois fazer a divisão pode garantir a precisão em transações normais sem estouros. Embora teoricamente ainda haja uma pequena perda de precisão, já é aceitável.
Calcular os lucros usando o modo Share
Uniswap precisa registrar os ganhos de taxa dos provedores de liquidez (. É evidente que não se pode registrar a taxa de cada LP a cada transação, pois isso consumiria uma grande quantidade de Gas.
A solução é registrar feeGrowthInside0LastX128 e feeGrowthInside1LastX128 na estrutura Position, representando a taxa de comissão que cada unidade de liquidez deve receber na última retirada de comissão de cada posição.
Basta registrar a taxa total de transação e a taxa de transação alocada por unidade de liquidez. Ao retirar LP, a taxa de transação que pode ser retirada pode ser calculada com base na liquidez detida. É semelhante a possuir ações, onde ao retirar os lucros, só é necessário saber o lucro histórico por ação e o lucro da última retirada.
![Série para iniciantes em Web3: Dicas de desenvolvimento de contratos que aprendi com o código do Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
Nem todas as informações precisam ser obtidas na cadeia
O armazenamento em cadeia é relativamente caro, nem todas as informações precisam estar na cadeia ou serem obtidas da cadeia. Por exemplo, muitas das interfaces chamadas pelo front-end do Uniswap são interfaces tradicionais da Web2.
A lista de pools de negociação, informações, etc. podem ser armazenadas em um banco de dados comum, algumas precisam ser sincronizadas periodicamente da cadeia, mas não é necessário chamar em tempo real a cadeia ou a interface RPC do nó para obter dados.
Muitos fornecedores de RPC de blockchain também oferecem interfaces avançadas, que permitem obter certos dados de forma mais rápida e barata. Essas interfaces geralmente utilizam cache para melhorar o desempenho e a eficiência.
Claro, as transações chave ainda são realizadas na cadeia.
Aprender a dividir contratos e utilizar contratos padrão existentes
Um projeto pode conter vários contratos realmente implementados. Mesmo que apenas um contrato seja implementado, o código pode ser mantido dividindo-se em vários contratos através da herança.
O contrato NonfungiblePositionManager da Uniswap herda vários contratos. O contrato ERC721Permit utiliza diretamente a implementação ERC721 da OpenZeppelin, o que facilita a gestão de posições com NFTs e melhora a eficiência do desenvolvimento.
Resumo
Desenvolver manualmente uma versão simples de uma troca descentralizada permitirá que você compreenda mais profundamente a implementação do Uniswap e aprenda mais sobre os pontos de conhecimento em projetos práticos. O aprendizado teórico é, sem dúvida, importante, mas a experiência prática é ainda mais valiosa. Espero que essas pequenas dicas possam ajudar no seu caminho de desenvolvimento de contratos.
![Web3 Novato: Dicas de desenvolvimento de contratos que aprendi com o código Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(