SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
28.11.2024

Lição: 165: Integrando IPFS com Contratos Inteligentes

Nesta aula, vamos explorar como integrar o Sistema de Arquivos Interplanetário (IPFS) com contratos inteligentes do Ethereum usando Solidity. O IPFS é uma rede de armazenamento descentralizada que nos permite armazenar arquivos de maneira distribuída, tornando-se uma excelente escolha para armazenar dados relacionados aos nossos contratos inteligentes.

O que é IPFS?

IPFS é um protocolo projetado para criar um método peer-to-peer de armazenamento e compartilhamento de hipermídia em um sistema de arquivos distribuído. Ele utiliza endereçamento de conteúdo para identificar exclusivamente cada arquivo, o que significa que os arquivos são acessíveis por meio de seu hash em vez de um local específico, proporcionando imutabilidade e descentralização.

Por que usar IPFS com Contratos Inteligentes?

Armazenar grandes quantidades de dados diretamente na blockchain do Ethereum pode ser caro devido aos custos de gás. O IPFS nos permite armazenar dados fora da blockchain, mantendo a integridade através do uso de hashes. Podemos armazenar o arquivo no IPFS e salvar o hash resultante na blockchain do Ethereum, reduzindo efetivamente os custos e melhorando a eficiência.

Pré-requisitos

  • Compreensão básica do Ethereum e contratos inteligentes
  • Configuração de um ambiente de desenvolvimento (ex.: Truffle, Hardhat) e IPFS
  • Familiaridade com JavaScript para construir a interface front-end

Configurando o IPFS

Antes de começarmos, certifique-se de que você tenha o IPFS instalado em sua máquina. Você pode usar um nó IPFS local ou um serviço como o Infura IPFS. Para um IPFS local:

  1. Instale o IPFS:
    npm install ipfs
  2. Inicie o seu daemon IPFS:
    ipfs daemon

Exemplo de Contrato Inteligente

Vamos criar um contrato inteligente simples que pode fazer upload de arquivos para o IPFS e armazenar o hash do arquivo na blockchain do Ethereum.

Contrato Solidity

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

contract ArmazenamentoDeArquivos {
    struct Arquivo {
        string ipfsHash;
        string descricao;
        address dono;
    }

    mapping(uint256 => Arquivo) public arquivos;
    uint256 public contadorDeArquivos;

    event ArquivoCarregado(uint256 idArquivo, string ipfsHash, string descricao, address dono);

    function carregarArquivo(string memory _ipfsHash, string memory _descricao) public {
        contadorDeArquivos++;
        arquivos[contadorDeArquivos] = Arquivo(_ipfsHash, _descricao, msg.sender);
        emit ArquivoCarregado(contadorDeArquivos, _ipfsHash, _descricao, msg.sender);
    }

    function obterArquivo(uint256 _idArquivo) public view returns (string memory, string memory, address) {
        Arquivo memory arquivo = arquivos[_idArquivo];
        return (arquivo.ipfsHash, arquivo.descricao, arquivo.dono);
    }
}

Explicação

  • Estrutura: Definimos uma estrutura Arquivo que conterá o hash do IPFS, uma descrição e o endereço do proprietário.
  • Mapping: Criamos um mapping chamado arquivos para armazenar os arquivos indexados por um ID.
  • Funções:
    • carregarArquivo: Esta função recebe o hash do IPFS e uma descrição como entrada. Ela incrementa o contador de arquivos, armazena os dados do arquivo e emite um evento.
    • obterArquivo: Esta função recupera as informações do arquivo pelo seu ID.

Interagindo com o Contrato Inteligente

Em seguida, vamos criar uma interface front-end simples usando JavaScript para interagir com nosso contrato inteligente e fazer upload de arquivos para o IPFS.

Código do Frontend

const IPFS = require('ipfs-core');
const Web3 = require('web3');
const contractABI = [ /* Array ABI da compilação */ ];
const contractAddress = '0xSeuEndereçoDeContratoAqui';

async function carregarArquivo(arquivo) {
    const ipfs = await IPFS.create();

    // Adiciona o arquivo ao IPFS
    const { path } = await ipfs.add(arquivo);
    const ipfsHash = path; // Obtém o hash do IPFS do arquivo carregado
    console.log(`Arquivo carregado no IPFS com hash: ${ipfsHash}`);

    // Envia o hash para o contrato inteligente do Ethereum
    const web3 = new Web3(window.ethereum);
    const contrato = new web3.eth.Contract(contractABI, contractAddress);
    const contas = await web3.eth.getAccounts();

    await contrato.methods.carregarArquivo(ipfsHash, arquivo.name).send({ from: contas[0] });
    console.log(`Hash do arquivo armazenado no contrato inteligente: ${ipfsHash}`);
}

// Manipulador de Upload de Arquivo HTML
document.getElementById('file-input').addEventListener('change', async (event) => {
    const arquivo = event.target.files[0];
    if (arquivo) {
        await carregarArquivo(arquivo);
    }
});

Explicação

  • Configuração do IPFS: Criamos uma instância do IPFS usando ipfs-core para fazer o upload de arquivos.
  • Adicionando Arquivos: O arquivo inserido é capturado e adicionado ao IPFS usando o método ipfs.add, gerando um hash único.
  • Interação com Ethereum: Iniciamos uma conexão com a blockchain do Ethereum usando o Web3, interagimos com nosso contrato inteligente e enviamos o hash do IPFS junto com o nome do arquivo.

Conclusão

Nesta aula, abordamos a integração do IPFS com contratos inteligentes do Ethereum. Ao utilizar o IPFS para armazenar arquivos fora da blockchain, conseguimos reduzir significativamente os custos associados ao armazenamento on-chain, enquanto garantimos a integridade e a acessibilidade desses arquivos. Você pode explorar ainda mais diversos casos de uso para essa integração, como armazenamento de conteúdo descentralizado, metadados de NFT e muito mais.

Boa codificação!

Video

Did you like this article? Rate it from 1 to 5:

Thank you for voting!