diff --git a/src/Unaboomer.sol b/src/Unaboomer.sol index de23585..d06aafc 100644 --- a/src/Unaboomer.sol +++ b/src/Unaboomer.sol @@ -21,6 +21,8 @@ contract Unaboomer is ERC721, Owned { mapping(uint256 => bool) public tokenDead; uint256 public constant MAX_SUPPLY = 10000; + uint256 public constant SURVIVOR_COUNT = 1000; + uint256 public killCount; uint256 public minted; string public aliveURI; string public deadURI; @@ -73,7 +75,10 @@ contract Unaboomer is ERC721, Owned { function kill(uint256 tokenId) external { require(msg.sender == address(main), "invalid minter"); require(tokenId < minted, "invalid token id"); - tokenDead[tokenId] = true; + if (tokenDead[tokenId] == false) { + killCount++; + tokenDead[tokenId] = true; + } } function totalSupply() public view returns (uint256 supply) { diff --git a/src/UnaboomerCommon.sol b/src/UnaboomerCommon.sol index 1b143bd..3be45fc 100644 --- a/src/UnaboomerCommon.sol +++ b/src/UnaboomerCommon.sol @@ -56,12 +56,21 @@ contract UnaboomerCommon is Owned { mailbomb = Mailbomb(_address); } + // ========================================================================= + // Modifiers + // ========================================================================= + + modifier missionCompleted { + require(unaboomer.killCount() <= unaboomer.SURVIVOR_COUNT(), "mission already completed"); + _; + } + // ========================================================================= // Tokens // ========================================================================= /// Radicalize a boomer to become a Unaboomer - function radicalizeBoomer(uint256 _amount) external payable { + function radicalizeBoomers(uint256 _amount) external payable missionCompleted { // check if game halted require(msg.value >= _amount * boomerPrice, "not enough ether"); unaboomer.mint(msg.sender, _amount); @@ -69,25 +78,17 @@ contract UnaboomerCommon is Owned { } /// Assemble additional mailbombs to kill targets - function assembleBomb(uint256 _amount) external payable { + function assembleBombs(uint256 _amount) external payable missionCompleted { // check if game halted require(msg.value >= _amount * bombPrice, "not enough ether"); mailbomb.mint(msg.sender, _amount); } - /// Kill random targets with mail bombs - /// @dev Function returns a boolean depending on if Boomer was already killed or not - i.e. if dud - /// @dev The likelihood of killing a boomer decreases as time goes on - i.e. more duds - function killBoomer(uint256 tokenId) private returns (bool isDud) { - bool dud = unaboomer.tokenDead(tokenId); - unaboomer.kill(tokenId); - return dud; - } - /// Send N bombs to pseudo-random Unaboomer tokenIds to potentially kill them. /// If the Unaboomer is already dead, the bomb is a dud. /// @dev Pick a pseudo-random tokenID from Unaboomer contract and toggle a mapping value - function sendBombs(uint256[] calldata tokenIds) external returns (bool[] memory results) { + /// @dev The likelihood of killing a boomer decreases as time goes on - i.e. more duds + function sendBombs(uint256[] calldata tokenIds) external missionCompleted returns (bool[] memory results) { require(tokenIds.length <= mailbomb.balanceOf(msg.sender)); bool[] memory res = new bool[](tokenIds.length); uint256 boomerSupply = unaboomer.totalSupply(); @@ -95,8 +96,9 @@ contract UnaboomerCommon is Owned { require(mailbomb.ownerOf(tokenIds[i]) == msg.sender, "token not owned"); uint256 randomBoomer = uint256(keccak256(abi.encodePacked(tokenIds[i], block.timestamp, msg.sender))) % boomerSupply; mailbomb.burn(tokenIds[i]); - bool _res = killBoomer(randomBoomer); - res[i] = _res; + bool dud = unaboomer.tokenDead(randomBoomer); + unaboomer.kill(randomBoomer); + res[i] = dud; } return res; } diff --git a/test/Unaboomer.t.sol b/test/Unaboomer.t.sol index f2c87cb..19a7c05 100644 --- a/test/Unaboomer.t.sol +++ b/test/Unaboomer.t.sol @@ -29,7 +29,7 @@ contract UnaboomerTest is Test { function testMint() public { hoax(address(1)); - main.radicalizeBoomer{value: 0.05 ether}(5); + main.radicalizeBoomers{value: 0.05 ether}(5); assertEq(boomr.totalSupply(), 5); assertEq(boomr.tokenDead(1), false); }