Skip to content

Latest commit

 

History

History
64 lines (52 loc) · 4.09 KB

README.md

File metadata and controls

64 lines (52 loc) · 4.09 KB

Solution

In solving this challenge, the primary objective is to trigger the explodeSpaceBank function, as outlined in the Challenge contract. This task requires navigating through a series of checks, each serving as a step toward achieving the goal of "exploding" the bank.

First, we need to understand the prerequisites of invoking the explodeSpaceBank function. Key among these is ensuring that the call occurs exactly two blocks after the alarmTime has been set. Additionally, the address stored in _createdAddress must be devoid of code, signifying either an externally owned account (EOA) or a contract that has been self-destructed at the point of verification. Moreover, the SpaceBank contract must be entirely empty of funds.

///Make the bank explode
function explodeSpaceBank() external {
    require(block.number == alarmTime + 2, "Can't explode the bank");
    uint256 codeSize;
    address value = _createdAddress;
    assembly {
        codeSize := extcodesize(value)
    }
    require(codeSize == 0, "You were caught");
    require(token.balanceOf(address(this)) == 0, "The bank still has funds");
    exploded = true;
}

To set the alarmTime, we indirectly engage the _emergencyAlarmProtocol by triggering the second alarm. This protocol is invoked via the _emergencyAlarms modifier, applied to the deposit function. Notably, the entered variable must be true for _emergencyAlarmProtocol to be called, a condition we satisfy by initiating a flash loan via the flashLoan function. This action sets the stage for a contract implementing the executeFlashLoan function that deposits into the SpaceBank, thereby escalating the alarm levels.

if (EmergencyAlarms == 2) {
    //second alarm
    bytes32 MagicNumber = bytes32(block.number);
    uint256 balance = address(this).balance;
    address newContractAddress;
    assembly {
        newContractAddress := create2(0, add(data, 0x20), mload(data), MagicNumber)
    }
    require(address(this).balance > balance, "You need to send ether to pass through security");
    _createdAddress = newContractAddress;
    alarmTime = block.number;
}
function flashLoan(uint256 amount, address flashLoanReceiver) external {
    uint256 initialBalance = token.balanceOf(address(this));

    require(initialBalance >= amount, "Not enough liquidity");
    // Transfer loan amount to the receiver
    require(token.transfer(flashLoanReceiver, amount), "Transfer failed");

    // Execute custom logic in the receiver's contract
    entered = true;

    (bool success, bytes memory result) =
        flashLoanReceiver.call(abi.encodeWithSignature("executeFlashLoan(uint256)", amount));
    if (success == false) revert(string(result));
    entered = false;
    uint256 fee = amount / 1000; // 0.1% fee
    uint256 currentBalance = token.balanceOf(address(this));
    require(currentBalance >= initialBalance + fee, "Loan not repaid with fee");
}

For the first alarm, we need to provide data that, when decoded into a uint256, matches the remainder of block.number % 47. The second alarm will create a contract using CREATE2 and check that it has funds. To pass this, we need to pre-calculate this contract address and send it an amount of Ether that is greater than the current balance of the SpaceBank contract. Additionally, we are able to define the code of this contract that gets created. Therefore, we have the possibility of self-destructing or doing any other operation.

Going back to the explodeSpaceBank function, we pass the first check, but now face the second and third checks. Specifically, the second check verifies that the CREATE2-created contract has no code (i.e. has self-destructed). Then, the third check verifies that the SpaceBank doesn't hold any tokens. This is achieved by executing a flash loan for the total amount of tokens available, followed by a withdrawal of these tokens, leaving the bank's coffers empty

By implementing these steps, we can successfully destroy the bank and solve the challenge. You can check the solve script here.