WEB3DEV

Cover image for Criando Contratos Inteligentes de NFT ERC721 na Blockchain Flow com a Linguagem de Programação Cadence
Fatima Lima
Fatima Lima

Posted on

Criando Contratos Inteligentes de NFT ERC721 na Blockchain Flow com a Linguagem de Programação Cadence

Um guia Abrangente com Exemplos

Image description

O mundo das blockchains foi revolucionado pelo surgimento de tokens não fungíveis (NFTs). Esses ativos digitais são exclusivos e não podem ser replicados, o que os torna ideais para casos de uso como arte, itens colecionáveis e itens de jogos. O padrão ERC721, desenvolvido pela Ethereum, é um dos padrões de NFT mais populares em uso atualmente. No entanto, as limitações da rede Ethereum, como altas taxas de gas e problemas de escalabilidade, levaram ao surgimento de plataformas alternativas de blockchain para o desenvolvimento de NFTs. Uma dessas plataformas é a blockchain Flow, que usa a linguagem de programação Cadence. Neste artigo, exploraremos como criar um contrato inteligente de NFT padrão ERC721 na blockchain Flow usando o Cadence, incluindo exemplos de código.

O que é um NFT ERC721?

Um NFT ERC721 é um ativo digital exclusivo que é armazenado na blockchain da Ethereum. Cada NFT é representado por um contrato inteligente que contém metadados e informações de propriedade. Diferentemente das criptomoedas tradicionais, como Bitcoin ou Ethereum, que são fungíveis e intercambiáveis, cada NFT ERC721 é único e não pode ser replicado. Essa exclusividade os torna ideais para casos de uso, como arte, itens colecionáveis e itens de jogos, em que o valor de um ativo é determinado por sua exclusividade.

Os contratos inteligentes ERC721 definem uma interface padrão que permite que os NFTs sejam criados, possuídos e negociados na rede Ethereum. O padrão ERC721 inclui funções como a criação de novos tokens, a transferência de propriedade de tokens e a consulta de metadados de tokens.

O que é a Blockchain Flow?

A blockchain Flow é uma plataforma de blockchain rápida, descentralizada e de fácil desenvolvimento, projetada para a criação de aplicativos e ativos digitais de alto desempenho. A Flow usa uma arquitetura exclusiva que separa as camadas de computação e armazenamento, permitindo o uso mais eficiente dos recursos e tempos de processamento de transações mais rápidos. A Flow também suporta contratos inteligentes escritos na linguagem de programação Cadence, que foi projetada para ser segura, fácil de usar e protegida.

Por que usar a Flow para o desenvolvimento de NFTs?

Embora a Ethereum seja a plataforma de blockchain mais popular para o desenvolvimento de NFTs, ela tem várias limitações que levaram ao surgimento de plataformas alternativas, como a Flow. Um dos principais problemas da Ethereum são as altas taxas de gas necessárias para executar transações na rede. As taxas de gas são pagas na moeda nativa da Ethereum, o Ether, e podem variar muito dependendo do congestionamento da rede e da complexidade da transação. Isso pode encarecer a criação, o comércio e a transferência de NFTs na rede Ethereum.

A Flow, por outro lado, tem taxas de transação mais baixas e tempos de processamento de transação mais rápidos do que a Ethereum. Isso a torna mais adequada para casos de uso como jogos, em que são necessários altos volumes de transações. Além disso, a arquitetura da Flow foi projetada para ser amigável ao desenvolvedor, com foco na facilidade de uso e na segurança.

Criação de um contrato inteligente de NFT ERC721 na Flow

Para criar um contrato inteligente de NFT ERC721 na blockchain Flow, usaremos o Cadence. O Cadence é uma linguagem de programação segura, fácil de usar e projetada especificamente para o desenvolvimento de blockchains. O Cadence é construído sobre a blockchain Flow, o que significa que os desenvolvedores podem aproveitar a arquitetura e os recursos exclusivos da Flow.

O primeiro passo na criação de um contrato inteligente de NFT ERC721 na Flow é definir a interface do contrato. A interface do contrato define as funções e propriedades que serão expostas ao mundo exterior. Em nosso caso, definiremos a interface padrão do ERC721, que inclui funções como a criação de novos tokens, a transferência de propriedade de tokens e a consulta de metadados de tokens.

Aqui está um exemplo de uma interface de contrato ERC721 no Cadence:

pub contract ERC721 {
 // Evento que é gerado quando um novo token é cunhado
 pub event Minted(tokenID: UInt64, owner: Address)

 // Evento que é gerado quando um token é transferido
 pub event Transferred(tokenID: UInt64, from: Address, to: Address)

// Função para cunhar um novo token
pub fun mint(to: Address, tokenID: UInt64) {
// A Fazer: Implementar a função mint
}

// Função para obter o proprietário de um token
pub fun ownerOf(tokenID: UInt64): Address? {
// A fazer: Implementar a função ownerOf
return nil
}

// Função para transferir o proprietário de um token
pub fun transfer(from: Address, to: Address, tokenID: UInt64) {
// A fazer: Implementar a função transfer
}
}
Enter fullscreen mode Exit fullscreen mode

Essa interface define as funções e os eventos necessários para um contrato inteligente ERC721. Definimos a função mint para cunhar novos tokens, a função ownerOf para consultar o proprietário de um token e a função transfer para transferir a propriedade de um token.

Agora que definimos a interface do nosso contrato ERC721, podemos começar a implementar a lógica do contrato. Em nossa implementação, usaremos um dicionário para armazenar as informações de propriedade de cada token. A chave do dicionário será o ID do token e o valor será o endereço do proprietário.

Aqui está um exemplo de implementação de um contrato inteligente ERC721 no Cadence:

pub contract MyNFT: ERC721 {
 // Dicionário para armazenar as informações de propriedade de cada token
 pub var tokenOwner: {UInt64: Address}

 // Função para cunhar um novo token
 pub fun mint(to: Address, tokenID: UInt64) {
   // Verificar se o token ainda não foi cunhado
   if (tokenOwner[tokenID] != nil) {
     panic("Token already exists")
   }

   // Cunhar o novo token e definir o proprietário para o endereço especificado
   tokenOwner[tokenID] = to

   //Gerar o evento Minted
   emit Minted(tokenID: tokenID, owner: to)
 }

 // Função para obter o proprietário de um token
 pub fun ownerOf(tokenID: UInt64): Address? {
   // Retornar o endereço do proprietário para o ID de token especificado
   return tokenOwner[tokenID]
 }

 // Função para transferir a propriedade de um token
 pub fun transfer(from: Address, to: Address, tokenID: UInt64) {
   // Verificar se o remetente é o proprietário atual do token
   if (tokenOwner[tokenID] != from) {
     panic("Sender is not the owner of the token")
   }

   // Transferir a propriedade do token para o novo endereço
   tokenOwner[tokenID] = to

   // Gerar o evento Transferred
   emit Transferred(tokenID: tokenID, from: from, to: to)
 }
}
Enter fullscreen mode Exit fullscreen mode

Essa implementação define um contrato chamado MyNFT que implementa a interface ERC721. Definimos o dicionário tokenOwner para armazenar as informações de propriedade de cada token e implementamos as funções mint, ownerOf e transfer.

A função mintverifica se o token ainda não foi cunhado e, em seguida, cunha o novo token definindo o proprietário como o endereço especificado. Também geramos o evento Minted para notificar aos observadores externos que um novo token foi cunhado.

A função ownerOf simplesmente retorna o endereço do proprietário para o ID de token especificado, pesquisando o valor no dicionário tokenOwner.

A função transfer verifica se o remetente é o proprietário atual do token e, em seguida, transfere a propriedade do token para o novo endereço, atualizando o valor no dicionário tokenOwner. Também geramos o evento Transferred para notificar aos observadores externos que a propriedade de um token foi transferida.

