Soliditas - Pola Penarikan
Pola penarikan memastikan bahwa panggilan transfer langsung tidak dilakukan yang menimbulkan ancaman keamanan. Kontrak berikut menunjukkan penggunaan transfer call yang tidak aman untuk mengirim Ether.
pragma solidity ^0.5.0;
contract Test {
address payable public richest;
uint public mostSent;
constructor() public payable {
richest = msg.sender;
mostSent = msg.value;
}
function becomeRichest() public payable returns (bool) {
if (msg.value > mostSent) {
// Insecure practice
richest.transfer(msg.value);
richest = msg.sender;
mostSent = msg.value;
return true;
} else {
return false;
}
}
}
Kontrak di atas dapat dibuat dalam keadaan tidak dapat digunakan dengan menyebabkan yang terkaya menjadi kontrak dengan fungsi fallback yang gagal. Saat fungsi fallback gagal, fungsi beRichest () juga gagal dan kontrak akan macet selamanya. Untuk mengatasi masalah ini, kita bisa menggunakan Pola Penarikan.
Dalam pola penarikan, kami akan mengatur ulang jumlah yang tertunda sebelum setiap transfer. Ini akan memastikan bahwa hanya kontrak penelepon yang gagal.
pragma solidity ^0.5.0;
contract Test {
address public richest;
uint public mostSent;
mapping (address => uint) pendingWithdrawals;
constructor() public payable {
richest = msg.sender;
mostSent = msg.value;
}
function becomeRichest() public payable returns (bool) {
if (msg.value > mostSent) {
pendingWithdrawals[richest] += msg.value;
richest = msg.sender;
mostSent = msg.value;
return true;
} else {
return false;
}
}
function withdraw() public {
uint amount = pendingWithdrawals[msg.sender];
pendingWithdrawals[msg.sender] = 0;
msg.sender.transfer(amount);
}
}