-
-
Save tinchoabbate/99fbf7cbce47eb7c463212fd13f21149 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.8.0; | |
contract Example { | |
uint256 public totalDeposits; | |
mapping(address => uint256) public deposits; | |
function deposit() external payable { | |
deposits[msg.sender] += msg.value; | |
totalDeposits += msg.value; | |
} | |
function withdraw() external { | |
/* | |
Apparently the only way to deposit ETH in the contract is via the `deposit` function. | |
If that were the case, this strict equality would always hold. | |
But anyone can deposit ETH via selfdestruct, or by setting this contract as the target | |
of a beacon chain withdrawal. | |
(see last paragraph of this section | |
https://eth2book.info/capella/part2/deposits-withdrawals/withdrawal-processing/#performing-withdrawals), | |
regardless of the contract not having a `receive` function. | |
If anybody deposits ETH that way, then the equality breaks and the contract is DoS'd. | |
To fix it, the code could be changed to >= instead of ==. Which means that the available | |
ETH balance should be _at least_ `totalDeposits`, which makes more sense. | |
*/ | |
assert(address(this.balance) == totalDeposits); // bad | |
uint256 amount = deposits[msg.sender]; | |
totalDeposits -= amount; | |
deposits[msg.sender] = 0; | |
payable(msg.sender).transfer(amount); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment