Compreendendo o padrão de retirada de solidez

Ao ter um padrão de retirada Solidity , é garantido que não sejam feitas transferências diretas, o que representaria um risco de segurança. Um exemplo de uso inseguro de chamadas de transferência para enviar ether pode ser visto no seguinte contrato.

Neste artigo, exploraremos as várias maneiras de sacar fundos de um contrato inteligente Solidity e discutiremos as melhores práticas para implementar mecanismos de retirada seguros e eficientes.



Padrões de Retirada de Solidez

De acordo com o padrão de retirada, o recebedor do fundo tem a responsabilidade de comprovar. Se o destinatário do fundo quiser sacar fundos e recuperá-los, ele precisará enviar uma transação.

Dessa forma, um contrato inteligente que envia pagamentos aos destinatários pode ser simplificado.

Consequentemente , o contrato não é afetado pela não entrega de fundos.

Quando o dinheiro é enviado para um contrato inteligente, não há como saber se ocorreu um erro ou se o destinatário é um contrato inteligente malicioso que se recusa a aceitar o pagamento por algum motivo.

O exemplo dado mostra o funcionamento do padrão de retirada:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
pragma solidity ^0.8.0;
contract SolidityTest {
address payable public buyer;
constructor() {
buyer = payable(msg.sender);
}
function allow_Access_To_withdraw(uint amount) public {
require(msg.sender == buyer, "Only the Specified Buyer can Withdraw amount");
require(address(this).balance >= amount, "Not Enough funds in the contract");
buyer.transfer(amount);
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>

Exemplo de Explicação

No exemplo acima, criamos um contrato chamado SolidityTest e possui uma única variável de estado chamada buyer .

O tipo de endereço pagável indica que esta variável pode receber ether (a criptomoeda do blockchain Ethereum).

A construtora define o valor do comprador para o endereço da pessoa que implantou o contrato.

A variável msg.sender é uma variável global especial no Solidity que representa o endereço da pessoa ou contrato que chamou a função atual.

A função allow_Access_To_withdraw é uma função pública que permite ao comprador especificado retirar uma certa quantia de ether do contrato.

As declarações necessárias são usadas para garantir que as condições para a retirada de fundos sejam atendidas.

  • A primeira instrução require verifica se a pessoa que está chamando a função é de fato o comprador especificado no contrato.
  • A segunda declaração obrigatória verifica se há fundos suficientes no contrato para sacar o valor solicitado.

Finalmente, a linha buyer.transfer(amount) transfere a quantidade solicitada de ether do contrato para o endereço do comprador.

Observação : a função de transferência lança automaticamente uma exceção se a transferência falhar (por exemplo, devido a fundos insuficientes ou endereço inválido), o que reverteria toda a transação.

Em vez de apenas verificar o endereço do comprador, também podemos verificar o saldo restante no contrato para ver se o valor correspondente existe no contrato para ser transferido ou não.

O código abaixo fornece uma melhor compreensão do padrão de retirada de solidez:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
pragma solidity ^0.8.0;
contract SolidityTest {
address payable public buyer;
mapping(address => uint) public contract_balance;
constructor() {
buyer = payable(msg.sender);
}
function deposit_mrx_amount() external payable {
contract_balance[msg.sender] += msg.value;
}
function withdraw(uint mrx_amount) external {
require(msg.sender == buyer, "Only the Buyer has the option to withdraw mrx_amount");
require(mrx_amount > 0, "Make sure the withdraw mrx_amount is greater than 0");
require(mrx_amount <= contract_balance[buyer], "The mrx_amount you want to transfer does not exists in the contract");
contract_balance[buyer] -= mrx_amount;
payable(msg.sender).transfer(mrx_amount);
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>

Exemplo de Explicação

Este é um contrato Solidity simples que permite ao proprietário do contrato (o comprador) depositar e sacar um token de criptomoeda específico chamado “ MRX ”.

O contrato tem duas variáveis ​​de estado : buyer e contract_balance. buyer é um endereço especificado no construtor e contract_balance é um mapeamento que armazena o saldo MRX para cada endereço que depositou fundos no contrato.

O tipo de endereço a pagar indica que as variáveis ​​comprador e pagável (msg.sender) podem receber ether ou MRX.

A construtora define o valor do comprador para o endereço da pessoa que implantou o contrato.

A variável msg.sender é uma variável global especial no Solidity que representa o endereço da pessoa ou contrato que chamou a função atual.

A função deposit_mrx_amount é uma função pública que permite que qualquer pessoa deposite MRX no contrato.

O modificador pagável indica que esta função pode receber MRX juntamente com ether.

O contract_balance[msg.sender] += msg.value; linha adiciona o MRX depositado ao saldo do endereço que chamou a função.

A função de retirada é uma função pública que permite ao comprador retirar uma quantia especificada de MRX do contrato.

As declarações necessárias são usadas para garantir que as condições para retirar o MRX sejam atendidas.

  1. Primeiro, exija que a instrução verifique se a pessoa que está chamando a função é realmente o comprador especificado no contrato.
  2. Em segundo lugar, a declaração exigida verifica se o valor da retirada solicitada é maior que zero.
  3. Em terceiro lugar, exija que o extrato verifique se o comprador tem saldo suficiente para sacar o valor solicitado.

Finalmente, o contract_balance[buyer] -= mrx_amount; linha subtrai o valor retirado do saldo do comprador.

O pagável(msg.sender).transfer(mrx_amount); A linha transfere a quantidade solicitada de MRX para o endereço que chamou a função.

Observe que a função de transferência lança automaticamente uma exceção se a transferência falhar (por exemplo, devido a fundos insuficientes ou endereço inválido), o que reverteria toda a transação.

Conclusão

A retirada de fundos de um contrato inteligente Solidity é um processo complexo que deve ser considerado cuidadosamente por motivos de segurança e usabilidade.

Discutimos os padrões de retirada do Solidity neste artigo como um bom ponto de partida para a construção de mecanismos de retirada convenientes e seguros .

Importante : se você estiver escolhendo o padrão de retirada do Solidity para seu caso de uso específico, é importante pesar as compensações entre custos de gás, segurança e usabilidade.
Nós valorizamos o seu feedback.
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0

Assine a nossa newsletter
Digite seu e-mail para receber um resumo semanal de nossos melhores posts. Saber mais!
ícone