Automatização de Contratos com Truffle

Truffle é uma ferramenta essencial para compilação e implantação em lote de contratos inteligentes, eliminando a necessidade de deploy manual como no Remix, aumenatndo significativamente a eficiência.

Comendos principais:

  • truffle compile: gera arquivos JSON com bytecode e metadados
  • trufffle migrate/deploy: executa implantações
  • truffle exec: executa módulos JS no ambiente Truffle

Exemplo de script personalizado para coletar hashes de pares:

// contratos
// const UniswapV2Router02 = artifacts.require("UniswapV2Router02");
// const UniswapV2Library = artifacts.require("UniswapV2Library");
const Fábrica = artifacts.require("UniswapV2Factory");
const stripHexPrefix = require('strip-hex-prefix');

const enderecosFábrica = [
    "0xcA976B7714f0b48088cCC959C2843Fe752A33855",
    "0x7e65601AB5A90E2A04Ed4eAa0D91aa34082FdDd3",
    "0xbBF29Fc64b9D5A90FE3cc75c696C6e542DEcEC35",
    "0x0A4e77be8aC06F2B4A1f08Ce8006C0B6eC475920",
    "0x402576A5Ffa4d6A1E6Deb2C3B7082759E3Be686B"
];

let hashes = [];


const tokenWETH = "";

module.exports = async function (deployer, rede, contas) {

    for (var i = 0; i < enderecosFábrica.length; i++) {
        const instanciaFábrica = await Fábrica.at(enderecosFábrica[i]);
        const hash = await instanciaFábrica.pairCodeHash();
        console.log('hash', enderecosFábrica[i], hash);
        var conteudoSubstituido = "hex'" + stripHexPrefix(hash) + "'"
        hashes.push(conteudoSubstituido);
    }
    console.log(hashes);
};

Implantação da fábrica de swaps:

const editJsonFile = require("edit-json-file");
const stripHexPrefix = require('strip-hex-prefix');
const fs = require('fs');

var REGEX = /hex'(.{64,})/g;

function substituir(caminho, regex, conteudoSubstituido) {
    // carrega o arquivo
    var conteudoArquivo = fs.readFileSync(caminho, 'utf8');

    conteudoArquivo = conteudoArquivo.replace(regex, conteudoSubstituido);

    // sobrescreve o arquivo original, altere o caminho para testes
    fs.writeFileSync(caminho, conteudoArquivo);
}

// contratos
const Fábrica = artifacts.require("UniswapV2Factory");
const ERC20 = artifacts.require("MyERC20")
// contratos
const UniswapV2Router02 = artifacts.require("UniswapV2Router02");
const UniswapV2Library = artifacts.require("UniswapV2Library");
const SafeMath = artifacts.require("SafeMath");
const StakingRewards = artifacts.require("StakingRewards");


var ArquivoSaida = "./cList.json"
const json = require(ArquivoSaida)
const deadline = 1956981781

