Solidity - รูปแบบการถอน
รูปแบบการถอนทำให้มั่นใจได้ว่าจะไม่มีการโอนสายโดยตรงซึ่งก่อให้เกิดภัยคุกคามด้านความปลอดภัย สัญญาต่อไปนี้แสดงการใช้การโอนสายเพื่อส่งอีเธอร์ที่ไม่ปลอดภัย
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;
}
}
}
สัญญาข้างต้นสามารถแสดงผลในสถานะใช้ไม่ได้โดยทำให้คนรวยที่สุดเป็นสัญญาของฟังก์ชันทางเลือกที่ล้มเหลว เมื่อฟังก์ชันทางเลือกล้มเหลวฟังก์ชัน becomeRichest () จะล้มเหลวและสัญญาจะค้างตลอดไป เพื่อลดปัญหานี้เราสามารถใช้รูปแบบการถอน
ในรูปแบบการถอนเราจะรีเซ็ตจำนวนเงินที่รอดำเนินการก่อนการโอนแต่ละครั้ง จะทำให้มั่นใจได้ว่าสัญญาเฉพาะผู้โทรล้มเหลว
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);
}
}