WEB3DEV

Cover image for Como Codificar Uma Fantástica Função de Pagamento em Lote Com o Solidity: Uma Técnica Que Deve Ser Conhecida
Panegali
Panegali

Posted on • Atualizado em

Como Codificar Uma Fantástica Função de Pagamento em Lote Com o Solidity: Uma Técnica Que Deve Ser Conhecida

Introdução

Você está pensando em se tornar um desenvolvedor blockchain de sucesso? Então este tutorial é para você.

A demanda global por desenvolvedores de blockchain está fora de alcance agora. Empresas de tecnologia e startups estão procurando desenvolvedores de blockchain que possam ajudá-los a construir tecnologias incríveis nesse espaço.

Mas uma das habilidades essenciais que você precisará para conseguir estes empregos bem remunerados é aprender solidity e o processamento de pagamentos de contratos inteligentes.

A propósito, se você estiver procurando por um tutor pessoal para acelerar o desenvolvimento da web3, marque uma sessão comigo.

Se você está entusiasmado como eu, vamos saltar para este tutorial…

Confira meu canal no Youtube para tutoriais gratuitos da web3 agora.

Por que você deve dominar o processamento de pagamentos em lote no Solidity

Solidity é uma linguagem de programação específica para lidar com o processamento de pagamentos entre contas. Esta é uma característica rara entre as linguagens de programação na web. O Solidity foi construído com o intuito de gerenciar transações com a moeda digital Ethereum eliminando a necessidade de intermediários e grandes corporações.

Com a programação de contrato inteligente Solidity, você não precisa de um banco ou de qualquer senhora do banco para processar seu pagamento, todos os seus pagamentos serão processados ​​na rede.

Mas o simples fato de que o solidity lhe dá o poder de tornar as transações digitais mais rápidas, seguras e em grande escala não significa que você possa fazer isso perfeitamente sem aprender.

Na medida em que essa rede financeira nos proporcionou uma forma de movimentar dinheiro entre pontos de forma rápida, segura e ilimitada, também atraiu os olhares predatórios de ladrões conhecidos como (hackers).

Sim, eles observam a fraqueza em seu sistema especificamente como o dinheiro é movido em seu contrato inteligente. Quando eles encontrarem uma maneira de explorar essa fraqueza, eles saqueiam seu sistema e tornarão seu negócio disfuncional.

Para que isso não aconteça, você deve entender como processar pagamentos em lote com seus contratos inteligentes.

Exemplo de contrato inteligente de pagamento em lote

Quero ilustrar isso para você por meio de um exemplo de contrato inteligente que criei chamado Payroll (Folha de Pagamento). Abaixo está o código completo do contrato inteligente…

//SPDX-Identificador da licença: MIT
pragma solidity >=0.7.0 <0.9.0;

contract Payroll {
    address public companyAcc;
    uint256 public companyBal;
    uint256 public totalWorkers = 0;
    uint256 public totalSalary = 0;
    uint256 public totalPayment = 0;

    mapping(address => bool) isWorker;

    event Paid(
        uint256 id,
        address from,
        uint256 totalSalary,
        uint256 timestamp
    );

    struct PaymentStruct {
        uint256 id;
        address worker;
        uint256 salary;
        uint256 timestamp;
    }

    PaymentStruct[] employees;

    modifier ownerOnly(){
        require(msg.sender == companyAcc, "Proprietário reservado apenas");
        _;
    }

    constructor() {
        companyAcc = msg.sender;
    }

    function addWorker(
        address worker,
        uint256 salary
    ) external ownerOnly returns (bool) {
        require(salary > 0 ether, "Salário não pode ser zero!");
        require(!isWorker[worker], "Registro já existente!");

        totalWorkers++;
        totalSalary += salary;
        isWorker[worker] = true;

        employees.push(
            PaymentStruct(
                totalWorkers,
                worker,
                salary,
                block.timestamp
            )
        );

        return true;
    }

    function payWorkers() payable external ownerOnly returns (bool) {
        require(msg.value >= totalSalary, "Ethers pequenos demais");
        require(totalSalary <= companyBal, "Balanço insuficiente");

        for(uint i = 0; i < employees.length; i++) {
            payTo(employees[i].worker, employees[i].salary);
        }

        totalPayment++;
        companyBal -= msg.value;

        emit Paid(
            totalPayment,
            companyAcc,
            totalSalary,
            block.timestamp
        );

        return true;
    }

    function fundCompanyAcc() payable external returns (bool) {
        require(companyAcc != msg.sender, "Você não pode se autofinanciar!");
        payTo(companyAcc, msg.value);
        companyBal += msg.value;
        return true;
    }

    function getWorkers() external view returns (PaymentStruct[] memory) {
        return employees;
    }

    function payTo(
        address to, 
        uint256 amount
    ) internal returns (bool) {
        (bool success,) = payable(to).call{value: amount}("");
        require(success, "O pagamento falhou");
        return true;
    }
}
Enter fullscreen mode Exit fullscreen mode