// implantação da fábrica de swaps
module.exports = async function(deployer, rede, contas) {
  for (ts = 0; ts < 5; ts++) {
    let mapa = new Map();
    var nomesERC20 = new Array()
    var listaERC20 = new Array()
    for (i = 0; i < 4; i++) {
      const nome = "Token" + i
      await deployer.deploy(ERC20, nome, 9000000000000000)
      const instanciaERC20 = await ERC20.deployed()
      listaERC20[i] = instanciaERC20.endereço
      mapa.set(nome, instanciaERC20.endereço)
    }

    await deployer.deploy(ERC20, "FakeWETH", 9000000000000000)
    const instanciaWETH = await ERC20.deployed()
    var enderecoWETH = instanciaWETH.endereço
    mapa.set("EndereçoWETH", enderecoWETH)


    await deployer.deploy(Fábrica, contas[0]);
    const instanciaFábrica = await Fábrica.deployed();
    const hash = await instanciaFábrica.pairCodeHash();
    var enderecoFábrica = instanciaFábrica.endereço
    var conteudoSubstituido = "hex'" + stripHexPrefix(hash) + "'"
    substituir(`${__dirname}/../contracts/swap/router/libraries/UniswapV2Library.sol`, REGEX, conteudoSubstituido);


    await deployer.deploy(UniswapV2Library);
    await deployer.link(UniswapV2Library, UniswapV2Router02);
    await deployer.deploy(SafeMath);
    await deployer.link(SafeMath, UniswapV2Router02);
    await deployer.deploy(UniswapV2Router02, enderecoFábrica, enderecoWETH);
    const instanciaRouter = await UniswapV2Router02.deployed();
    var enderecoRouter = instanciaRouter.endereço



    mapa.set("Fábrica", enderecoFábrica)
    mapa.set("Router", enderecoRouter)

    var valorDepósito = 4000000000000000

    for (i = 0; i < listaERC20.length; i++) {
      const instanciaERC20 = await ERC20.at(listaERC20[i])
      await instanciaERC20.approvar(enderecoRouter, valorDepósito)
    }

    await instanciaRouter.addLiquidity(listaERC20[0], listaERC20[1], 3000000000000000, 3000000000000000, 0, 0, contas[0], deadline)
    await instanciaRouter.addLiquidity(listaERC20[2], listaERC20[3], 3000000000000000, 3000000000000000, 0, 0, contas[0], deadline)
    var lp1 = await instanciaRouter.pairFor(listaERC20[0], listaERC20[1])
    var lp2 = await instanciaRouter.pairFor(listaERC20[2], listaERC20[3])

    mapa.set("LP1", lp1)
    mapa.set("LP2", lp2)


    await instanciaRouter.swapExactTokensForTokens(1000000000000000, 0, [listaERC20[0], listaERC20[1]], contas[0], deadline)
    await instanciaRouter.swapExactTokensForTokens(1000000000000000, 0, [listaERC20[2], listaERC20[3]], contas[0], deadline)


    // implantação de staking LP1
    await deployer.deploy(StakingRewards, contas[0], listaERC20[0], lp1, 63072000);
    var instanciaStaking = await StakingRewards.deployed();
    mapa.set("Staking1", instanciaStaking.endereço);


    var instanciaERC20 = await ERC20.at(lp1)
    var saldo = await instanciaERC20.saldoDe(contas[0])
    await instanciaERC20.approvar(instanciaStaking.endereço, saldo)
    await instanciaStaking.stake(saldo)



    instanciaERC20 = await ERC20.at(listaERC20[0])
    saldo = await instanciaERC20.saldoDe(contas[0])
    await instanciaERC20.transferir(instanciaStaking.endereço, saldo / 2)
    await instanciaStaking.notificarPremio(saldo / 2)
    await instanciaStaking.receberPremio()


    // implantação de staking LP2
    await deployer.deploy(StakingRewards, contas[0], listaERC20[2], lp2, 63072000);
    var instanciaStaking = await StakingRewards.deployed();
    mapa.set("Staking2", instanciaStaking.endereço);


    var instanciaERC20 = await ERC20.at(lp2)
    var saldo = await instanciaERC20.saldoDe(contas[0])
    await instanciaERC20.approvar(instanciaStaking.endereço, saldo)
    await instanciaStaking.stake(saldo)


    instanciaERC20 = await ERC20.at(listaERC20[2])
    saldo = await instanciaERC20.saldoDe(contas[0])
    await instanciaERC20.transferir(instanciaStaking.endereço, saldo / 2)
    await instanciaStaking.notificarPremio(saldo / 2)
    await instanciaStaking.receberPremio()


    json.push(Object.fromEntries(mapa))
    fs.writeFile(ArquivoSaida,JSON.stringify(json),(err)=>{
      if (err) console.log("err",err)
    })
    continue
    console.log("índice", ts)
  }
};

Implantação do router:

// contratos
const UniswapV2Router02 = artifacts.require("UniswapV2Router02");
const UniswapV2Library = artifacts.require("UniswapV2Library");
const SafeMath = artifacts.require("SafeMath");

const enderecoFábrica = "";
const enderecoWETH = "";

module.exports = async function (deployer, rede, contas) {
    if (enderecoFábrica === "") {
        throw new Error('endereço da fábrica não está definido');
    }

    await deployer.deploy(UniswapV2Library);
    await deployer.link(UniswapV2Library, UniswapV2Router02);
    await deployer.deploy(SafeMath);
    await deployer.link(SafeMath, UniswapV2Router02);
    await deployer.deploy(UniswapV2Router02, enderecoFábrica, enderecoWETH);
    const instanciaRouter = await UniswapV2Router02.deployed();
    console.log("endereço do router: " + instanciaRouter.endereço);
};

