Skip to content

Instantly share code, notes, and snippets.

@tinchoabbate
Last active March 3, 2024 19:00
Show Gist options
  • Save tinchoabbate/99fbf7cbce47eb7c463212fd13f21149 to your computer and use it in GitHub Desktop.
Save tinchoabbate/99fbf7cbce47eb7c463212fd13f21149 to your computer and use it in GitHub Desktop.
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