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:
- Instale o IPFS:
npm install ipfs
- 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!