Como executar:

truffle exec seu_arquivo.js --network testnet

O método pairCodeHash() do contrato factory retorna type(c).creationCode que representa o bytecode gerado pelo Truffle (campo bytecode após compilação).

type(c).name: retorna o nome do contrato
type(c).creationCode: retorna o bytecode de criação
type(c).runtimeCode: retorna o bytecode de execução

Configuração do truffle-config.js

/**
 * Use este arquivo para configurar seu projeto Truffle. Ele contém configurações
 * comuns para diferentes redes e funcionalidades como migrações,
 * compilação e testes. Descomente os que precisar ou os modifique
 * para atender às necessidades do seu projeto.
 *
 * Mais informações sobre configuração estão disponíveis em:
 *
 * trufflesuite.com/docs/advanced/configuration
 *
 * Para implantar via Infura, será necessário um provedor de carteira (como @truffle/hdwallet-provider)
 * para assinar transações antes de enviá-las para um nó público remoto. Contas Infura
 * estão disponíveis gratuitamente em: infura.io/register.
 *
 * Também será necessário uma senha-mnemônica - a frase de 12 palavras que a carteira usa para gerar
 * pares de chaves públicas/privadas. Se você estiver publicando seu código no GitHub, certifique-se de carregar essa
 * frase de um arquivo que você tenha .gitignored para que não se torne acidentalmente público.
 */

const HDWalletProvider = require('@truffle/hdwallet-provider');

require('dotenv').config()
const MAINNET_URL = process.env.MAINNET_URL

module.exports = {
  /**
   * Redes definem como você se conecta ao cliente Ethereum e permite configurar os
   * valores padrão web3 usa para enviar transações. Se você não especificar uma, truffle
   * criará uma blockchain de desenvolvimento para você na porta 9545 quando você
   * executar `develop` ou `test`. Você pode pedir a um comando truffle para usar uma específica
   * rede da linha de comando, por exemplo
   *
   * $ truffle test --network <nome-da-rede>
   */

  redes: {
    // Útil para testes. O nome 'development' é especial - truffle o usa por padrão
    // se estiver definido aqui e nenhuma outra rede for especificada na linha de comando.
    // Você deve executar um cliente (como ganache-cli, geth ou parity) em uma aba separada
    // se usar esta rede e deve definir as opções host, port e network_id
    // abaixo para algum valor.
    //
    local: {
      host: "127.0.0.1", // Hostlocal (padrão: nenhum)
      porta: 8545, // Porta Ethereum padrão (padrão: nenhum)
      network_id: "8", // Qualquer rede (padrão: nenhum)
    },
    testnet: {
      //provedor: () => new HDWalletProvider("chave privada", "https://http-testnet.hecochain.com"),
      provedor: () => new HDWalletProvider("chave privada", "https://exchaintestrpc.okex.org"),
      network_id: 65,
      gas: 30000000,
      gasPrice: 1000000000,
      networkCheckTimeout: 100000000,
      timeoutBlocks: 2000,
      intervaloPolingImplantação: 80000
    },
    mainnet: {
      provedor: () => new HDWalletProvider(MNEMONIC, MAINNET_URL, 0, 2),
      network_id: 66,
    },
    development: {
      host: "127.0.0.1", // Hostlocal (padrão: nenhum)
      porta: 8545, // Porta Ethereum padrão (padrão: nenhum)
      network_id: "*", // Qualquer rede (padrão: nenhum)
    },
  },

  // Defina opções padrão do mocha aqui, use relatores especiais etc.
  mocha: {
    // timeout: 100000
  },

  // Configure seus compiladores
  compiladores: {
    solc: {
      versão: "^0.6.6", // Busca versão exata de solc-bin (padrão: versão do truffle)
      configurações: {
        otimizador: {
          ativado: true,
          runs: 1500
        }
      }
    }
  }
};

Tags: truffle solidity ethereum smart-contracts Blockchain

Publicado em 9-22 15:40