Solidity - Mô hình rút tiền
Mô hình rút tiền đảm bảo rằng cuộc gọi chuyển khoản trực tiếp không được thực hiện gây ra mối đe dọa bảo mật. Hợp đồng sau đây cho thấy việc sử dụng không an toàn cuộc gọi chuyển tiền để gửi 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;
}
}
}
Hợp đồng trên có thể được hiển thị ở trạng thái không sử dụng được bằng cách khiến hợp đồng giàu nhất trở thành hợp đồng không hoạt động chức năng dự phòng. Khi hàm dự phòng không thành công, hàm trở thànhRichest () cũng không thành công và hợp đồng sẽ bị mắc kẹt mãi mãi. Để giảm thiểu vấn đề này, chúng ta có thể sử dụng Mô hình Rút tiền.
Trong mô hình rút tiền, chúng tôi sẽ đặt lại số tiền đang chờ xử lý trước mỗi lần chuyển. Nó sẽ đảm bảo rằng chỉ có hợp đồng người gọi không thành công.
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);
}
}