Solidität - Entnahmemuster
Das Abhebungsmuster stellt sicher, dass kein direkter Weiterleitungsanruf getätigt wird, der eine Sicherheitsbedrohung darstellt. Der folgende Vertrag zeigt die unsichere Verwendung des Weiterleitungsanrufs zum Senden von Äther.
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;
}
}
}
Der oben genannte Vertrag kann in einen unbrauchbaren Zustand versetzt werden, indem der reichste Vertrag ein Vertrag mit fehlgeschlagener Fallback-Funktion wird. Wenn die Fallback-Funktion fehlschlägt, schlägt auch die Funktion areRichest () fehl und der Vertrag bleibt für immer bestehen. Um dieses Problem zu beheben, können wir das Abhebungsmuster verwenden.
Im Auszahlungsmuster setzen wir den ausstehenden Betrag vor jeder Überweisung zurück. Dadurch wird sichergestellt, dass nur der Anrufervertrag fehlschlägt.
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);
}
}