Solidity - Geri Çekilme Modeli
Para çekme modeli, bir güvenlik tehdidi oluşturan doğrudan transfer çağrısının yapılmamasını sağlar. Aşağıdaki sözleşme, ether göndermek için transfer çağrısının güvensiz kullanımını gösteriyor.
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;
}
}
}
Yukarıdaki sözleşme, en zengin olanın başarısız bir geri dönüş işlevi sözleşmesi olmasına neden olarak kullanılamaz hale getirilebilir. Geri dönüş işlevi başarısız olduğunda, haleRichest () işlevi de başarısız olur ve sözleşme sonsuza kadar takılı kalır. Bu sorunu hafifletmek için Para Çekme Modelini kullanabiliriz.
Para çekme modelinde, bekleyen tutarı her transferden önce sıfırlayacağız. Yalnızca arayan sözleşmesinin başarısız olmasını sağlayacaktır.
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);
}
}