cleanup and tighten tests

master
lza_menace 2 years ago
parent 16cd16a979
commit ce306d953f

@ -32,12 +32,6 @@ contract Mailbomb is ERC1155, Owned {
// Admin // Admin
// ========================================================================= // =========================================================================
/// Withdraw funds to contract owner
function withdraw() external onlyOwner {
uint256 balance = address(this).balance;
payable(msg.sender).transfer(balance);
}
/// Set metadata URI for all BOMB (token 1) /// Set metadata URI for all BOMB (token 1)
/// @param _baseURI IPFS hash or URL to retrieve JSON metadata /// @param _baseURI IPFS hash or URL to retrieve JSON metadata
function setBaseURI(string calldata _baseURI) external onlyOwner { function setBaseURI(string calldata _baseURI) external onlyOwner {

@ -99,7 +99,8 @@ contract Main is Owned {
/// Withdraw funds to contract owner /// Withdraw funds to contract owner
function withdraw() external onlyOwner { function withdraw() external onlyOwner {
uint256 balance = address(this).balance; uint256 balance = address(this).balance;
payable(msg.sender).transfer(balance); (bool success, ) = payable(msg.sender).call{value: balance}("");
require(success, "failed to withdraw");
} }
/// Set price per BOOMR /// Set price per BOOMR
@ -134,7 +135,7 @@ contract Main is Owned {
/// The game stops; no more bombing/killing. Survivors make it to the next round. /// The game stops; no more bombing/killing. Survivors make it to the next round.
modifier missionNotCompleted { modifier missionNotCompleted {
require( require(
unaboomer.totalKillCount() <= (unaboomer.MAX_SUPPLY() - unaboomer.SURVIVOR_COUNT()), unaboomer.totalKillCount() < (unaboomer.MAX_SUPPLY() - unaboomer.MAX_SURVIVOR_COUNT()),
"mission already completed" "mission already completed"
); );
_; _;
@ -171,8 +172,8 @@ contract Main is Owned {
/// Get BOOMR token survivor count /// Get BOOMR token survivor count
/// @return survivorCount Maximum amount of BOOMR survivor tokens that can ever exist /// @return survivorCount Maximum amount of BOOMR survivor tokens that can ever exist
function unaboomerSurvivorCount() public view returns (uint256) { function unaboomerMaxSurvivorCount() public view returns (uint256) {
return unaboomer.SURVIVOR_COUNT(); return unaboomer.MAX_SURVIVOR_COUNT();
} }
/// Get BOMB token balance of wallet /// Get BOMB token balance of wallet

@ -15,7 +15,7 @@ Each Unaboomer is a unique, dynamically generated pixel avatar in the likeness
of the real-life Unabomber, Theodore Kaczynski. Unaboomers can be "killed" by of the real-life Unabomber, Theodore Kaczynski. Unaboomers can be "killed" by
other players by "sending" (burning) mailbombs. When Unaboomers are killed their other players by "sending" (burning) mailbombs. When Unaboomers are killed their
corresponding image is replaced with an explosion, rendering it worthless as any corresponding image is replaced with an explosion, rendering it worthless as any
rarity associated with it ceases to exist. The game stops when SURVIVOR_COUNT rarity associated with it ceases to exist. The game stops when MAX_SURVIVOR_COUNT
threshold is breached. The surviving players (any address which holds an "alive" threshold is breached. The surviving players (any address which holds an "alive"
Unaboomer) will advance to the next round of gameplay. Unaboomer) will advance to the next round of gameplay.
@dev All contract functions regarding token burning and minting are limited to @dev All contract functions regarding token burning and minting are limited to
@ -29,7 +29,7 @@ contract Unaboomer is ERC721, Owned {
/// Maximum supply of BOOMR tokens /// Maximum supply of BOOMR tokens
uint256 public constant MAX_SUPPLY = 10000; uint256 public constant MAX_SUPPLY = 10000;
/// Maximum amount of survivors remaining to advance to the next round /// Maximum amount of survivors remaining to advance to the next round
uint256 public constant SURVIVOR_COUNT = 1000; uint256 public constant MAX_SURVIVOR_COUNT = 1000;
/// The total amount of Unaboomers who have been killed during the game /// The total amount of Unaboomers who have been killed during the game
uint256 public totalKillCount; uint256 public totalKillCount;
/// Number of tokens minted (total supply) /// Number of tokens minted (total supply)
@ -47,12 +47,6 @@ contract Unaboomer is ERC721, Owned {
// Admin // Admin
// ========================================================================= // =========================================================================
/// Withdraw funds to contract owner
function withdraw() external onlyOwner {
uint256 balance = address(this).balance;
payable(msg.sender).transfer(balance);
}
/// Set metadata URI for living Unaboomer tokens /// Set metadata URI for living Unaboomer tokens
/// @param _baseURI IPFS hash or URL to retrieve JSON metadata for living Unaboomer tokens /// @param _baseURI IPFS hash or URL to retrieve JSON metadata for living Unaboomer tokens
function setAliveURI(string calldata _baseURI) external onlyOwner { function setAliveURI(string calldata _baseURI) external onlyOwner {

@ -7,11 +7,15 @@ import {Unaboomer} from "../src/Unaboomer.sol";
import {Mailbomb} from "../src/Mailbomb.sol"; import {Mailbomb} from "../src/Mailbomb.sol";
contract UnaboomerTest is Test { contract UnaboomerTest is Test {
using stdStorage for StdStorage;
Main public main; Main public main;
Unaboomer public boomr; Unaboomer public boomr;
Mailbomb public bomb; Mailbomb public bomb;
uint256 unaboomerPrice; uint256 unaboomerPrice;
uint256 bombPrice; uint256 bombPrice;
address victim = address(1);
address killer = address(2);
function setUp() public { function setUp() public {
main = new Main(); main = new Main();
@ -42,8 +46,6 @@ contract UnaboomerTest is Test {
// ensure killing increments leaderboard // ensure killing increments leaderboard
function testLeaderboard() public { function testLeaderboard() public {
address victim = address(1);
address killer = address(2);
uint256 amt = 20; uint256 amt = 20;
hoax(victim); hoax(victim);
main.radicalizeBoomers{value: unaboomerPrice * amt}(amt); main.radicalizeBoomers{value: unaboomerPrice * amt}(amt);
@ -60,21 +62,112 @@ contract UnaboomerTest is Test {
} }
// ensure killing toggles URI // ensure killing toggles URI
function testURIToggling() public {
boomr.setAliveURI('ipfs://alive/');
boomr.setDeadURI('ipfs://dead/');
startHoax(victim);
main.radicalizeBoomers{value: unaboomerPrice * 1}(1);
assertEq(boomr.tokenURI(1), 'ipfs://alive/1.json');
main.sendBombs(1);
assertEq(boomr.tokenURI(1), 'ipfs://dead/1.json');
}
// ensure sending bombs burns bombs // ensure sending bombs burns bombs
function testBombBurning() public {
hoax(victim);
main.radicalizeBoomers{value: unaboomerPrice * 20}(20);
startHoax(killer);
main.assembleBombs{value: bombPrice * 20}(20);
assertEq(main.bombBalance(killer), 20);
assertEq(main.bombsExploded(), 0);
main.sendBombs(5);
assertEq(main.bombBalance(killer), 15);
assertEq(main.bombsExploded(), 5);
}
// ensure supply limits enforced // ensure supply limits enforced
// ensure survivor limit enforced function testMaximumSupply() public {
// ensure only owners can withdraw funds uint256 maxSupply = main.unaboomerMaxSupply();
// ensure withdraw function actuall works uint256 slot = stdstore
.target(address(boomr))
.sig("minted()")
.find();
bytes32 loc = bytes32(slot);
bytes32 mockedCurrentTokenId = bytes32(abi.encode(maxSupply - 1));
vm.store(address(boomr), loc, mockedCurrentTokenId);
assertEq(main.unaboomerSupply(), (maxSupply - 1));
startHoax(victim);
main.radicalizeBoomers{value: unaboomerPrice}(1);
vm.expectRevert(bytes("supply reached"));
main.radicalizeBoomers{value: unaboomerPrice}(1);
}
// ensure survivor limit enforced and actions halted
function testSurvivors() public {
uint256 maxSupply = main.unaboomerMaxSupply();
uint256 maxSurvivorCount = main.unaboomerMaxSurvivorCount();
uint256 slot = stdstore
.target(address(boomr))
.sig("minted()")
.find();
bytes32 loc = bytes32(slot);
bytes32 a = bytes32(abi.encode(maxSupply)); // 10k
vm.store(address(boomr), loc, a);
slot = stdstore
.target(address(boomr))
.sig("totalKillCount()")
.find();
loc = bytes32(slot);
a = bytes32(abi.encode((maxSupply - maxSurvivorCount))); // 1k
vm.store(address(boomr), loc, a);
startHoax(victim);
vm.expectRevert(bytes("mission already completed"));
main.radicalizeBoomers{value: unaboomerPrice}(1);
vm.expectRevert(bytes("mission already completed"));
main.assembleBombs{value: bombPrice}(1);
vm.expectRevert(bytes("mission already completed"));
main.sendBombs(1);
}
// ensure withdraw function works as expected
function testWithdrawalWorksAsOwner() public {
address owner = main.owner();
uint256 ownerStartBalance = owner.balance;
assertEq(address(main).balance, 0);
hoax(victim);
main.radicalizeBoomers{value: unaboomerPrice * 10}(10);
uint256 contractBalance = address(main).balance;
assertEq(contractBalance, unaboomerPrice * 10);
main.withdraw();
assertEq(owner.balance, ownerStartBalance + contractBalance);
}
// ensure only owner can withdraw
function testWithdrawalFailsAsNotOwner() public {
hoax(victim);
main.radicalizeBoomers{value: unaboomerPrice * 10}(10);
uint256 contractBalance = address(main).balance;
assertEq(contractBalance, unaboomerPrice * 10);
vm.expectRevert("UNAUTHORIZED");
hoax(address(0xd3ad));
main.withdraw();
vm.expectRevert("UNAUTHORIZED");
hoax(address(123));
main.withdraw();
}
// ensure NFT contracts do not accept Ether
function testNoAcceptEther() public {
(bool tbb, ) = payable(address(bomb)).call{value: .5 ether}("");
assertEq(tbb, false);
(bool tbr, ) = payable(address(boomr)).call{value: .5 ether}("");
assertEq(tbr, false);
}
// function testURILogic() public { // Function to receive Ether. msg.data must be empty
// address t = address(1); receive() external payable {}
// boomr.setAliveURI('ipfs://alive/');
// boomr.setDeadURI('ipfs://dead/'); // Fallback function is called when msg.data is not empty
// startHoax(t); fallback() external payable {}
// main.radicalizeBoomers{value: .01 ether}(1);
// assertEq(boomr.tokenURI(0), 'ipfs://alive/0.json');
// main.sendBombs(1);
// assertEq(boomr.tokenURI(0), 'ipfs://dead/0.json');
// }
} }

Loading…
Cancel
Save