You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.9 KiB
Solidity
214 lines
7.9 KiB
Solidity
2 years ago
|
// 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 {}
|
||
|
|
||
|
}
|