Ótimo, acima está um contrato inteligente para pagar os funcionários de uma empresa de acordo com seus salários. Vamos dar uma olhada em como realizamos esse contrato inteligente passo a passo.

Passo 1:

Nesta primeira etapa, estamos configurando nossa estrutura de contrato inteligente. Estamos usando o identificador de licença MIT e o intervalo do compilador de 0.7.0 a 0.9.0. Em seguida, definimos o contrato inteligente com um nome chamado Payroll.

//SPDX-Identificador da licença: MIT
pragma solidity >=0.7.0 <0.9.0;
contract Payroll {
// Os códigos vão aqui...
}
Enter fullscreen mode Exit fullscreen mode

Passo 2:

Aqui estamos definindo as variáveis ​​de estado essenciais para nosso contrato inteligente. O companyAcc especifica a conta ou endereço de implantação. CompanyBal detém todo o fundo que entra na empresa. Em seguida, especificamos algumas variáveis ​​para acompanhar o total de trabalhadores, salários e pagamentos em nosso contrato inteligente.

address public companyAcc; // Conta do proprietário
uint256 public companyBal; // Fundo das empresas
uint256 public totalWorkers = 0;
uint256 public totalSalary = 0;
uint256 public totalPayment = 0;
mapping(address => bool) isWorker; // Identifica os trabalhadores

Enter fullscreen mode Exit fullscreen mode

Etapa 3:

Esta etapa especifica o registro de eventos do contrato inteligente. Queremos alguns dados vitais desconectados em cada pagamento bem-sucedido. Os dados a serem desconectados aqui incluem o ID de pagamento, o pagador, o salário total pago e a hora do pagamento.

event Paid(
uint256 id,
address from,
uint256 totalSalary,
uint256 timestamp
);
Enter fullscreen mode Exit fullscreen mode

Passo 4:

Isso especifica a estrutura de pagamento. Struct é uma palavra-chave do solidity, que denota estrutura. Queremos que cada funcionário tenha os seguintes registros:

  • Id que deve ser um inteiro sem sinal.
  • Um endereço de carteira digital especificado pelo trabalhador.
  • Um salário especificado.
  • Um carimbo de data/hora que representa a hora de entrada na empresa.
struct PaymentStruct {
uint256 id;
address worker;
uint256 salary;
uint256 timestamp;
}
PaymentStruct[] employees; //Um elenco de funcionários
Enter fullscreen mode Exit fullscreen mode

Etapa 5:

Nesta etapa, criamos um modificador chamado ownerOnly. Seu único propósito é proteger uma função contra acesso não autorizado. Qualquer que seja a função em que incluirmos esse modificador, só permitirá o acesso ao proprietário da empresa que, neste caso, é o implantador do contrato inteligente.

modifier ownerOnly(){
require(msg.sender == companyAcc, "Reservado ao proprietário apenas");
_;
}
Enter fullscreen mode Exit fullscreen mode

Etapa 6:

Aqui estabelecemos o endereço do implementador para ser a conta da empresa.

constructor() {
companyAcc = msg.sender;
}
Enter fullscreen mode Exit fullscreen mode

Etapa 7:

Esta função é responsável por adicionar um novo trabalhador aos registros de funcionários. Ele só pode ser operado pelo implantador do contrato inteligente que é a conta da empresa.

function addWorker(
address worker,
uint256 salary
) external ownerOnly returns (bool) {
// Verifica a existência do salário e do trabalho...
require(salary > 0 ether, "O salário não pode ser zero!");
require(!isWorker[worker], "Registro já existente!");
// Realiza os cálculos essenciais...
totalWorkers++;
totalSalary += salary;
isWorker[worker] = true;
// Inclui o trabalhador no quadro de funcionários...
employees.push(
PaymentStruct(
totalWorkers,
worker,
salary,
block.timestamp
)
);
return true;
}

