Desde a introdução da tecnologia de contratos inteligentes, o Solidity tem sido a linguagem de codificação escolhida pelos desenvolvedores de contratos inteligentes.
No entanto, se você é um desenvolvedor do Solidity, já sabe que ele tem desvantagens. Entre outras falhas, grandes preocupações de segurança podem surgir do simples manuseio incorreto de certos tipos de dados, e não há controles de acesso integrados.
Uma nova linguagem de contrato inteligente desenvolvida para o blockchain Flow, Cadence , aprende com as omissões do Solidity e resolve nativamente muitos de seus problemas inerentes. E se você já conhece o Solidity, é fácil de aprender!
Este artigo apresenta a linguagem de contratos inteligentes Cadence, detalha como ela melhora em relação ao Solidity e, em seguida, percorre uma comparação lado a lado de ambas as linguagens em alguns exemplos comuns de contratos inteligentes. No final, você deve estar confortável com o Cadence e pronto para começar no Flow!
Cadence é a linguagem de programação que alimenta o blockchain Flow, que foi originalmente criado por
Tudo isso significa que o Cadence é altamente otimizado para criação e gerenciamento de ativos digitais .
A inovação mais substancial introduzida pela Cadence é a sua
A cadência melhora em relação à solidez de várias maneiras. Vejamos três exemplos: pequenos erros de codificação, segurança e controle de acesso e implantação de contrato.
Alguns dos maiores problemas com o Solidity geralmente decorrem dos menores erros. Por exemplo, inicializar uma variável apenas com um valor padrão - embora conveniente às vezes - pode levar a resultados inesperados se essa variável não for alterada. E os tipos de dados de intervalo fixo podem levar a possíveis situações de estouro ou estouro, o que seria desastroso se esse tipo de dados representasse um valor monetário.
No Cadence, os valores das variáveis devem ser definidos na inicialização, removendo quaisquer resultados indesejados dos valores padrão. Além disso, os números inteiros em Cadence são verificados automaticamente quanto a condições de estouro ou estouro, enquanto você precisaria herdar a biblioteca matemática segura do OpenZeppelin ou usar uma versão superior a 0,8 com Solidity.
Quando se trata de segurança e controle de acesso, o Solidity exige que você crie modificadores personalizados ou herde outros contratos inteligentes baseados em segurança, mas também possui muitas funções que são públicas por padrão.
Com o modelo de segurança baseado em capacidade da Cadence, as contas podem executar apenas as funções às quais têm acesso. Isso significa que o Cadence tem controle de acesso fundamentalmente embutido no próprio idioma. Além disso, os métodos definidos em objetos de recurso no Cadence não podem ser suscetíveis a ataques de reentrância , algo que os desenvolvedores do Solidity devem estar cientes ao criar o fluxo de sua lógica.
Quando são encontrados problemas nos contratos inteligentes do Solidity, os desenvolvedores não conseguem corrigi-los sem implantar um contrato totalmente novo. E mesmo assim, o contrato vulnerável ainda existe. Os desenvolvedores devem garantir que sua base de usuários mude para o novo contrato.
Na Cadence, a capacidade de atualização do contrato inteligente é integrada e transparente. Quando o código é declarado seguro e final, o contrato pode se tornar imutável removendo as chaves do proprietário do contrato inteligente.
No geral, a Cadence é uma linguagem de contrato inteligente mais segura e protegida que deixa menos espaço para erros.
Agora vamos ver em detalhes as diferenças entre contratos inteligentes escritos em Solidity e Cadence. Passaremos por um simples contrato Hello World e, em seguida, por uma implementação NFT mais complicada.
Vamos começar com um clássico de todos os tempos. Todos nós escrevemos “Hello World” em vários idiomas, por isso é uma introdução fácil ao Cadence.
Vamos passar por isso passo a passo.
Primeiro, temos a definição do contrato. A diferença óbvia é que o contrato Cadence possui um modificador de controle de acesso: neste caso, pub. Este modificador garante que todos na rede Flow possam acessar o contrato, o comportamento padrão para contratos Solidity.
No entanto, em Cadence, também podemos definir o controle de acesso para access(account)
. Isso limita o acesso do contrato à conta que implantou esse contrato . Aqui já vemos uma grande diferença entre Flow e Ethereum. Não implantamos simplesmente contratos no blockchain do Flow; nós os implantamos em nosso armazenamento de conta. Na blockchain Flow, cada conta é inicializada com storage, onde recursos e estruturas podem ser armazenados. Esse armazenamento tem suas próprias permissões, o que nos permite um controle refinado sobre quem pode executar os métodos de nosso contrato.
A próxima linha define uma variável de string com escopo para nosso contrato. Ponto e vírgula são opcionais em Cadence, e uma palavra-chave let
é usada para definir a variável.
A cadência tem dois tipos de variáveis: mutáveis e imutáveis. Variáveis criadas com let
são imutáveis, ou também conhecidas como constantes; só podemos defini-los uma vez e eles não podem ser alterados durante a vigência do contrato. Definimos variáveis mutáveis (aquelas que podem ser alteradas) com a palavra-chave var
.
Nesse caso, definimos o valor da variável no método init, porque o Cadence garante que esse método seja chamado apenas uma vez para cada implantação de contrato.
O Cadence equivalente ao constructor
do Solidity é o método init
. Esse método é chamado exatamente uma vez — no momento em que um contrato é implantado.
Dentro do método init, definimos o valor para nossa variável de saudação. Enquanto o Solidity grava em variáveis de contrato por padrão, o Cadence grava em variáveis locais e requer que você use o auto-objeto para acessar as variáveis de contrato. Esta decisão protege contra você escrever acidentalmente em uma variável de contrato ao cometer um erro de digitação.
O segundo método do nosso contrato retorna a variável de saudação. Tanto no Cadence quanto no Solidity, temos que declarar o acesso para que o método seja público, e ambas as linguagens exigem que definamos o tipo de retorno. Neste caso, é uma string.
Mas o Solidity exige que sejamos mais de baixo nível aqui. Isso exige que digamos explicitamente onde a string está localizada. Também nos faz marcar as funções como view, para que não modifiquemos acidentalmente o estado da blockchain.
Cadence, por outro lado, não precisa desse controle de baixo nível, já que é fortemente tipado e estaticamente. Erros potenciais são detectados antes que o programa seja executado na cadeia, tornando toda a declaração do método mais legível ao remover palavras-chave redundantes.
Em seguida, vamos ver um contrato NFT básico de ambas as linguagens:
Como ambas as linguagens têm abordagens diferentes para este exemplo, vamos analisá-las separadamente: primeiro percorrendo o exemplo Solidity, depois Cadence.
No Solidity, um NFT é basicamente uma lista de IDs. Você deve acompanhar esses IDs dentro do contrato inteligente e incrementá-los manualmente para garantir a exclusividade. Solidity não sabe nada sobre NFTs ou sua singularidade. É apenas uma lista de IDs mapeados para seus proprietários, todos gerenciados manualmente dentro do contrato. Isso deixa espaço para erros se o incremento de ID for tratado incorretamente, resultando potencialmente em vários NFTs com IDs idênticos.
No exemplo, o NFT não tem nenhum dado adicional anexado, mas você pode adicionar outro ID de mapeamento a um URI. O contrato garante que cada NFT recém-criado seja mapeado para o endereço de um proprietário.
Este é um exemplo simples, claro. Normalmente, você precisaria estender várias interfaces para obter um contrato NFT remotamente seguro e recursos como metadados usados para anexar os conhecidos JPGs ao seu NFT, mas os mecanismos básicos são os mesmos.
Agora, vamos ver a versão do Cadence e como ela melhora este exemplo do Solidity.
O exemplo Cadence começa com um tipo de recurso chamado NFT
. Observe o símbolo @ na frente de NFT
? Este símbolo é necessário, pois garante que o uso e o comportamento dos tipos de recursos permaneçam explícitos.
Podemos criar instâncias a partir de um recurso e ele pode ter atributos como uma estrutura. A diferença de uma struct regular é que um recurso é um tipo especial que lida com a propriedade além dos dados que armazena.
Dentro do tipo de recurso NFT
, existe um campo id. O campo id
é um número inteiro, UInt64
, e é um id único dado a cada recurso NFT. Este id
será diferente para cada recurso NFT, o que significa que o recurso não pode ser duplicado ou combinado. Em seguida, o campo id
é inicializado usando a função init
.
Semelhante a como o verificador de empréstimo do Rust garante que apenas uma função pode modificar uma variável, o Cadence garante o mesmo para seus recursos.
Quando criamos um novo recurso, temos que movê-lo pelos locais de armazenamento. Nosso contrato inteligente não funcionará corretamente se deixarmos o recurso como está, então isso nos obriga a ser deliberados com os recursos e seus locais de armazenamento. Essa forma de controle também garante que os recursos nunca sejam perdidos ou excluídos acidentalmente; eles só podem estar em um local por vez.
Quando chamamos a função mint, ela criará uma nova instância do nosso recurso NFT
. Esta função retorna um recurso do tipo NFT
e recebe no campo id
, do recurso que foi definido anteriormente. A palavra-chave create
é um pouco como o operador new na programação orientada a objetos, criando um novo recurso. O <-
, ou move-operador, torna explícito que este recurso não está disponível na fonte depois que o chamamos.
A variável self.account
apontará para a conta que usamos como destino de implantação para nosso contrato. Como aprendemos antes: os contratos inteligentes não são implantados em um namespace global na rede Flow, mas em um armazenamento on-chain especial que pertence à sua conta. Portanto, o contrato inteligente sabe em qual conta foi implantado e pode usar essas informações em seus métodos.
Neste exemplo, usamos o método save da conta. Na função init
final, movemos o recurso para o primeiro argumento dos métodos de save
e informamos qual caminho dentro da conta deve armazenar nosso NFT.
Como nosso NFT é um recurso, nenhuma entidade da rede Flow pode copiá-lo; não precisamos acompanhar explicitamente sua singularidade.
Cadence é uma nova visão sobre linguagens de programação de contratos inteligentes, otimizada para criação e gerenciamento de ativos. É uma alternativa moderna que atenua as deficiências do Solidity por meio de meios como gerenciamento forçado de variáveis e recursos, segurança e controles de acesso em um nível fundamental e a capacidade de atualizar contratos inteligentes antes de torná-los imutáveis. A Cadence abre você para as possibilidades do ecossistema Flow e incorpora muitos recursos de linguagens como Rust.
Portanto, se você é um desenvolvedor que deseja escrever contratos inteligentes em uma linguagem fundamentalmente mais segura e protegida, o Cadence é uma excelente opção. Para saber mais, confira a Documentação do Cadence e o Flow Developer Portal .
Tenha um ótimo dia!