Agora podemos implementar este contrato inteligente ERC721 na blockchain Flow usando a CLI da Flow. Veja a seguir os passos para implementar o contrato:

  1. Instale a CLI da Flow seguindo as instruções da documentação oficial da Flow.
  2. Crie um novo diretório para seu projeto e navegue até ele em seu terminal.
  3. Inicialize um novo projeto Flow, executando flow init em seu terminal. Isso criará um novo arquivo flow.json no diretório do seu projeto.
  4. Crie um novo arquivo Cadence no diretório do seu projeto, chamado MyNFT.cdc e cole a implementação do contrato inteligente ERC721 que acabamos de criar.
  5. Implante o contrato executando o seguinte comando em seu terminal: flow project deploy --network=emulator. Isso implantará o contrato na rede do emulador da Flow.
  6. Depois que o contrato for implantado, você poderá interagir com ele usando a CLI da Flow. Aqui estão alguns exemplos de como usar o contrato:
  7. Cunhar um novo token:
flow transactions send ./transactions/mint.cdc
Enter fullscreen mode Exit fullscreen mode

Esse comando enviará uma transação ao contrato para cunhar um novo token.

  1. Consultar o proprietário de um token:
flow scripts execute ./scripts/ownerOf.cdc
Enter fullscreen mode Exit fullscreen mode

Esse comando executará um script para consultar o proprietário de um token.

  1. Transferir a propriedade de um token:
flow transactions send ./transactions/transfer.cdc
Enter fullscreen mode Exit fullscreen mode

Esse comando enviará uma transação ao contrato para transferir a propriedade de um token.

Para executar transações e scripts na blockchain Flow, precisamos escrever um código Cadence que interaja com o contrato. Aqui está um exemplo de como fazer isso no Cadence:

import FungibleToken from "./FungibleToken.cdc"
import MyNFT from "./MyNFT.cdc"

// Endereço do contrato
let contractAddress: Address = 0x01

// Endereço do proprietário do token
let ownerAddress: Address = 0x02

// Endereço do destinatário do token
let recipientAddress: Address = 0x03

// ID do token a ser cunhado
let tokenID: UInt64 = 1

// Quantidade de tokens a ser transferida
let amount: UInt64 = 10

// Instanciar o contrato FungibleToken
let tokenContract = getAccount(contractAddress)
 .getContract<FungibleToken.FungibleToken>("FungibleToken")

// Instanciar o contrato MyNFT
let nftContract = getAccount(contractAddress)
 .getContract<MyNFT.MyNFT>("MyNFT")

// Cunhar um novo token
nftContract.mint(to: ownerAddress, tokenID: tokenID)

// Obter o proprietário de um token
let owner = nftContract.ownerOf(tokenID: tokenID)

// Transferir a propriedade de um token
nftContract.transfer(from: ownerAddress, to: recipientAddress, tokenID: tokenID)

// Transferir tokens
tokenContract.transfer(from: ownerAddress, to: recipientAddress, amount: amount)
Enter fullscreen mode Exit fullscreen mode

Nesse exemplo, estamos importando os contratos FungibleToken e MyNFT que criamos anteriormente. Em seguida, estamos instanciando esses contratos usando a função getAccount e chamando suas funções para interagir com eles.

Primeiro, criamos um novo token chamando a função mint no contrato MyNT. Em seguida, obtemos o proprietário do token chamando a função ownerOf no contrato MyNFT.

Em seguida, transferimos a propriedade do token chamando a função transfer no contrato MyNFT. Finalmente, transferimos alguns tokens FLOW, chamando a função transfer no contrato FungibleToken.

Concluindo, os tokens ERC721 são uma ferramenta poderosa para criar ativos digitais exclusivos e indivisíveis na blockchain. Com o uso de contratos inteligentes, podemos criar tokens ERC721 com propriedades e comportamentos específicos, como tokens não fungíveis, transferíveis e apropriáveis. A blockchain Flow e a linguagem de programação Cadence oferecem um ambiente ideal para criar e implantar contratos ERC721, com um alto grau de segurança e desempenho.

Aqui está a implementação final do contrato inteligente ERC721 em Cadence:

import FlowToken from 0xFLOWTOKENADDRESS
import FungibleToken from "./FungibleToken.cdc"

