// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; import "forge-std/Test.sol"; import {Punkhunt} from "../src/Punkhunt.sol"; import {Duck} from "../src/Duck.sol"; import {Zapper} from "../src/Zapper.sol"; contract DuckTest is Test { using stdStorage for StdStorage; Punkhunt public punkhunt; Duck public duck; Zapper public zapper; uint256 duckPrice; uint256 zapperPrice; address victim = address(1); address killer = address(2); function setUp() public { punkhunt = new Punkhunt(); duck = new Duck(); zapper = new Zapper(); duck.setPunkhuntContract(address(punkhunt)); zapper.setPunkhuntContract(address(punkhunt)); punkhunt.setDuckContract(address(duck)); punkhunt.setZapperContract(address(zapper)); duckPrice = punkhunt.duckPrice(); zapperPrice = punkhunt.zapperPrice(); } // // ensure only Punkhunt can mint/burn/kill // function testOnlyPunkhunt() public { // address t = address(1); // startHoax(t); // vm.expectRevert(bytes("invalid msg sender")); // duck.radicalize(t, 10); // vm.expectRevert(bytes("invalid msg sender")); // duck.die(1); // vm.expectRevert(bytes("invalid msg sender")); // zapper.create(t, 10); // vm.expectRevert(bytes("invalid msg sender")); // zapper.explode(t, 10); // assertEq(duck.totalSupply() == 0, true); // } // // ensure killing increments leaderboard // function testLeaderboard() public { // uint256 amt = 20; // punkhunt.toggleMayhem(); // hoax(victim); // punkhunt.radicalizeBoomers{value: duckPrice * amt}(amt); // startHoax(killer); // punkhunt.assembleBombs{value: zapperPrice * amt}(amt); // punkhunt.sendBombs(3); // punkhunt.sendBombs(3); // punkhunt.sendBombs(3); // punkhunt.sendBombs(3); // punkhunt.sendBombs(3); // assertEq(punkhunt.leaderboard(punkhunt.leaderboardPointer()), killer); // assertEq(punkhunt.ducksKilled() > 0, true); // console.log(punkhunt.killCount(killer)); // } // // ensure killing toggles URI // function testURIToggling() public { // duck.setBaseURI('ipfs://base/'); // punkhunt.toggleMayhem(); // startHoax(victim); // punkhunt.radicalizeBoomers{value: duckPrice}(1); // assertEq(duck.tokenURI(1), 'ipfs://base/1.json'); // punkhunt.sendBombs(1); // assertEq(duck.tokenURI(1), 'ipfs://base/dead.json'); // } // // ensure sending zappers burns zappers // function testBombBurning() public { // punkhunt.toggleMayhem(); // hoax(victim); // punkhunt.radicalizeBoomers{value: duckPrice * 20}(20); // startHoax(killer); // punkhunt.assembleBombs{value: zapperPrice * 20}(20); // assertEq(punkhunt.zapperBalance(killer), 20); // assertEq(punkhunt.zappersExploded(), 0); // punkhunt.sendBombs(5); // assertEq(punkhunt.zapperBalance(killer), 15); // assertEq(punkhunt.zappersExploded(), 5); // } // // ensure sending zappers doesn't bork // function testSendBombErrors() public { // punkhunt.toggleMayhem(); // hoax(address(1)); // punkhunt.radicalizeBoomers{value: duckPrice * 20}(20); // hoax(address(2)); // punkhunt.radicalizeBoomers{value: duckPrice * 20}(20); // hoax(address(3)); // punkhunt.radicalizeBoomers{value: duckPrice * 20}(20); // startHoax(address(4)); // punkhunt.assembleBombs{value: zapperPrice * 200}(200); // vm.warp(2); // punkhunt.sendBombs(1); // vm.warp(300); // punkhunt.sendBombs(1); // vm.warp(400); // punkhunt.sendBombs(1); // vm.warp(500); // punkhunt.sendBombs(1); // vm.warp(6000); // punkhunt.sendBombs(1); // vm.warp(7000); // punkhunt.sendBombs(1); // vm.warp(8000); // punkhunt.sendBombs(1); // vm.warp(9000); // punkhunt.sendBombs(1); // } // // ensure wallet limits enforced // function testWalletMintLimit() public { // uint256 max = punkhunt.duckMaxMintPerWallet(); // startHoax(victim); // punkhunt.radicalizeBoomers{value: max * duckPrice}(max); // vm.expectRevert("cannot exceed maximum per wallet"); // punkhunt.radicalizeBoomers{value: duckPrice}(1); // } // // ensure supply limits enforced // function testMaximumSupply() public { // uint256 maxSupply = punkhunt.duckMaxSupply(); // uint256 slot = stdstore // .target(address(duck)) // .sig("minted()") // .find(); // bytes32 loc = bytes32(slot); // bytes32 mockedCurrentTokenId = bytes32(abi.encode(maxSupply - 1)); // vm.store(address(duck), loc, mockedCurrentTokenId); // assertEq(punkhunt.ducksRadicalized(), (maxSupply - 1)); // startHoax(victim); // punkhunt.radicalizeBoomers{value: duckPrice}(1); // vm.expectRevert(bytes("supply reached")); // punkhunt.radicalizeBoomers{value: duckPrice}(1); // } // // ensure survivor limit enforced and actions halted // function testSurvivors() public { // uint256 maxSupply = punkhunt.duckMaxSupply(); // uint256 maxSurvivorCount = punkhunt.duckMaxSurvivorCount(); // uint256 slot = stdstore // .target(address(duck)) // .sig("minted()") // .find(); // bytes32 loc = bytes32(slot); // bytes32 a = bytes32(abi.encode(maxSupply)); // 10k // vm.store(address(duck), loc, a); // slot = stdstore // .target(address(duck)) // .sig("burned()") // .find(); // loc = bytes32(slot); // a = bytes32(abi.encode((maxSupply - maxSurvivorCount))); // 1k // vm.store(address(duck), loc, a); // startHoax(victim); // vm.expectRevert(bytes("mission already completed")); // punkhunt.radicalizeBoomers{value: duckPrice}(1); // vm.expectRevert(bytes("mission already completed")); // punkhunt.assembleBombs{value: zapperPrice}(1); // vm.expectRevert(bytes("mission already completed")); // punkhunt.sendBombs(1); // } // // ensure withdraw function works as expected // function testWithdrawalWorksAsOwner() public { // address owner = punkhunt.owner(); // uint256 ownerStartBalance = owner.balance; // assertEq(address(punkhunt).balance, 0); // hoax(victim); // punkhunt.radicalizeBoomers{value: duckPrice * 10}(10); // uint256 contractBalance = address(punkhunt).balance; // assertEq(contractBalance, duckPrice * 10); // punkhunt.withdraw(); // assertEq(owner.balance, ownerStartBalance + contractBalance); // } // // ensure only owner can withdraw // function testWithdrawalFailsAsNotOwner() public { // hoax(victim); // punkhunt.radicalizeBoomers{value: duckPrice * 10}(10); // uint256 contractBalance = address(punkhunt).balance; // assertEq(contractBalance, duckPrice * 10); // vm.expectRevert("UNAUTHORIZED"); // hoax(address(0xd3ad)); // punkhunt.withdraw(); // vm.expectRevert("UNAUTHORIZED"); // hoax(address(123)); // punkhunt.withdraw(); // } // // ensure NFT contracts do not accept Ether // function testNoAcceptEther() public { // (bool tbb, ) = payable(address(zapper)).call{value: .5 ether}(""); // assertEq(tbb, false); // (bool tbr, ) = payable(address(duck)).call{value: .5 ether}(""); // assertEq(tbr, false); // } // Function to receive Ether. msg.data must be empty receive() external payable {} // Fallback function is called when msg.data is not empty fallback() external payable {} }