Enter fullscreen mode Exit fullscreen mode

Etapa 8:

Esta função é responsável pelo pagamento dos trabalhadores da empresa. Esta é a função que executa as transações em massa. Você deve prestar bem atenção a isto.

function payWorkers() payable external ownerOnly returns (bool) {
// Assegura que o salário pode ser pago...
require(msg.value >= totalSalary, "Ethers pequenos demais");
require(totalSalary <= companyBal, "Balanço insuficiente");
// Realiza pagamento recorrente a cada funcionário...
for(uint i = 0; i < employees.length; i++) {
payTo(employees[i].worker, employees[i].salary);
}
// Realiza os cálculos essenciais...
totalPayment++;
companyBal -= msg.value;
// Emite evento de pagamento...
emit Paid(
totalPayment,
companyAcc,
totalSalary,
block.timestamp
);
return true;
}
Enter fullscreen mode Exit fullscreen mode

O segredo para processar o pagamento em lote é colocá-lo em uma construção de ciclo e fazer com que o ciclo chame a função de pagamento seguro repetidamente até que todos os casos sejam resolvidos.

Etapa 9:

Esta função recebe pagamentos de fora e financia a conta da empresa.

function fundCompanyAcc() payable external returns (bool) {
require(companyAcc != msg.sender, "Você não pode se autofinanciar!");
payTo(companyAcc, msg.value);
companyBal += msg.value;
return true;
}
Enter fullscreen mode Exit fullscreen mode

Etapa 10:

Esta função simplesmente retorna a lista de funcionários que agora fazem parte da empresa.

function getWorkers() external view returns (PaymentStruct[] memory) {
return employees;
}
Enter fullscreen mode Exit fullscreen mode

Etapa 11:

Esta função é responsável por enviar dinheiro de um endereço para outro. Foi chamada repetidamente durante o pagamento do lote aos trabalhadores.

function payTo(
address to,
uint256 amount
) internal returns (bool) {
(bool success,) = payable(to).call{value: amount}("");
require(success, "O pagamento falhou");
return true;
}
Enter fullscreen mode Exit fullscreen mode

Cuidado sobre o processamento de pagamentos em lote

Observe que o processamento de pagamentos em lote é uma atividade autônoma posta em ação, portanto, é aconselhável fazer algumas verificações antes do processamento. Aqui estão algumas dicas para tomar nota.

Verificar os dados

Certifique-se de verificar a exatidão dos dados antes de processar os pagamentos. Usando as funções necessárias e modificadores especiais, como adminOnly, para garantir que apenas registros precisos sejam inseridos no sistema.

Processo de pagamento

Certifique-se de cobrar a conta antes de alterar as variáveis ​​de estado. Isto ajudará a proteger contra ataques de reentrada.

Recalibrar Registro

Atualize as variáveis ​​de estado somente depois de realizar as atividades acima. Por exemplo, se um usuário mal-intencionado pretende atacar sua função de pagamento enviando várias solicitações ao mesmo tempo. Ele será obrigado a pagar duas vezes e, a cada solicitação, o pagamento deve ser feito antes que as variáveis ​​de estado sejam atualizadas.

Assista meus tutoriais web3 GRATUITOS no Youtube agora.

Conclusão

O processamento de pagamentos é uma habilidade obrigatória se você realmente quer ser um desenvolvedor web3. Também é importante saber como ficar na defensiva contra ataques como o de reentrada.

Isso é tudo para este tutorial. Espero que esta informação tenha sido valiosa para você. Ainda estou fazendo aulas particulares para quem quiser entrar no espaço web3. Se você estiver interessado, por favor marque um horário no meu site.

Espero vê-lo na próxima, até lá, tenha um ótimo dia!

Sobre o autor

Gospel Darlington iniciou sua jornada como engenheiro de software em 2016. Ao longo dos anos, ele desenvolveu habilidades completas em JavaScript, como React, ReactNative, NextJs e agora blockchain.

Atualmente, ele está trabalhando como freelancer, criando aplicativos para clientes e escrevendo tutoriais técnicos ensinando outras pessoas a fazer o que ele faz.

Gospel Darlington está disponível para ouvir você. Você pode contatá-lo no LinkedIn, Facebook, Github ou em seu site.


Este artigo foi escrito por Darlington Gospel e publicado aqui. Traduzido e adaptado por Marcelo Panegali.

Top comments (0)