pub contract MyNFT: FungibleToken {

   // Evento gerado quando um novo token é cunhado
   pub event Mint(tokenID: UInt64, to: Address)

   // Evento gerado quando a propriedade de um token é transferida
   pub event Transfer(tokenID: UInt64, from: Address, to: Address)

   // Armazenamento de informações do proprietário do token
   pub var owners: {UInt64: Address}

   // Armazenamento do fornecimento total de tokens
   pub var totalSupply: UInt64

   // Inicializar o contrato com um mapeamento de proprietários vazio
   init() {
       self.owners = {}
       self.totalSupply = 0
   }

   // Criar um novo token e atribuir a propriedade ao endereço especificado
   pub fun mint(to: Address, tokenID: UInt64) {
       // Certificar-se de que o ID do token ainda não pertence a nenhum usuário
       assert(!self.exists(tokenID), message: "Token already exists")

       // Atribuir propriedade ao endereço especificado
       self.owners[tokenID] = to

       // Aumentar o suprimento total de tokens
       self.totalSupply += 1

       // Gerar um evento Mint
       emit Mint(tokenID: tokenID, to: to)
   }

   // Verificar se um token existe
   pub fun exists(tokenID: UInt64): Bool {
       return self.owners[tokenID] != nil
   }

   // Obter o proprietário de um token
   pub fun ownerOf(tokenID: UInt64): Address? {
       return self.owners[tokenID]
   }

   // Transferir a propriedade de um token de um endereço para outro
   pub fun transfer(from: Address, to: Address, tokenID: UInt64) {
       // Certificar-se de que o remetente é o proprietário atual do token
       assert(self.ownerOf(tokenID) == from, message: "Sender does not own token")

       // Atribuir propriedade ao novo endereço
       self.owners[tokenID] = to

       // Gerar um evento Transfer
       emit Transfer(tokenID: tokenID, from: from, to: to)
   }

   // Substituir a implementação do FungibleToken para evitar que os tokens sejam transferidos
   pub fun transfer(from: Address, to: Address, amount: UFix64) {
       panic("ERC721 tokens are not transferrable with FungibleToken")
   }

   // Substituir a implementação do FungibleToken para evitar que os tokens sejam aprovados para transferência
   pub fun approve(to: Address, amount: UFix64) {
       panic("ERC721 tokens are not approvable with FungibleToken")
   }

   // Substituir a implementação do FungibleToken para evitar que os tokens sejam transferidos de um endereço para outro
   pub fun transferFrom(from: Address, to: Address, amount: UFix64) {
       panic("ERC721 tokens are not transferrable with FungibleToken")
   }

}
Enter fullscreen mode Exit fullscreen mode

Espero que este artigo tenha sido útil para entender como criar e implementar contratos inteligentes ERC721 na blockchain Flow, usando a linguagem de programação Cadence. Seguindo os exemplos e orientações apresentados aqui, você poderá criar seus próprios ativos digitais exclusivos e interagir com eles na blockchain.

É importante observar que a implementação dos tokens ERC721 pode variar dependendo do caso de uso específico e dos requisitos do projeto. Por exemplo, alguns projetos podem exigir funcionalidades adicionais, como a capacidade de queimar tokens ou adicionar metadados a cada token. Esses recursos podem ser adicionados ao contrato modificando a implementação ou criando funções adicionais.

Além disso, é importante testar exaustivamente seus contratos inteligentes antes de implantá-los na blockchain. Isso pode ser feito por meio da criação de testes automatizados que abranjam todos os cenários e casos extremos possíveis. A blockchain Flow oferece uma estrutura de teste robusta que pode ser usada para testar seus contratos antes de implementá-los na rede principal.

Em resumo, os tokens ERC721 são uma ferramenta poderosa para a criação de ativos digitais exclusivos e indivisíveis na blockchain. A blockchain Flow e a linguagem de programação Cadence oferecem um ambiente ideal para criar e implantar contratos ERC721, com alto grau de segurança e desempenho. Seguindo as diretrizes e os exemplos apresentados neste artigo, você poderá criar seus próprios tokens ERC721 e interagir com eles na blockchain.

Esse artigo foi escrito por Lea Lobanov e traduzido por Fátima Lima. O original pode ser lido aqui.

Top comments (0)