_Follow along with this video:_ --- ### Mishandling of ETH To see this vulnerability in action we're going to again reference our [**sc-exploits-minimized**](https://github.com/Cyfrin/sc-exploits-minimized) repo! There are two situational examples available for `Mishandling of ETH` for this lesson we want [**Remix (Vulnerable to selfdestruct)**](https://remix.ethereum.org/#url=https://github.com/Cyfrin/sc-exploits-minimized/blob/main/src/mishandling-of-eth/SelfDestructMe.sol&lang=en&optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.20+commit.a1b79de6.js). > Remember: The codebase is available on the [**sc-exploits-minimized**](https://github.com/Cyfrin/sc-exploits-minimized/blob/main/src/mishandling-of-eth/SelfDestructMe.sol) repo as well, if you want to test things locally. ### Remix Example We've done this a few times, so we should be familiar with the process - go ahead and compile our `SelfDestructMe.sol` contract and deploy. You'll likely be met with this message, `selfdestruct` is being heavily considered for deprecation, but for now this vulnerability still exists, so we can ignore this message for now. ::image{src='/security-section-4/34-mishandling-eth-minimized/mishandling-eth-minimized1.png' style='width: 50%; height: auto;'} <details> <summary>SelfDestructMe.sol</summary> ```js contract SelfDestructMe { 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); } } ``` </details> :br `SelfDestructMe.sol` is a fairly straightforward contract at a glance, experiment with the basic functions of the contract as you wish. A user is able to deposit funds, which updates their balance as well as the `totalDeposits` variable. A user can also call `withdraw`, this function checks that the contract's balance is still equal to the `totalDeposits` and if so will updates balances and transfer funds. I've deposited 1 Ether to the contract, here. ::image{src='/security-section-4/34-mishandling-eth-minimized/mishandling-eth-minimized2.png' style='width: 50%; height: auto;'} The issue comes from this line: ```js assert(address(this).balance == totalDeposits); ``` The core of this vulnerability is the assumption that, without a `receive` or `fallback` function, the only way to send value to this contract is through the deposit function. This is **_false_**. Go ahead and deploy the `AttackSelfDestructMe.sol` contract. The constructor requires an attack target, so be sure to copy the address for `SelfDestructMe.sol` and pass it to your deploy. Give the contract a balance during deployment as well. ::image{src='/security-section-4/34-mishandling-eth-minimized/mishandling-eth-minimized3.png' style='width: 50%; height: auto;'} Now, when the attack function is called, `selfdestruct` will be triggered, and we expect to see our 5 Ether forced onto `SelfDestructMe.sol`. And, that's exactly what we see: ::image{src='/security-section-4/34-mishandling-eth-minimized/mishandling-eth-minimized4.png' style='width: 50%; height: auto;'} Lastly, try calling the `withdraw` function on `SelfDestructMe.sol`. It reverts! The contract's accounting has been broken and it's balance is now stuck! ::image{src='/security-section-4/34-mishandling-eth-minimized/mishandling-eth-minimized5.png' style='width: 75%; height: auto;'} ### Wrap Up We've illustrated how relying on a contract's balance as a means of internal counting can be risky. There's really no way to be certain that arbitrary value isn't sent to a contract currently. As I'd mentioned previously, the concept of `Mishandling Eth` is a broad one. Our sc-exploits-minimized repo outlines another common scenario (push over pull) that I encourage you to look at, as we won't go over it here. Ultimately, this is another finding for sure - let's make note of it. ```js // @Audit: Mishandling Eth function withdraw() external {...} ```
How ETH Misuse Leads to Smart Contract Vulnerability, Patrick Explains Solutions
Previous lesson
Previous
Next lesson
Next
Give us feedback
Solidity Developer
Smart Contract SecurityDuration: 25min
Duration: 1h 18min
Duration: 35min
Duration: 2h 28min
Duration: 5h 03min
Duration: 5h 22min
Duration: 4h 33min
Duration: 2h 01min
Duration: 1h 40min
Testimonials
Read what our students have to say about this course.
Chainlink
Chainlink
Gustavo Gonzalez
Solutions Engineer at OpenZeppelin
Francesco Andreoli
Lead Devrel at Metamask
Albert Hu
DeForm Founding Engineer
Radek
Senior Developer Advocate at Ceramic
Boidushya
WalletConnect
Idris
Developer Relations Engineer at Axelar