Force Send ETH - 2
Tags: solidity, security, bestpractice
Published: 2022-05-14 20:46:50

---series: Security Vulnerabilities---

In the last post [Force Send ETH - 1](https://dev.to/rushanksavant/force-send-eth-1-2on1), we understood about `selfdestruct` and how it's used to forcefully send ETH to any contract.

Now let's take an example to understand what's the vulnerability in this. Consider the following contract:

```solidity
contract Crowdfund {
    // this contract only accepts a certain amount of funds
    // if someone tries to send an amount that exceeds contract balance more than the limit, tnx fails
    // funds are transfered to an address only when contract balance equals fund limit

    uint fundLimit = 3 ether;
    bool contractOpen = true;

    function donate() external payable { // for others to donate eth to this contract
        require(contractOpen, "Contract has stopped recieving funds");
        require(address(this).balance <= fundLimit, "Can't send specified amount");
        // note: we cannot do address(this).balance + msg.value, because address(this).balance already takes msg.value
    }

    function getBalance() external view returns(uint) { // to get current balance of this contract
        return address(this).balance;
    } 

    function sendFunds() external { // to send all collected funds
        require(contractOpen, "Contract has stopped recieving funds");
        require(address(this).balance == fundLimit, "Fund limit not reached yet");
        contractOpen = false; // contract closed
        payable(address(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB)).transfer(address(this).balance);
    }
}
```
Now consider the following scenario:
- Contract balance has reached 3 ether, but some hacker force-sends extra ETH to CrowdFund contract address. 
- Now contract balance > fundLimit, hence `require(address(this).balance == fundLimit, "Fund limit not reached yet");` from the `sendFunds()` function will fail and not let anyone send the collected funds to required receiver.

Hope you got an idea about what exactly the vulnerability is.

Let's see the attacker contract:

```solidity
contract Attacker{
    fallback() external payable {

    }

    function attack(address _crowdFund) external {
        selfdestruct(payable(_crowdFund));
    }
}
```

Till now we understood what exactly this vulnerability is and how hackers can take advantage of it. Let's now see how to avoid such hacks.
- one solution is to change 

`require(address(this).balance == fundLimit, "Fund limit not reached yet");` to 

`require(address(this).balance >= fundLimit, "Fund limit not reached yet");` in `sendFunds()` function of `Crowdfund` contract.

But what if that's an important condition for some application?

- better solution is to avoid using `address(this)` to track funds

Let's see the following contract to understand this better:

```solidity
contract CrowdFund_safe{
    uint fundLimit = 3 ether;
    bool contractOpen = true;
    uint balance = 0;

    function donate() external payable { // for others to donate eth to this contract
        require(contractOpen, "Contract has stopped recieving funds");
        require(balance + msg.value <= fundLimit, "Can't send specified amount");
        balance += msg.value;
    }

    function getBalance() external view returns(uint) { // to get current balance of this contract
        return address(this).balance;
    } 

    function sendFunds() external { // to send all collected funds
        require(contractOpen, "Contract has stopped recieving funds");
        require(balance == fundLimit, "Fund limit not reached yet");
        contractOpen = false; // contract closed
        payable(address(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB)).transfer(balance);
    }
}
```

Now even if hacker force-sends ETH to this contract, it won't change the `balance` state variable, hence this won't affect any conditions in the contract.
Hence the contract is safe from such attacks.